Loading...
Searching...
No Matches
Queue.h
Go to the documentation of this file.
// Copyright Contributors to the OpenVDB Project
// SPDX-License-Identifier: MPL-2.0
/// @file Queue.h
/// @author Peter Cucka
#ifndef OPENVDB_IO_QUEUE_HAS_BEEN_INCLUDED
#define OPENVDB_IO_QUEUE_HAS_BEEN_INCLUDED
#include <openvdb/Types.h>
#include <openvdb/Grid.h>
#include <algorithm> // for std::copy
#include <functional>
#include <iterator> // for std::back_inserter
#include <memory>
namespace openvdb {
OPENVDB_USE_VERSION_NAMESPACE
namespace OPENVDB_VERSION_NAME {
namespace io {
class Archive;
/// @brief Queue for asynchronous output of grids to files or streams
///
/// @warning The queue holds shared pointers to grids. It is not safe
/// to modify a grid that has been placed in the queue. Instead,
/// make a deep copy of the grid (Grid::deepCopy()).
///
/// @par Example:
/// @code
/// #include <openvdb/openvdb.h>
/// #include <openvdb/io/Queue.h>
/// #include <tbb/concurrent_hash_map.h>
/// #include <functional>
///
/// using openvdb::io::Queue;
///
/// struct MyNotifier
/// {
/// // Use a concurrent container, because queue callback functions
/// // must be thread-safe.
/// using FilenameMap = tbb::concurrent_hash_map<Queue::Id, std::string>;
/// FilenameMap filenames;
///
/// // Callback function that prints the status of a completed task.
/// void callback(Queue::Id id, Queue::Status status)
/// {
/// const bool ok = (status == Queue::SUCCEEDED);
/// FilenameMap::accessor acc;
/// if (filenames.find(acc, id)) {
/// std::cout << (ok ? "wrote " : "failed to write ")
/// << acc->second << std::endl;
/// filenames.erase(acc);
/// }
/// }
/// };
///
/// int main()
/// {
/// // Construct an object to receive notifications from the queue.
/// // The object's lifetime must exceed the queue's.
/// MyNotifier notifier;
///
/// Queue queue;
///
/// // Register the callback() method of the MyNotifier object
/// // to receive notifications of completed tasks.
/// queue.addNotifier(std::bind(&MyNotifier::callback, &notifier,
/// std::placeholders::_1, std::placeholders::_2));
///
/// // Queue grids for output (e.g., for each step of a simulation).
/// for (int step = 1; step <= 10; ++step) {
/// openvdb::FloatGrid::Ptr grid = ...;
///
/// std::ostringstream os;
/// os << "mygrid." << step << ".vdb";
/// const std::string filename = os.str();
///
/// Queue::Id id = queue.writeGrid(grid, openvdb::io::File(filename));
///
/// // Associate the filename with the ID of the queued task.
/// MyNotifier::FilenameMap::accessor acc;
/// notifier.filenames.insert(acc, id);
/// acc->second = filename;
/// }
/// }
/// @endcode
/// Output:
/// @code
/// wrote mygrid.1.vdb
/// wrote mygrid.2.vdb
/// wrote mygrid.4.vdb
/// wrote mygrid.3.vdb
/// ...
/// wrote mygrid.10.vdb
/// @endcode
/// Note that tasks do not necessarily complete in the order in which they were queued.
class OPENVDB_API Queue
{
public:
/// Default maximum queue length (see setCapacity())
static const Index32 DEFAULT_CAPACITY = 100;
/// @brief Default maximum time in seconds to wait to queue a task
/// when the queue is full (see setTimeout())
static const Index32 DEFAULT_TIMEOUT = 120; // seconds
/// ID number of a queued task or of a registered notification callback
using Id = Index32;
/// Status of a queued task
enum Status { UNKNOWN, PENDING, SUCCEEDED, FAILED };
/// Construct a queue with the given capacity.
explicit Queue(Index32 capacity = DEFAULT_CAPACITY);
/// Block until all queued tasks complete (successfully or unsuccessfully).
~Queue();
/// @brief Return @c true if the queue is empty.
bool empty() const;
/// @brief Return the number of tasks currently in the queue.
Index32 size() const;
/// @brief Return the maximum number of tasks allowed in the queue.
/// @details Once the queue has reached its maximum size, adding
/// a new task will block until an existing task has executed.
Index32 capacity() const;
/// Set the maximum number of tasks allowed in the queue.
void setCapacity(Index32);
/// Return the maximum number of seconds to wait to queue a task when the queue is full.
Index32 timeout() const;
/// Set the maximum number of seconds to wait to queue a task when the queue is full.
void setTimeout(Index32 seconds = DEFAULT_TIMEOUT);
/// @brief Return the status of the task with the given ID.
/// @note Querying the status of a task that has already completed
/// (whether successfully or not) removes the task from the status registry.
/// Subsequent queries of its status will return UNKNOWN.
Status status(Id) const;
using Notifier = std::function<void (Id, Status)>;
/// @brief Register a function that will be called with a task's ID
/// and status when that task completes, whether successfully or not.
/// @return an ID that can be passed to removeNotifier() to deregister the function
/// @details When multiple notifiers are registered, they are called
/// in the order in which they were registered.
/// @warning Notifiers are called from worker threads, so they must be thread-safe
/// and their lifetimes must exceed that of the queue. They must also not call,
/// directly or indirectly, addNotifier(), removeNotifier() or clearNotifiers(),
/// as that can result in a deadlock.
Id addNotifier(Notifier);
/// Deregister the notifier with the given ID.
void removeNotifier(Id);
/// Deregister all notifiers.
void clearNotifiers();
/// @brief Queue a single grid for output to a file or stream.
/// @param grid the grid to be serialized
/// @param archive the io::File or io::Stream to which to output the grid
/// @param fileMetadata optional file-level metadata
/// @return an ID with which the status of the queued task can be queried
/// @throw RuntimeError if the task cannot be queued within the time limit
/// (see setTimeout()) because the queue is full
/// @par Example:
/// @code
/// openvdb::FloatGrid::Ptr grid = ...;
///
/// openvdb::io::Queue queue;
///
/// // Write the grid to the file mygrid.vdb.
/// queue.writeGrid(grid, openvdb::io::File("mygrid.vdb"));
///
/// // Stream the grid to a binary string.
/// std::ostringstream ostr(std::ios_base::binary);
/// queue.writeGrid(grid, openvdb::io::Stream(ostr));
/// @endcode
Id writeGrid(GridBase::ConstPtr grid, const Archive& archive,
const MetaMap& fileMetadata = MetaMap());
/// @brief Queue a container of grids for output to a file.
/// @param grids any iterable container of grid pointers
/// (e.g., a GridPtrVec or GridPtrSet)
/// @param archive the io::File or io::Stream to which to output the grids
/// @param fileMetadata optional file-level metadata
/// @return an ID with which the status of the queued task can be queried
/// @throw RuntimeError if the task cannot be queued within the time limit
/// (see setTimeout()) because the queue is full
/// @par Example:
/// @code
/// openvdb::FloatGrid::Ptr floatGrid = ...;
/// openvdb::BoolGrid::Ptr boolGrid = ...;
/// openvdb::GridPtrVec grids;
/// grids.push_back(floatGrid);
/// grids.push_back(boolGrid);
///
/// openvdb::io::Queue queue;
///
/// // Write the grids to the file mygrid.vdb.
/// queue.write(grids, openvdb::io::File("mygrid.vdb"));
///
/// // Stream the grids to a (binary) string.
/// std::ostringstream ostr(std::ios_base::binary);
/// queue.write(grids, openvdb::io::Stream(ostr));
/// @endcode
template<typename GridPtrContainer>
Id write(const GridPtrContainer& grids, const Archive& archive,
const MetaMap& fileMetadata = MetaMap());
private:
// Disallow copying of instances of this class.
Queue(const Queue&);
Queue& operator=(const Queue&);
Id writeGridVec(const GridCPtrVec&, const Archive&, const MetaMap&);
struct Impl;
std::unique_ptr<Impl> mImpl;
}; // class Queue
template<typename GridPtrContainer>
inline Queue::Id
Queue::write(const GridPtrContainer& container,
const Archive& archive, const MetaMap& metadata)
{
GridCPtrVec grids;
std::copy(container.begin(), container.end(), std::back_inserter(grids));
return this->writeGridVec(grids, archive, metadata);
}
// Specialization for vectors of const Grid pointers; no copying necessary
template<>
inline Queue::Id
Queue::write<GridCPtrVec>(const GridCPtrVec& grids,
const Archive& archive, const MetaMap& metadata)
{
return this->writeGridVec(grids, archive, metadata);
}
} // namespace io
} // namespace OPENVDB_VERSION_NAME
} // namespace openvdb
#endif // OPENVDB_IO_QUEUE_HAS_BEEN_INCLUDED
Grid.h
OPENVDB_API
#define OPENVDB_API
Definition Platform.h:251
openvdb::v10_0::GridBase::ConstPtr
SharedPtr< const GridBase > ConstPtr
Definition Grid.h:81
openvdb::v10_0::MetaMap
Container that maps names (strings) to values of arbitrary types.
Definition MetaMap.h:20
openvdb::v10_0::io::Archive
Grid serializer/unserializer.
Definition Archive.h:33
openvdb::v10_0::io::Queue::DEFAULT_CAPACITY
static const Index32 DEFAULT_CAPACITY
Default maximum queue length (see setCapacity()).
Definition Queue.h:104
openvdb::v10_0::io::Queue::capacity
Index32 capacity() const
Return the maximum number of tasks allowed in the queue.
openvdb::v10_0::io::Queue::writeGrid
Id writeGrid(GridBase::ConstPtr grid, const Archive &archive, const MetaMap &fileMetadata=MetaMap())
Queue a single grid for output to a file or stream.
openvdb::v10_0::io::Queue::clearNotifiers
void clearNotifiers()
Deregister all notifiers.
openvdb::v10_0::io::Queue::~Queue
~Queue()
Block until all queued tasks complete (successfully or unsuccessfully).
openvdb::v10_0::io::Queue::size
Index32 size() const
Return the number of tasks currently in the queue.
openvdb::v10_0::io::Queue::setTimeout
void setTimeout(Index32 seconds=DEFAULT_TIMEOUT)
Set the maximum number of seconds to wait to queue a task when the queue is full.
openvdb::v10_0::io::Queue::removeNotifier
void removeNotifier(Id)
Deregister the notifier with the given ID.
openvdb::v10_0::io::Queue::addNotifier
Id addNotifier(Notifier)
Register a function that will be called with a task's ID and status when that task completes,...
openvdb::v10_0::io::Queue::empty
bool empty() const
Return true if the queue is empty.
openvdb::v10_0::io::Queue::Status
Status
Status of a queued task.
Definition Queue.h:113
openvdb::v10_0::io::Queue::PENDING
@ PENDING
Definition Queue.h:113
openvdb::v10_0::io::Queue::UNKNOWN
@ UNKNOWN
Definition Queue.h:113
openvdb::v10_0::io::Queue::SUCCEEDED
@ SUCCEEDED
Definition Queue.h:113
openvdb::v10_0::io::Queue::FAILED
@ FAILED
Definition Queue.h:113
openvdb::v10_0::io::Queue::DEFAULT_TIMEOUT
static const Index32 DEFAULT_TIMEOUT
Default maximum time in seconds to wait to queue a task when the queue is full (see setTimeout()).
Definition Queue.h:107
openvdb::v10_0::io::Queue::write
Id write(const GridPtrContainer &grids, const Archive &archive, const MetaMap &fileMetadata=MetaMap())
Queue a container of grids for output to a file.
Definition Queue.h:226
openvdb::v10_0::io::Queue::setCapacity
void setCapacity(Index32)
Set the maximum number of tasks allowed in the queue.
openvdb::v10_0::io::Queue::Queue
Queue(Index32 capacity=DEFAULT_CAPACITY)
Construct a queue with the given capacity.
openvdb::v10_0::io::Queue::timeout
Index32 timeout() const
Return the maximum number of seconds to wait to queue a task when the queue is full.
openvdb::v10_0::io::Queue::Notifier
std::function< void(Id, Status)> Notifier
Definition Queue.h:144
openvdb::v10_0::io::Queue::Id
Index32 Id
ID number of a queued task or of a registered notification callback.
Definition Queue.h:110
openvdb::v10_0::io::Queue::status
Status status(Id) const
Return the status of the task with the given ID.
openvdb::v10_0::Index32
uint32_t Index32
Definition Types.h:52
openvdb::v10_0::GridCPtrVec
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition Grid.h:513
openvdb
Definition Exceptions.h:13
Types.h
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:212