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  /// Access to archive metadata
83  {
84  return myArchive.getPtr()->getMetaData();
85  }
86 
87  bool isOgawa() const { return myIsOgawa; }
88 
89  /// Purge all object references
90  void purgeObjects();
91 
92  /// Close and reopen the archive with the given number of file streams
93  /// (-1 is to use the default)
94  void reopenStream(int num_ogawa_streams = -1);
95 
96  /// @{
97  /// @private
98  /// Called by GABC_IObject to resolve the object
99  void resolveObject(GABC_IObject &obj);
100 
101  /// Called to maintain references to GABC_IItem objects
102  void reference(GABC_IItem *item);
103  void unreference(GABC_IItem *item);
104  /// @}
105 
106  /// @{
107  /// Reference counting
108  void incref() { myRefCount.add(1); }
109  void decref()
110  {
111  if (!myRefCount.add(-1))
112  {
113  closeAndDelete();
114  }
115  }
116  /// @}
117 
118  /// @{
119  /// Open an archive. Please use GABC_Util::open instead
120  /// This method is @b not thread-safe. You must lock around it.
121  /// @private
122  static GABC_IArchivePtr open(const std::vector<std::string> &filenames,
123  int num_ogawa_streams = -1);
124  /// @}
125 
126  /// @{
127  /// Generate a single, user-friendly printable string from a list
128  /// of filenames
129  static std::string filenamesToString(const std::vector<std::string> &filenames);
130  /// @}
131 
132 private:
133  void openArchive(const std::vector<std::string> &paths, int num_streams);
134  void closeAndDelete();
135  /// Access to the file lock - required for non-thread safe HDF5
136  UT_Lock &getLock() const { return *theLock; }
137  friend class GABC_AutoLock;
138 
139  GABC_IArchive(const std::vector<std::string> &filenames,
140  int num_streams = -1);
141 
142  /// Destructor
143  ~GABC_IArchive();
144 
145  // At the current time, HDF5 requires a *global* lock across all files.
146  // Wouldn't it be nice if it could have a per-file lock?
147  static UT_Lock *theLock;
148 
149  bool openStream(const std::string &path,
150  int num_streams = -1);
151  void clearStream();
152 
153  SYS_AtomicInt32 myRefCount;
154  std::vector<std::string> myFileNames;
155  std::string myError;
156  struct gabc_streamentry
157  {
158  gabc_streamentry()
159  : myReader(nullptr), myStreamBuf(nullptr), myStream(nullptr) {}
160  ~gabc_streamentry()
161  {
162  delete myReader;
163  delete myStreamBuf;
164  delete myStream;
165  }
166  gabc_istream *myReader;
167  gabc_streambuf *myStreamBuf;
168  std::istream *myStream;
169  };
170  UT_Array<gabc_streamentry> myStreams;
171  IArchive myArchive;
172  SetType myObjects;
173  bool myPurged;
174  bool myIsOgawa;
175 };
176 
177 static inline void intrusive_ptr_add_ref(GABC_IArchive *i) { i->incref(); }
178 static inline void intrusive_ptr_release(GABC_IArchive *i) { i->decref(); }
179 
180 /// When running with a thread safe Alembic implementation, the fake lock is
181 /// used (since the underlying library is safe).
183 {
184 public:
188  void unlock() {}
189 };
190 /// The true lock is an implementation of a UT_AutoLock which is used when
191 /// locking internal library structures.
193 {
194 public:
196  : myLock(&(arch.getLock()))
197  {
198  if (myLock)
199  myLock->lock();
200  }
202  : myLock(arch ? &(arch->getLock()) : NULL)
203  {
204  if (myLock)
205  myLock->lock();
206  }
208  {
209  if (myLock)
210  myLock->unlock();
211  }
212  void unlock() { myLock->unlock(); myLock = NULL; }
213 private:
214  UT_Lock *myLock;
215 };
216 
217 #if defined(GABC_ALEMBIC_THREADSAFE)
219 #else
221 #endif
222 
223 }
224 
225 #endif
FS_IStreamDeviceBuffer gabc_streambuf
Definition: GABC_IArchive.h:62
Alembic::Abc::MetaData getMetadata()
Access to archive metadata.
Definition: GABC_IArchive.h:82
GABC_AutoFakeLock(const GABC_IArchivePtr &)
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