Home | Libraries | People | FAQ | More |
Schedule a batch of asynchronous directory enumerations after preceding operations.
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 > > dispatcher::enumerate(const std::vector< enumerate_req > & reqs)
Type |
Concept |
Name |
Description |
---|---|---|---|
const std::vector< enumerate_req > & |
reqs |
A batch of enumeration requests. |
A batch of stl_future vectors of directory entries with boolean returning false if done.
#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(N) to dispatch. Amortised O(N/threadpool*M) to complete where M is the average number of entries in each directory.
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.
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);