OLD | NEW |
1 //-***************************************************************************** | 1 //-***************************************************************************** |
2 // | 2 // |
3 // Copyright (c) 2009-2010, | 3 // Copyright (c) 2009-2010, |
4 // Sony Pictures Imageworks Inc. and | 4 // Sony Pictures Imageworks Inc. and |
5 // Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd. | 5 // Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd. |
6 // | 6 // |
7 // All rights reserved. | 7 // All rights reserved. |
8 // | 8 // |
9 // Redistribution and use in source and binary forms, with or without | 9 // Redistribution and use in source and binary forms, with or without |
10 // modification, are permitted provided that the following conditions are | 10 // modification, are permitted provided that the following conditions are |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 // we ignore it everything else | 86 // we ignore it everything else |
87 std::string attrName( iAttrName ); | 87 std::string attrName( iAttrName ); |
88 size_t attrNameLen = attrName.size(); | 88 size_t attrNameLen = attrName.size(); |
89 if ( attrNameLen < 6 ) | 89 if ( attrNameLen < 6 ) |
90 { | 90 { |
91 // An error | 91 // An error |
92 ABCA_THROW( "Invalid attribute in compound property group: " | 92 ABCA_THROW( "Invalid attribute in compound property group: " |
93 << attrName | 93 << attrName |
94 << std::endl | 94 << std::endl |
95 << "... has no suffix" ); | 95 << "... has no suffix" ); |
96 | 96 |
97 // Continue iterating. | 97 // Continue iterating. |
98 // return 0; | 98 // return 0; |
99 } | 99 } |
100 | 100 |
101 // Last 5 characters. | 101 // Last 5 characters. |
102 std::string suffix( attrName, attrNameLen-5 ); | 102 std::string suffix( attrName, attrNameLen-5 ); |
103 if ( suffix == ".info" ) | 103 if ( suffix == ".info" ) |
104 { | 104 { |
105 std::string propertyName( attrName, 0, attrNameLen-5 ); | 105 std::string propertyName( attrName, 0, attrNameLen-5 ); |
106 visitor->createNewProperty( propertyName ); | 106 visitor->createNewProperty( propertyName ); |
107 } | 107 } |
108 | 108 |
109 return 0; | 109 return 0; |
110 } | 110 } |
111 | 111 |
112 //-***************************************************************************** | 112 //-***************************************************************************** |
113 //-***************************************************************************** | 113 //-***************************************************************************** |
114 // CLASS | 114 // CLASS |
115 //-***************************************************************************** | 115 //-***************************************************************************** |
116 //-***************************************************************************** | 116 //-***************************************************************************** |
117 | 117 |
118 //-***************************************************************************** | 118 //-***************************************************************************** |
119 BaseCprImpl::BaseCprImpl( hid_t iParentGroup, | 119 BaseCprImpl::BaseCprImpl( hid_t iParentGroup, |
120 const std::string &iName ) | 120 const std::string &iName ) |
121 : m_group( -1 ) | 121 : m_group( -1 ) |
| 122 , m_subPropertyMutexes( NULL ) |
122 { | 123 { |
123 ABCA_ASSERT( iParentGroup >= 0, "invalid parent group" ); | 124 ABCA_ASSERT( iParentGroup >= 0, "invalid parent group" ); |
124 | 125 |
125 // Object ptr is left NULL. | 126 // Object ptr is left NULL. |
126 // CprImpl will set it explicitly, and TopCprImpl leaves it NULL. | 127 // CprImpl will set it explicitly, and TopCprImpl leaves it NULL. |
127 | 128 |
128 // If our group exists, open it. If it does not, this is not a problem! | 129 // If our group exists, open it. If it does not, this is not a problem! |
129 // It just means we don't have any subproperties. We essentially are just | 130 // It just means we don't have any subproperties. We essentially are just |
130 // some floating metadata, at that point. | 131 // some floating metadata, at that point. |
131 if ( !GroupExists( iParentGroup, iName ) ) | 132 if ( !GroupExists( iParentGroup, iName ) ) |
132 { | 133 { |
133 // No group. It's okay! | 134 // No group. It's okay! |
134 // Just return - it means we have no subprops! | 135 // Just return - it means we have no subprops! |
135 return; | 136 return; |
136 } | 137 } |
137 | 138 |
138 // Okay now open the group. | 139 // Okay now open the group. |
139 m_group = H5Gopen2( iParentGroup, iName.c_str(), H5P_DEFAULT ); | 140 m_group = H5Gopen2( iParentGroup, iName.c_str(), H5P_DEFAULT ); |
140 ABCA_ASSERT( m_group >= 0, | 141 ABCA_ASSERT( m_group >= 0, |
141 "Could not open compound property group named: " | 142 "Could not open compound property group named: " |
142 << iName << ", H5Gopen2 failed" ); | 143 << iName << ", H5Gopen2 failed" ); |
143 | 144 |
144 // Do the visiting to gather property names. | 145 // Do the visiting to gather property names. |
145 CprAttrVisitor visitor; | 146 CprAttrVisitor visitor; |
146 try | 147 try |
147 { | 148 { |
148 herr_t status = H5Aiterate2( m_group, | 149 herr_t status = H5Aiterate2( m_group, |
149 H5_INDEX_CRT_ORDER, | 150 H5_INDEX_CRT_ORDER, |
150 H5_ITER_INC, | 151 H5_ITER_INC, |
151 NULL, | 152 NULL, |
152 CprVisitAllAttrsCB, | 153 CprVisitAllAttrsCB, |
153 ( void * )&visitor ); | 154 ( void * )&visitor ); |
154 | 155 |
155 ABCA_ASSERT( status >= 0, | 156 ABCA_ASSERT( status >= 0, |
156 "CprImpl::init(): H5Aiterate failed" ); | 157 "CprImpl::init(): H5Aiterate failed" ); |
157 } | 158 } |
158 catch ( std::exception & exc ) | 159 catch ( std::exception & exc ) |
159 { | 160 { |
160 ABCA_THROW( "Could not attr iterate property group named: " | 161 ABCA_THROW( "Could not attr iterate property group named: " |
161 << iName << ", reason: " << exc.what() ); | 162 << iName << ", reason: " << exc.what() ); |
162 } | 163 } |
163 catch ( ... ) | 164 catch ( ... ) |
164 { | 165 { |
165 ABCA_THROW( "Could not attr iterate property group named: " | 166 ABCA_THROW( "Could not attr iterate property group named: " |
166 << iName << ", unknown reason" ); | 167 << iName << ", unknown reason" ); |
167 } | 168 } |
168 | 169 |
169 size_t index = 0; | 170 size_t index = 0; |
170 m_propertyHeaders.resize(visitor.properties.size()); | 171 m_propertyHeaders.resize(visitor.properties.size()); |
171 | 172 |
172 // For each property name, read the various pieces of information | 173 // For each property name, read the various pieces of information |
173 for ( std::vector<std::string>::iterator siter = visitor.properties.begin(); | 174 for ( std::vector<std::string>::iterator siter = visitor.properties.begin(); |
174 siter != visitor.properties.end(); ++siter, ++index ) | 175 siter != visitor.properties.end(); ++siter, ++index ) |
175 { | 176 { |
176 m_subProperties[(*siter)] = index; | 177 m_subProperties[(*siter)] = index; |
177 m_propertyHeaders[index].name = (*siter); | 178 m_propertyHeaders[index].name = (*siter); |
178 m_propertyHeaders[index].numSamples = 0; | 179 m_propertyHeaders[index].numSamples = 0; |
179 m_propertyHeaders[index].firstChangedIndex = 0; | 180 m_propertyHeaders[index].firstChangedIndex = 0; |
180 m_propertyHeaders[index].lastChangedIndex = 0; | 181 m_propertyHeaders[index].lastChangedIndex = 0; |
181 m_propertyHeaders[index].isScalarLike = false; | 182 m_propertyHeaders[index].isScalarLike = false; |
182 } | 183 } |
| 184 m_subPropertyMutexes = new boost::mutex [ visitor.properties.size() ]; |
183 } | 185 } |
184 | 186 |
185 //-***************************************************************************** | 187 //-***************************************************************************** |
186 // Destructor is at the end, so that this file has a logical ordering that | 188 // Destructor is at the end, so that this file has a logical ordering that |
187 // matches the order of operations (create, get children, destroy) | 189 // matches the order of operations (create, get children, destroy) |
188 //-***************************************************************************** | 190 //-***************************************************************************** |
189 | 191 |
190 //-***************************************************************************** | 192 //-***************************************************************************** |
191 AbcA::ObjectReaderPtr BaseCprImpl::getObject() | 193 AbcA::ObjectReaderPtr BaseCprImpl::getObject() |
192 { | 194 { |
| 195 // m_object is assinged once, in CprImpl ctor, so multithread safe. |
193 ABCA_ASSERT( m_object, "Invalid object in BaseCprImpl::getObject()" ); | 196 ABCA_ASSERT( m_object, "Invalid object in BaseCprImpl::getObject()" ); |
194 return m_object; | 197 return m_object; |
195 } | 198 } |
196 | 199 |
197 //-***************************************************************************** | 200 //-***************************************************************************** |
198 size_t BaseCprImpl::getNumProperties() | 201 size_t BaseCprImpl::getNumProperties() |
199 { | 202 { |
| 203 // fixed length and resize called in ctor, so multithread safe. |
200 return m_propertyHeaders.size(); | 204 return m_propertyHeaders.size(); |
201 } | 205 } |
202 | 206 |
203 //-***************************************************************************** | 207 //-***************************************************************************** |
204 const AbcA::PropertyHeader &BaseCprImpl::getPropertyHeader( size_t i ) | 208 const AbcA::PropertyHeader &BaseCprImpl::getPropertyHeader( size_t i ) |
205 { | 209 { |
206 if ( i < 0 || i > m_propertyHeaders.size() ) | 210 if ( i < 0 || i > m_propertyHeaders.size() ) |
207 { | 211 { |
208 ABCA_THROW( "Out of range index in " | 212 ABCA_THROW( "Out of range index in " |
209 << "CprImpl::getPropertyHeader: " << i ); | 213 << "CprImpl::getPropertyHeader: " << i ); |
210 } | 214 } |
| 215 boost::mutex::scoped_lock l( m_subPropertyMutexes[i] ); |
211 | 216 |
212 // read the property header stuff if we haven't yet | 217 // read the property header stuff if we haven't yet |
213 if (m_propertyHeaders[i].header == NULL) | 218 if ( m_propertyHeaders[i].header == NULL ) |
214 { | 219 { |
215 uint32_t tsid = 0; | 220 uint32_t tsid = 0; |
216 | 221 |
217 PropertyHeaderPtr iPtr( new AbcA::PropertyHeader() ); | 222 PropertyHeaderPtr iPtr( new AbcA::PropertyHeader() ); |
218 ReadPropertyHeader( m_group, m_propertyHeaders[i].name, *iPtr, | 223 ReadPropertyHeader( m_group, m_propertyHeaders[i].name, *iPtr, |
219 m_propertyHeaders[i].isScalarLike, | 224 m_propertyHeaders[i].isScalarLike, |
220 m_propertyHeaders[i].numSamples, | 225 m_propertyHeaders[i].numSamples, |
221 m_propertyHeaders[i].firstChangedIndex, | 226 m_propertyHeaders[i].firstChangedIndex, |
222 m_propertyHeaders[i].lastChangedIndex, tsid ); | 227 m_propertyHeaders[i].lastChangedIndex, tsid ); |
223 | 228 |
224 if ( iPtr->isSimple() ) | 229 if ( iPtr->isSimple() ) |
225 { | 230 { |
226 AbcA::TimeSamplingPtr tsPtr = | 231 AbcA::TimeSamplingPtr tsPtr = |
227 getObject()->getArchive()->getTimeSampling( tsid ); | 232 getObject()->getArchive()->getTimeSampling( tsid ); |
228 | 233 |
229 iPtr->setTimeSampling(tsPtr); | 234 iPtr->setTimeSampling(tsPtr); |
230 } | 235 } |
231 | 236 |
232 m_propertyHeaders[i].header = iPtr; | 237 m_propertyHeaders[i].header = iPtr; |
233 | 238 |
234 // don't need name anymore (it's in the header) | 239 // don't need name anymore (it's in the header) |
235 m_propertyHeaders[i].name = ""; | 240 m_propertyHeaders[i].name = ""; |
236 } | 241 } |
237 | 242 |
238 return *(m_propertyHeaders[i].header); | 243 return *(m_propertyHeaders[i].header); |
239 } | 244 } |
240 | 245 |
241 //-***************************************************************************** | 246 //-***************************************************************************** |
242 const AbcA::PropertyHeader * | 247 const AbcA::PropertyHeader * |
243 BaseCprImpl::getPropertyHeader( const std::string &iName ) | 248 BaseCprImpl::getPropertyHeader( const std::string &iName ) |
244 { | 249 { |
| 250 // map of names to indexes filled by ctor (CprAttrVistor), |
| 251 // so multithread safe. |
245 SubPropertiesMap::iterator fiter = m_subProperties.find( iName ); | 252 SubPropertiesMap::iterator fiter = m_subProperties.find( iName ); |
246 if ( fiter == m_subProperties.end() ) | 253 if ( fiter == m_subProperties.end() ) |
247 { | 254 { |
248 return NULL; | 255 return NULL; |
249 } | 256 } |
250 | 257 |
251 return &(getPropertyHeader(fiter->second)); | 258 return &(getPropertyHeader(fiter->second)); |
252 } | 259 } |
253 | 260 |
254 //-***************************************************************************** | 261 //-***************************************************************************** |
255 AbcA::ScalarPropertyReaderPtr | 262 AbcA::ScalarPropertyReaderPtr |
256 BaseCprImpl::getScalarProperty( const std::string &iName ) | 263 BaseCprImpl::getScalarProperty( const std::string &iName ) |
257 { | 264 { |
| 265 // map of names to indexes filled by ctor (CprAttrVistor), |
| 266 // so multithread safe. |
258 SubPropertiesMap::iterator fiter = m_subProperties.find( iName ); | 267 SubPropertiesMap::iterator fiter = m_subProperties.find( iName ); |
259 if ( fiter == m_subProperties.end() ) | 268 if ( fiter == m_subProperties.end() ) |
260 { | 269 { |
261 return AbcA::ScalarPropertyReaderPtr(); | 270 return AbcA::ScalarPropertyReaderPtr(); |
262 } | 271 } |
263 | 272 |
264 // make sure we've read the header | 273 // make sure we've read the header |
265 getPropertyHeader(fiter->second); | 274 getPropertyHeader(fiter->second); |
266 SubProperty & sub = m_propertyHeaders[fiter->second]; | 275 SubProperty & sub = m_propertyHeaders[fiter->second]; |
267 | 276 |
268 if ( !(sub.header->isScalar()) ) | 277 if ( !(sub.header->isScalar()) ) |
269 { | 278 { |
270 ABCA_THROW( "Tried to read a scalar property from a non-scalar: " | 279 ABCA_THROW( "Tried to read a scalar property from a non-scalar: " |
271 << iName << ", type: " | 280 << iName << ", type: " |
272 << sub.header->getPropertyType() ); | 281 << sub.header->getPropertyType() ); |
273 } | 282 } |
274 | 283 |
275 AbcA::BasePropertyReaderPtr bptr; | 284 AbcA::BasePropertyReaderPtr bptr = sub.made.lock(); |
276 if ( sub.made.expired() ) | 285 if ( ! bptr ) |
277 { | 286 { |
278 // Make a new one. | 287 // Make a new one. |
279 bptr.reset( new SprImpl( this->asCompoundPtr(), m_group, sub.header, | 288 bptr.reset( new SprImpl( this->asCompoundPtr(), m_group, sub.header, |
280 sub.numSamples, sub.firstChangedIndex, sub.lastChangedIndex ) ); | 289 sub.numSamples, sub.firstChangedIndex, |
| 290 sub.lastChangedIndex ) ); |
281 sub.made = bptr; | 291 sub.made = bptr; |
282 } | 292 } |
283 else | |
284 { | |
285 bptr = sub.made.lock(); | |
286 } | |
287 | 293 |
288 AbcA::ScalarPropertyReaderPtr ret = | 294 AbcA::ScalarPropertyReaderPtr ret = |
289 boost::dynamic_pointer_cast<AbcA::ScalarPropertyReader, | 295 boost::dynamic_pointer_cast<AbcA::ScalarPropertyReader, |
290 AbcA::BasePropertyReader>( bptr ); | 296 AbcA::BasePropertyReader>( bptr ); |
291 return ret; | 297 return ret; |
292 } | 298 } |
293 | 299 |
294 //-***************************************************************************** | 300 //-***************************************************************************** |
295 AbcA::ArrayPropertyReaderPtr | 301 AbcA::ArrayPropertyReaderPtr |
296 BaseCprImpl::getArrayProperty( const std::string &iName ) | 302 BaseCprImpl::getArrayProperty( const std::string &iName ) |
297 { | 303 { |
| 304 // map of names to indexes filled by ctor (CprAttrVistor), |
| 305 // so multithread safe. |
298 SubPropertiesMap::iterator fiter = m_subProperties.find( iName ); | 306 SubPropertiesMap::iterator fiter = m_subProperties.find( iName ); |
299 if ( fiter == m_subProperties.end() ) | 307 if ( fiter == m_subProperties.end() ) |
300 { | 308 { |
301 return AbcA::ArrayPropertyReaderPtr(); | 309 return AbcA::ArrayPropertyReaderPtr(); |
302 } | 310 } |
303 | 311 |
304 // make sure we've read the header | 312 // make sure we've read the header |
305 getPropertyHeader(fiter->second); | 313 getPropertyHeader(fiter->second); |
306 SubProperty & sub = m_propertyHeaders[fiter->second]; | 314 SubProperty & sub = m_propertyHeaders[fiter->second]; |
307 | 315 |
308 if ( !(sub.header->isArray()) ) | 316 if ( !(sub.header->isArray()) ) |
309 { | 317 { |
310 ABCA_THROW( "Tried to read an array property from a non-array: " | 318 ABCA_THROW( "Tried to read an array property from a non-array: " |
311 << iName << ", type: " | 319 << iName << ", type: " |
312 << sub.header->getPropertyType() ); | 320 << sub.header->getPropertyType() ); |
313 } | 321 } |
314 | 322 |
315 AbcA::BasePropertyReaderPtr bptr; | 323 AbcA::BasePropertyReaderPtr bptr = sub.made.lock(); |
316 if ( sub.made.expired() ) | 324 if ( ! bptr ) |
317 { | 325 { |
318 // Make a new one. | 326 // Make a new one. |
319 bptr.reset( new AprImpl( this->asCompoundPtr(), m_group, sub.header, | 327 bptr.reset( new AprImpl( this->asCompoundPtr(), m_group, sub.header, |
320 sub.isScalarLike, sub.numSamples, sub.firstChangedIndex, | 328 sub.isScalarLike, sub.numSamples, |
321 sub.lastChangedIndex ) ); | 329 sub.firstChangedIndex, |
| 330 sub.lastChangedIndex ) ); |
322 sub.made = bptr; | 331 sub.made = bptr; |
323 } | 332 } |
324 else | |
325 { | |
326 bptr = sub.made.lock(); | |
327 } | |
328 | 333 |
329 AbcA::ArrayPropertyReaderPtr ret = | 334 AbcA::ArrayPropertyReaderPtr ret = |
330 boost::dynamic_pointer_cast<AbcA::ArrayPropertyReader, | 335 boost::dynamic_pointer_cast<AbcA::ArrayPropertyReader, |
331 AbcA::BasePropertyReader>( bptr ); | 336 AbcA::BasePropertyReader>( bptr ); |
332 return ret; | 337 return ret; |
333 } | 338 } |
334 | 339 |
335 //-***************************************************************************** | 340 //-***************************************************************************** |
336 AbcA::CompoundPropertyReaderPtr | 341 AbcA::CompoundPropertyReaderPtr |
337 BaseCprImpl::getCompoundProperty( const std::string &iName ) | 342 BaseCprImpl::getCompoundProperty( const std::string &iName ) |
338 { | 343 { |
| 344 // map of names to indexes filled by ctor (CprAttrVistor), |
| 345 // so multithread safe. |
339 SubPropertiesMap::iterator fiter = m_subProperties.find( iName ); | 346 SubPropertiesMap::iterator fiter = m_subProperties.find( iName ); |
340 if ( fiter == m_subProperties.end() ) | 347 if ( fiter == m_subProperties.end() ) |
341 { | 348 { |
342 return AbcA::CompoundPropertyReaderPtr(); | 349 return AbcA::CompoundPropertyReaderPtr(); |
343 } | 350 } |
344 | 351 |
345 // make sure we've read the header | 352 // make sure we've read the header |
346 getPropertyHeader(fiter->second); | 353 getPropertyHeader( fiter->second ); |
347 SubProperty & sub = m_propertyHeaders[fiter->second]; | 354 SubProperty & sub = m_propertyHeaders[fiter->second]; |
348 | 355 |
349 if ( !(sub.header->isCompound()) ) | 356 if ( !(sub.header->isCompound()) ) |
350 { | 357 { |
351 ABCA_THROW( "Tried to read a compound property from a non-compound: " | 358 ABCA_THROW( "Tried to read a compound property from a non-compound: " |
352 << iName << ", type: " | 359 << iName << ", type: " |
353 << sub.header->getPropertyType() ); | 360 << sub.header->getPropertyType() ); |
354 } | 361 } |
355 | 362 |
356 AbcA::BasePropertyReaderPtr bptr; | 363 AbcA::BasePropertyReaderPtr bptr = sub.made.lock(); |
357 if ( sub.made.expired() ) | 364 if ( ! bptr ) |
358 { | 365 { |
359 // Make a new one. | 366 // Make a new one. |
360 bptr.reset( new CprImpl( this->asCompoundPtr(), m_group, sub.header ) ); | 367 bptr.reset( new CprImpl( this->asCompoundPtr(), m_group, sub.header ) ); |
361 sub.made = bptr; | 368 sub.made = bptr; |
362 } | 369 } |
363 else | |
364 { | |
365 bptr = sub.made.lock(); | |
366 } | |
367 | 370 |
368 AbcA::CompoundPropertyReaderPtr ret = | 371 AbcA::CompoundPropertyReaderPtr ret = |
369 boost::dynamic_pointer_cast<AbcA::CompoundPropertyReader, | 372 boost::dynamic_pointer_cast<AbcA::CompoundPropertyReader, |
370 AbcA::BasePropertyReader>( bptr ); | 373 AbcA::BasePropertyReader>( bptr ); |
371 return ret; | 374 return ret; |
372 } | 375 } |
373 | 376 |
374 //-***************************************************************************** | 377 //-***************************************************************************** |
375 BaseCprImpl::~BaseCprImpl() | 378 BaseCprImpl::~BaseCprImpl() |
376 { | 379 { |
| 380 delete[] m_subPropertyMutexes; |
377 if ( m_group >= 0 ) | 381 if ( m_group >= 0 ) |
378 { | 382 { |
379 H5Gclose( m_group ); | 383 H5Gclose( m_group ); |
380 m_group = -1; | 384 m_group = -1; |
381 } | 385 } |
382 } | 386 } |
383 | 387 |
384 } // End namespace ALEMBIC_VERSION_NS | 388 } // End namespace ALEMBIC_VERSION_NS |
385 } // End namespace AbcCoreHDF5 | 389 } // End namespace AbcCoreHDF5 |
386 } // End namespace Alembic | 390 } // End namespace Alembic |
OLD | NEW |