Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext
truncate (batch)

Schedule a batch of asynchronous file length truncations after preceding operations.

Synopsis
future dispatcher::truncate(const std::vector< future<>> & ops, const std::vector< off_t > & sizes)
Parameters

Type

Concept

Name

Description

const std::vector< future<>> &

ops

A batch of op handles.

const std::vector< off_t > &

sizes

A batch of new lengths.

Returns

A batch of op handles.

Header

#include <boost/afio/v2/afio.hpp>

Complexity

Amortised O(N) to dispatch. Amortised O(N/threadpool) to complete if truncating file lengths is constant time.

Exception Model

Propagates exceptions of any input preconditions with an errored state at the point of dispatch, and throws a std::invalid_argument if any inputs have values which could not possibly be correct. Once a batch of input ops has been verified at the point of entry as not errored, you are guaranteed that the batch is atomically scheduled as a whole, unless a failure to allocate memory occurs.

Example
namespace afio = BOOST_AFIO_V2_NAMESPACE;
namespace asio = BOOST_AFIO_V2_NAMESPACE::asio;

// Set a dispatcher as current for this thread
afio::current_dispatcher_guard h(afio::make_dispatcher().get());

// Schedule an opening of a file called example_file.txt
afio::future<> openfile = afio::async_file(
"example_file.txt", afio::file_flags::create | afio::file_flags::read_write);

// Something a bit surprising for many people is that writing off
// the end of a file in AFIO does NOT extend the file and writes
// which go past the end will simply fail instead. Why not?
// Simple: that's the convention with async file i/o, because
// synchronising multiple processes concurrently adjusting a
// file's length has significant overhead which is wasted if you
// don't need that functionality. Luckily, there is an easy
// workaround: either open a file for append-only access, in which
// case all writes extend the file for you, or else you explicitly
// extend files before writing, like this:
afio::future<> resizedfile = afio::async_truncate(openfile, 12);

// Config a write gather. You could do this of course as a batch
// of writes, but a write gather has optimised host OS support in most
// cases, so it's one syscall instead of many.
std::vector<asio::const_buffer> buffers;
buffers.push_back(asio::const_buffer("He", 2));
buffers.push_back(asio::const_buffer("ll", 2));
buffers.push_back(asio::const_buffer("o ", 2));
buffers.push_back(asio::const_buffer("Wo", 2));
buffers.push_back(asio::const_buffer("rl", 2));
buffers.push_back(asio::const_buffer("d\n", 2));
// Schedule the write gather to offset zero after the resize file
afio::future<> written(afio::async_write(resizedfile, buffers, 0));

// Have the compiler config the exact same write gather as earlier for you
// The compiler assembles an identical sequence of ASIO write gather
// buffers for you
std::vector<std::string> buffers2 = {"He", "ll", "o ", "Wo", "rl", "d\n"};
// Schedule this to occur after the previous write completes
afio::future<> written2(afio::async_write(written, buffers2, 0));

// Schedule making sure the previous batch has definitely reached physical
// storage
// This won't complete until the write is on disc
afio::future<> stored(afio::async_sync(written2));

// Schedule filling this array from the file. Note how convenient std::array
// is and completely replaces C style char buffer[bytes]
std::array<char, 12> buffer;
afio::future<> read(afio::async_read(stored, buffer, 0));

// Schedule the closing and deleting of example_file.txt after the contents read
afio::future<> deletedfile(afio::async_rmfile(afio::async_close(read)));

// Wait until the buffer has been filled, checking all steps for errors
afio::when_all_p(openfile, resizedfile, written, written2, stored, read)
.get(); 1

// There is actually a io_req<std::string> specialisation you
// can use to skip this bit by reading directly into a string ...
std::string contents(buffer.begin(), buffer.end());
std::cout << "Contents of file is '" << contents << "'" << std::endl;

// Check remaining ops for errors
deletedfile.get();

1

waits for file open, resize, write, sync and read to complete, throwing any exceptions encountered


PrevUpHomeNext