Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext
enumerate (batch)

Schedule a batch of asynchronous directory enumerations after preceding operations.

Description

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

Synopsis
future< std::pair< std::vector< directory_entry >, bool > > dispatcher::enumerate(const std::vector< enumerate_req > & reqs)
Parameters

Type

Concept

Name

Description

const std::vector< enumerate_req > &

reqs

A batch of enumeration requests.

Returns

A batch of stl_future vectors of directory entries with boolean returning false if done.

Header

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

Race Guarantees

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.

Complexity

Amortised O(N) to dispatch. Amortised O(N/threadpool*M) to complete where M is the average number of entries in each directory.

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
  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);


PrevUpHomeNext