HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Queue.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2012-2018 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
29 ///////////////////////////////////////////////////////////////////////////
30 
31 /// @file Queue.h
32 /// @author Peter Cucka
33 
34 #ifndef OPENVDB_IO_QUEUE_HAS_BEEN_INCLUDED
35 #define OPENVDB_IO_QUEUE_HAS_BEEN_INCLUDED
36 
37 #include <openvdb/Types.h>
38 #include <openvdb/Grid.h>
39 #include <algorithm> // for std::copy
40 #include <functional>
41 #include <iterator> // for std::back_inserter
42 #include <memory>
43 
44 
45 namespace openvdb {
47 namespace OPENVDB_VERSION_NAME {
48 namespace io {
49 
50 class Archive;
51 
52 /// @brief Queue for asynchronous output of grids to files or streams
53 ///
54 /// @warning The queue holds shared pointers to grids. It is not safe
55 /// to modify a grid that has been placed in the queue. Instead,
56 /// make a deep copy of the grid (Grid::deepCopy()).
57 ///
58 /// @par Example:
59 /// @code
60 /// #include <openvdb/openvdb.h>
61 /// #include <openvdb/io/Queue.h>
62 /// #include <tbb/concurrent_hash_map.h>
63 /// #include <functional>
64 ///
65 /// using openvdb::io::Queue;
66 ///
67 /// struct MyNotifier
68 /// {
69 /// // Use a concurrent container, because queue callback functions
70 /// // must be thread-safe.
71 /// using FilenameMap = tbb::concurrent_hash_map<Queue::Id, std::string>;
72 /// FilenameMap filenames;
73 ///
74 /// // Callback function that prints the status of a completed task.
75 /// void callback(Queue::Id id, Queue::Status status)
76 /// {
77 /// const bool ok = (status == Queue::SUCCEEDED);
78 /// FilenameMap::accessor acc;
79 /// if (filenames.find(acc, id)) {
80 /// std::cout << (ok ? "wrote " : "failed to write ")
81 /// << acc->second << std::endl;
82 /// filenames.erase(acc);
83 /// }
84 /// }
85 /// };
86 ///
87 /// int main()
88 /// {
89 /// // Construct an object to receive notifications from the queue.
90 /// // The object's lifetime must exceed the queue's.
91 /// MyNotifier notifier;
92 ///
93 /// Queue queue;
94 ///
95 /// // Register the callback() method of the MyNotifier object
96 /// // to receive notifications of completed tasks.
97 /// queue.addNotifier(std::bind(&MyNotifier::callback, &notifier,
98 /// std::placeholders::_1, std::placeholders::_2));
99 ///
100 /// // Queue grids for output (e.g., for each step of a simulation).
101 /// for (int step = 1; step <= 10; ++step) {
102 /// openvdb::FloatGrid::Ptr grid = ...;
103 ///
104 /// std::ostringstream os;
105 /// os << "mygrid." << step << ".vdb";
106 /// const std::string filename = os.str();
107 ///
108 /// Queue::Id id = queue.writeGrid(grid, openvdb::io::File(filename));
109 ///
110 /// // Associate the filename with the ID of the queued task.
111 /// MyNotifier::FilenameMap::accessor acc;
112 /// notifier.filenames.insert(acc, id);
113 /// acc->second = filename;
114 /// }
115 /// }
116 /// @endcode
117 /// Output:
118 /// @code
119 /// wrote mygrid.1.vdb
120 /// wrote mygrid.2.vdb
121 /// wrote mygrid.4.vdb
122 /// wrote mygrid.3.vdb
123 /// ...
124 /// wrote mygrid.10.vdb
125 /// @endcode
126 /// Note that tasks do not necessarily complete in the order in which they were queued.
128 {
129 public:
130  /// Default maximum queue length (see setCapacity())
131  static const Index32 DEFAULT_CAPACITY = 100;
132  /// @brief Default maximum time in seconds to wait to queue a task
133  /// when the queue is full (see setTimeout())
134  static const Index32 DEFAULT_TIMEOUT = 120; // seconds
135 
136  /// ID number of a queued task or of a registered notification callback
137  using Id = Index32;
138 
139  /// Status of a queued task
140  enum Status { UNKNOWN, PENDING, SUCCEEDED, FAILED };
141 
142 
143  /// Construct a queue with the given capacity.
144  explicit Queue(Index32 capacity = DEFAULT_CAPACITY);
145  /// Block until all queued tasks complete (successfully or unsuccessfully).
146  ~Queue();
147 
148  /// @brief Return @c true if the queue is empty.
149  bool empty() const;
150  /// @brief Return the number of tasks currently in the queue.
151  Index32 size() const;
152 
153  /// @brief Return the maximum number of tasks allowed in the queue.
154  /// @details Once the queue has reached its maximum size, adding
155  /// a new task will block until an existing task has executed.
156  Index32 capacity() const;
157  /// Set the maximum number of tasks allowed in the queue.
158  void setCapacity(Index32);
159 
160  /// Return the maximum number of seconds to wait to queue a task when the queue is full.
161  Index32 timeout() const;
162  /// Set the maximum number of seconds to wait to queue a task when the queue is full.
163  void setTimeout(Index32 seconds = DEFAULT_TIMEOUT);
164 
165  /// @brief Return the status of the task with the given ID.
166  /// @note Querying the status of a task that has already completed
167  /// (whether successfully or not) removes the task from the status registry.
168  /// Subsequent queries of its status will return UNKNOWN.
169  Status status(Id) const;
170 
171  using Notifier = std::function<void (Id, Status)>;
172  /// @brief Register a function that will be called with a task's ID
173  /// and status when that task completes, whether successfully or not.
174  /// @return an ID that can be passed to removeNotifier() to deregister the function
175  /// @details When multiple notifiers are registered, they are called
176  /// in the order in which they were registered.
177  /// @warning Notifiers are called from worker threads, so they must be thread-safe
178  /// and their lifetimes must exceed that of the queue. They must also not call,
179  /// directly or indirectly, addNotifier(), removeNotifier() or clearNotifiers(),
180  /// as that can result in a deadlock.
181  Id addNotifier(Notifier);
182  /// Deregister the notifier with the given ID.
183  void removeNotifier(Id);
184  /// Deregister all notifiers.
185  void clearNotifiers();
186 
187  /// @brief Queue a single grid for output to a file or stream.
188  /// @param grid the grid to be serialized
189  /// @param archive the io::File or io::Stream to which to output the grid
190  /// @param fileMetadata optional file-level metadata
191  /// @return an ID with which the status of the queued task can be queried
192  /// @throw RuntimeError if the task cannot be queued within the time limit
193  /// (see setTimeout()) because the queue is full
194  /// @par Example:
195  /// @code
196  /// openvdb::FloatGrid::Ptr grid = ...;
197  ///
198  /// openvdb::io::Queue queue;
199  ///
200  /// // Write the grid to the file mygrid.vdb.
201  /// queue.writeGrid(grid, openvdb::io::File("mygrid.vdb"));
202  ///
203  /// // Stream the grid to a binary string.
204  /// std::ostringstream ostr(std::ios_base::binary);
205  /// queue.writeGrid(grid, openvdb::io::Stream(ostr));
206  /// @endcode
207  Id writeGrid(GridBase::ConstPtr grid, const Archive& archive,
208  const MetaMap& fileMetadata = MetaMap());
209 
210  /// @brief Queue a container of grids for output to a file.
211  /// @param grids any iterable container of grid pointers
212  /// (e.g., a GridPtrVec or GridPtrSet)
213  /// @param archive the io::File or io::Stream to which to output the grids
214  /// @param fileMetadata optional file-level metadata
215  /// @return an ID with which the status of the queued task can be queried
216  /// @throw RuntimeError if the task cannot be queued within the time limit
217  /// (see setTimeout()) because the queue is full
218  /// @par Example:
219  /// @code
220  /// openvdb::FloatGrid::Ptr floatGrid = ...;
221  /// openvdb::BoolGrid::Ptr boolGrid = ...;
222  /// openvdb::GridPtrVec grids;
223  /// grids.push_back(floatGrid);
224  /// grids.push_back(boolGrid);
225  ///
226  /// openvdb::io::Queue queue;
227  ///
228  /// // Write the grids to the file mygrid.vdb.
229  /// queue.write(grids, openvdb::io::File("mygrid.vdb"));
230  ///
231  /// // Stream the grids to a (binary) string.
232  /// std::ostringstream ostr(std::ios_base::binary);
233  /// queue.write(grids, openvdb::io::Stream(ostr));
234  /// @endcode
235  template<typename GridPtrContainer>
236  Id write(const GridPtrContainer& grids, const Archive& archive,
237  const MetaMap& fileMetadata = MetaMap());
238 
239 private:
240  // Disallow copying of instances of this class.
241  Queue(const Queue&);
242  Queue& operator=(const Queue&);
243 
244  Id writeGridVec(const GridCPtrVec&, const Archive&, const MetaMap&);
245 
246  struct Impl;
247  std::unique_ptr<Impl> mImpl;
248 }; // class Queue
249 
250 
251 template<typename GridPtrContainer>
252 inline Queue::Id
253 Queue::write(const GridPtrContainer& container,
254  const Archive& archive, const MetaMap& metadata)
255 {
256  GridCPtrVec grids;
257  std::copy(container.begin(), container.end(), std::back_inserter(grids));
258  return this->writeGridVec(grids, archive, metadata);
259 }
260 
261 // Specialization for vectors of const Grid pointers; no copying necessary
262 template<>
263 inline Queue::Id
264 Queue::write<GridCPtrVec>(const GridCPtrVec& grids,
265  const Archive& archive, const MetaMap& metadata)
266 {
267  return this->writeGridVec(grids, archive, metadata);
268 }
269 
270 } // namespace io
271 } // namespace OPENVDB_VERSION_NAME
272 } // namespace openvdb
273 
274 #endif // OPENVDB_IO_QUEUE_HAS_BEEN_INCLUDED
275 
276 // Copyright (c) 2012-2018 DreamWorks Animation LLC
277 // All rights reserved. This software is distributed under the
278 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
Grid serializer/unserializer.
Definition: Archive.h:59
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:189
Container that maps names (strings) to values of arbitrary types.
Definition: MetaMap.h:46
GLsizeiptr size
Definition: glcorearb.h:663
#define OPENVDB_API
Helper macros for defining library symbol visibility.
Definition: Platform.h:194
GLbitfield GLuint64 timeout
Definition: glcorearb.h:1598
Status
Status of a queued task.
Definition: Queue.h:140
Queue for asynchronous output of grids to files or streams.
Definition: Queue.h:127
Index32 Id
ID number of a queued task or of a registered notification callback.
Definition: Queue.h:137
std::function< void(Id, Status)> Notifier
Definition: Queue.h:171
SharedPtr< const GridBase > ConstPtr
Definition: Grid.h:108
void write(T &out, bool v)
Definition: ImfXdr.h:332
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition: Grid.h:442
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:135
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:253