HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GABC_IArchive.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) COPYRIGHTYEAR
3  * Side Effects Software Inc. All rights reserved.
4  *
5  * Redistribution and use of Houdini Development Kit samples in source and
6  * binary forms, with or without modification, are permitted provided that the
7  * following conditions are met:
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. The name of Side Effects Software may not be used to endorse or
11  * promote products derived from this software without specific prior
12  * written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17  * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
20  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  *----------------------------------------------------------------------------
26  */
27 
28 #ifndef __GABC_IArchive__
29 #define __GABC_IArchive__
30 
31 #include "GABC_API.h"
32 #include "GABC_IObject.h"
33 #include <SYS/SYS_AtomicInt.h>
34 #include <UT/UT_Lock.h>
35 #include <UT/UT_Set.h>
36 #include <UT/UT_IStream.h>
37 #include <FS/FS_Reader.h>
38 #include <FS/FS_IStreamDevice.h>
39 #include <Alembic/Abc/IArchive.h>
40 #include <SYS/SYS_BoostStreams.h>
41 
42 // Change this when Ogawa is supported
43 #if ALEMBIC_LIBRARY_VERSION >= 10200
44  #define GABC_OGAWA 1
45 #endif
46 
47 // If you're using a thread-safe version of Alembic (thread-safe HDF5 or Ogawa
48 // for example), you can set this define.
49 #define GABC_ALEMBIC_THREADSAFE
50 
51 namespace GABC_NAMESPACE
52 {
53 
54 class GABC_IItem;
55 
56 /// Wrapper around an Alembic archive. This provides thread-safe access to
57 /// Alembic data.
59 {
60 public:
65 
66  /// Test validity
67  bool valid() const { return myArchive.valid(); }
68 
69  /// Error (set on creation)
70  const std::string &error() const { return myError; }
71 
72  /// Access the filename
73  const std::vector<std::string> &filenames() const { return myFileNames; }
74 
75  /// Get the root object
76  GABC_IObject getTop() const;
77 
78  /// Access to the underlying archive
79  const IArchive &archive() const { return myArchive; }
80 
81  bool isOgawa() const { return myIsOgawa; }
82 
83  /// Purge all object references
84  void purgeObjects();
85 
86  /// Close and reopen the archive with the given number of file streams
87  /// (-1 is to use the default)
88  void reopenStream(int num_ogawa_streams = -1);
89 
90  /// @{
91  /// @private
92  /// Called by GABC_IObject to resolve the object
93  void resolveObject(GABC_IObject &obj);
94 
95  /// Called to maintain references to GABC_IItem objects
96  void reference(GABC_IItem *item);
97  void unreference(GABC_IItem *item);
98  /// @}
99 
100  /// @{
101  /// Reference counting
102  void incref() { myRefCount.add(1); }
103  void decref()
104  {
105  if (!myRefCount.add(-1))
106  {
107  closeAndDelete();
108  }
109  }
110  /// @}
111 
112  /// @{
113  /// Open an archive. Please use GABC_Util::open instead
114  /// This method is @b not thread-safe. You must lock around it.
115  /// @private
116  static GABC_IArchivePtr open(const std::vector<std::string> &filenames,
117  int num_ogawa_streams = -1);
118  /// @}
119 
120  /// @{
121  /// Generate a single, user-friendly printable string from a list
122  /// of filenames
123  static std::string filenamesToString(const std::vector<std::string> &filenames);
124  /// @}
125 
126 private:
127  void openArchive(const std::vector<std::string> &paths, int num_streams);
128  void closeAndDelete();
129  /// Access to the file lock - required for non-thread safe HDF5
130  UT_Lock &getLock() const { return *theLock; }
131  friend class GABC_AutoLock;
132 
133  GABC_IArchive(const std::vector<std::string> &filenames,
134  int num_streams = -1);
135 
136  /// Destructor
137  ~GABC_IArchive();
138 
139  // At the current time, HDF5 requires a *global* lock across all files.
140  // Wouldn't it be nice if it could have a per-file lock?
141  static UT_Lock *theLock;
142 
143  bool openStream(const std::string &path,
144  int num_streams = -1);
145  void clearStream();
146 
147  SYS_AtomicInt32 myRefCount;
148  std::vector<std::string> myFileNames;
149  std::string myError;
150  struct gabc_streamentry
151  {
152  gabc_streamentry()
153  : myReader(nullptr), myStreamBuf(nullptr), myStream(nullptr) {}
154  ~gabc_streamentry()
155  {
156  delete myReader;
157  delete myStreamBuf;
158  delete myStream;
159  }
160  gabc_istream *myReader;
161  gabc_streambuf *myStreamBuf;
162  std::istream *myStream;
163  };
164  UT_Array<gabc_streamentry> myStreams;
165  IArchive myArchive;
166  SetType myObjects;
167  bool myPurged;
168  bool myIsOgawa;
169 };
170 
171 static inline void intrusive_ptr_add_ref(GABC_IArchive *i) { i->incref(); }
172 static inline void intrusive_ptr_release(GABC_IArchive *i) { i->decref(); }
173 
174 /// When running with a thread safe Alembic implementation, the fake lock is
175 /// used (since the underlying library is safe).
177 {
178 public:
182  void unlock() {}
183 };
184 /// The true lock is an implementation of a UT_AutoLock which is used when
185 /// locking internal library structures.
187 {
188 public:
190  : myLock(&(arch.getLock()))
191  {
192  if (myLock)
193  myLock->lock();
194  }
196  : myLock(arch ? &(arch->getLock()) : NULL)
197  {
198  if (myLock)
199  myLock->lock();
200  }
202  {
203  if (myLock)
204  myLock->unlock();
205  }
206  void unlock() { myLock->unlock(); myLock = NULL; }
207 private:
208  UT_Lock *myLock;
209 };
210 
211 #if defined(GABC_ALEMBIC_THREADSAFE)
213 #else
215 #endif
216 
217 }
218 
219 #endif
FS_IStreamDeviceBuffer gabc_streambuf
Definition: GABC_IArchive.h:62
GABC_AutoFakeLock(const GABC_IArchivePtr &)
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
GLsizei const GLchar *const * path
Definition: glcorearb.h:3341
#define GABC_NAMESPACE
Definition: GABC_API.h:42
bios::stream_buffer< FS_IStreamDevice > FS_IStreamDeviceBuffer
int open(float queuesize) override
GABC_AutoLock(const GABC_IArchivePtr &arch)
bool valid() const
Test validity.
Definition: GABC_IArchive.h:67
const std::vector< std::string > & filenames() const
Access the filename.
Definition: GABC_IArchive.h:73
const IArchive & archive() const
Access to the underlying archive.
Definition: GABC_IArchive.h:79
GABC_AutoLock(const GABC_IArchive &arch)
#define GABC_API
Definition: GABC_API.h:37
const std::string & error() const
Error (set on creation)
Definition: GABC_IArchive.h:70
GABC_AutoFakeLock(const GABC_IArchive &)
that also have some descendant prim *whose name begins with which in turn has a child named baz where *the predicate and *a name There is also one special expression reference