Home | Libraries | People | FAQ | More |
Asynchronous directory enumeration after a preceding operation.
By default dir() returns shared handles i.e. dir( foo) and dir( foo)
will return the exact same handle, and therefore enumerating not all
of the entries at once is a race condition. The solution is to either
set maxitems to a value large enough to guarantee a directory will be
enumerated in a single shot, or to open a separate directory handle using
the file_flags::unique_directory_handle flag. Note that setting maxitems=1
will often cause a buffer space exhaustion, causing a second syscall
with an enlarged buffer. This is because AFIO cannot know if the allocated
buffer can hold all of the filename being retrieved, so it may have to
retry. Put another way, setting maxitems=1 will give you the worst performance
possible, whereas maxitems=2 will probably only return one item most
of the time. Related types:
,
enumerate_req
,
directory_entry
stat_t
future<std::pair<std::vector<directory_entry>, bool> > async_enumerate(future<> _precondition, metadata_flags _metadata, size_t _maxitems = 2, bool _restart = true, path _glob = path(), enumerate_req::filter _filtering = enumerate_req::filter::fastdeleted)
Type |
Concept |
Name |
Description |
---|---|---|---|
future<> |
_precondition |
The precondition to use. |
|
metadata_flags |
_metadata |
The metadata to prefetch for each item enumerated. AFIO may fetch more metadata than requested if it is cost free. |
|
size_t |
_maxitems |
The maximum number of items to return in this request. Note that setting to one will often invoke two syscalls. |
|
bool |
_restart |
Restarts the enumeration for this open directory handle. |
|
path |
_glob |
An optional shell glob by which to filter the items returned. Done kernel side on Windows, user side on POSIX. |
|
enumerate_req::filter |
_filtering |
Any filtering you want AFIO to do for you. |
A future<std::pair<std::vector<
directory_entry
>,
bool>>
#include <boost/afio/v2/afio.hpp>
Operating system | Race guarantees under a changing file system |
---|---|
FreeBSD, Linux, OS X | Race free per batch of up to maxitems for ino and type only. Remember that many filing systems will recycle inodes such that a created file will get the inode of a just deleted file, so comparing inodes for equivalence to a direntry() won't help you. |
Windows | Race free per batch of up to maxitems for ino, type, atim, mtim, ctim, size, allocated, birthtim, sparse, compressed. |
Amortised O(1) to dispatch. Amortised O(M) to complete where M is the average number of entries in each directory.
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.
boost::afio::current_dispatcher_guard h(boost::afio::make_dispatcher().get()); // Schedule an opening of the root directory boost::afio::future<> rootdir(boost::afio::async_dir("/")); std::pair<std::vector<boost::afio::directory_entry>, bool> list; // This is used to reset the enumeration to the start bool restart = true; do { // Schedule an enumeration of an open directory handle boost::afio::future<std::pair<std::vector<boost::afio::directory_entry>, bool>> enumeration(boost::afio::async_enumerate( rootdir, /* This is the maximum entries to enumerate. Note the use of compatibility_maximum() which is the same value your libc uses. The problem with smaller enumerations is that the directory contents can change out from underneath you more frequently. */ boost::afio::directory_entry::compatibility_maximum(), /* True if to reset enumeration */ restart)); restart = false; // People using AFIO often forget that futures can be waited // on normally without needing to wait on the op handle list = enumeration.get(); for(boost::afio::directory_entry &i : list.first) { #ifdef WIN32 std::wcout << i.name(); #else /*_ defined(WIN32) _*/ std::cout << i.name(); #endif /*_ defined(WIN32) _*/ std::cout << " type " << static_cast<int>(i.st_type()) << std::endl; } } while(list.second);