Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext
truncate (throwing)

Synchronous file length truncation after a preceding operation.

Synopsis
void truncate(future<> _precondition, off_t newsize)
Parameters

Type

Concept

Name

Description

future<>

_precondition

The precondition to use.

off_t

newsize

The new size for the file.

Header

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

Complexity

Amortised O(1) to dispatch. Amortised O(1) to complete if truncating file lengths is constant time.

Exception Model

Propagates the exception of any input precondition 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. Note that error code returning functions may still throw exceptions e.g. failure to allocate memory.

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