Ptex
PtexCache.h
Go to the documentation of this file.
1 #ifndef PtexCache_h
2 #define PtexCache_h
3 
4 /*
5 PTEX SOFTWARE
6 Copyright 2014 Disney Enterprises, Inc. All rights reserved
7 
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are
10 met:
11 
12  * Redistributions of source code must retain the above copyright
13  notice, this list of conditions and the following disclaimer.
14 
15  * Redistributions in binary form must reproduce the above copyright
16  notice, this list of conditions and the following disclaimer in
17  the documentation and/or other materials provided with the
18  distribution.
19 
20  * The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
21  Studios" or the names of its contributors may NOT be used to
22  endorse or promote products derived from this software without
23  specific prior written permission from Walt Disney Pictures.
24 
25 Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
26 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
27 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
28 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
29 IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
30 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37 */
38 
39 #include "PtexPlatform.h"
40 #include <cstddef>
41 
42 #include "PtexMutex.h"
43 #include "PtexHashMap.h"
44 #include "PtexReader.h"
45 
47 
48 // Intrusive LRU list item (to be used only by PtexLruList)
50 {
53 
54  void extract() {
55  _next->_prev = _prev;
56  _prev->_next = _next;
57  _next = _prev = this;
58  }
59 
60 public:
61  PtexLruItem() : _prev(this), _next(this) {}
62 
63  // add item to end of list (pointed to by _prev)
64  void push(PtexLruItem* item) {
65  item->extract();
66  _prev->_next = item;
67  item->_next = this;
68  item->_prev = _prev;
69  _prev = item;
70  }
71 
72  // remove item from front of list (pointed to by _next)
74  if (_next == this) return 0;
75  PtexLruItem* item = _next;
76  _next->extract();
77  return item;
78  }
79 };
80 
81 // Intrusive LRU list (with LRU item stored as member of T)
82 template<class T, PtexLruItem T::*item>
84 {
86 
87 public:
88  void push(T* node)
89  {
90  // the item is added to the intrusive pointer specified by the template
91  // templatization allows more than one intrusive list to be in the object
92  _end.push(&(node->*item));
93  }
94 
95  T* pop()
96  {
97  PtexLruItem* it = _end.pop();
98  // "it" points to the intrusive item, a member within T
99  // subtract off the pointer-to-member offset to get a pointer to the containing T object
100  static const T* dummy = 0;
101  static const std::ptrdiff_t itemOffset = (const char*)&(dummy->*item) - (const char*)dummy;
102  return it ? (T*) ((char*)it - itemOffset) : 0;
103  }
104 };
105 
106 class PtexReaderCache;
107 
109 {
111  volatile int32_t _refCount;
117  friend class PtexReaderCache;
118 
119  bool trylock()
120  {
121  return AtomicCompareAndSwap(&_refCount, 0, -1);
122  }
123 
124  void unlock()
125  {
126  AtomicStore(&_refCount, 0);
127  }
128 
129 public:
130  PtexCachedReader(bool premultiply, PtexInputHandler* inputHandler, PtexErrorHandler* errorHandler, PtexReaderCache* cache)
131  : PtexReader(premultiply, inputHandler, errorHandler), _cache(cache), _refCount(1),
133  {
134  }
135 
137 
138  void ref() {
139  while (1) {
140  int32_t oldCount = _refCount;
141  if (oldCount >= 0 && AtomicCompareAndSwap(&_refCount, oldCount, oldCount+1))
142  return;
143  }
144  }
145 
146  int32_t unref() {
147  return AtomicDecrement(&_refCount);
148  }
149 
150  virtual void release();
151 
152  bool tryPrune(size_t& memUsedChange) {
153  if (trylock()) {
154  prune();
155  memUsedChange = getMemUsedChange();
156  unlock();
157  return true;
158  }
159  return false;
160  }
161 
162  bool tryPurge(size_t& memUsedChange) {
163  if (trylock()) {
164  purge();
165  memUsedChange = getMemUsedChange();
166  unlock();
167  return true;
168  }
169  setPendingPurge();
170  return false;
171  }
172 
173  size_t getMemUsedChange() {
174  size_t memUsedTmp = _memUsed;
175  size_t result = memUsedTmp - _memUsedAccountedFor;
176  _memUsedAccountedFor = memUsedTmp;
177  return result;
178  }
179 
180  size_t getOpensChange() {
181  size_t opensTmp = _opens;
182  size_t result = opensTmp - _opensAccountedFor;
183  _opensAccountedFor = opensTmp;
184  return result;
185  }
186 
188  size_t blockReadsTmp = _blockReads;
189  size_t result = blockReadsTmp - _blockReadsAccountedFor;
190  _blockReadsAccountedFor = blockReadsTmp;
191  return result;
192  }
193 };
194 
195 
198 {
199 public:
200  PtexReaderCache(int maxFiles, size_t maxMem, bool premultiply, PtexInputHandler* inputHandler, PtexErrorHandler* errorHandler)
201  : _maxFiles(maxFiles), _maxMem(maxMem), _io(inputHandler), _err(errorHandler), _premultiply(premultiply),
202  _memUsed(sizeof(*this)), _filesOpen(0), _mruList(&_mruLists[0]), _prevMruList(&_mruLists[1]),
204  {
205  memset((void*)&_mruLists[0], 0, sizeof(_mruLists));
206  CACHE_LINE_PAD_INIT(_memUsed); // keep cppcheck happy
209  }
210 
212  {}
213 
214  virtual void release() { delete this; }
215 
216  virtual void setSearchPath(const char* path)
217  {
218  // record path
219  _searchpath = path ? path : "";
220 
221  // split into dirs
222  _searchdirs.clear();
223 
224  if (path) {
225  const char* cp = path;
226  while (1) {
227  const char* delim = strchr(cp, ':');
228  if (!delim) {
229  if (*cp) _searchdirs.push_back(cp);
230  break;
231  }
232  int len = int(delim-cp);
233  if (len) _searchdirs.push_back(std::string(cp, len));
234  cp = delim+1;
235  }
236  }
237  }
238 
239  virtual const char* getSearchPath()
240  {
241  return _searchpath.c_str();
242  }
243 
244  virtual PtexTexture* get(const char* path, Ptex::String& error);
245 
246  virtual void purge(PtexTexture* /*texture*/);
247  virtual void purge(const char* /*filename*/);
248  virtual void purgeAll();
249  virtual void getStats(Stats& stats);
250 
251  void purge(PtexCachedReader* reader);
252 
253  void adjustMemUsed(size_t amount) {
254  if (amount) {
255  size_t memUsed = AtomicAdd(&_memUsed, amount);
256  _peakMemUsed = std::max(_peakMemUsed, memUsed);
257  }
258  }
259  void adjustFilesOpen(size_t amount) {
260  if (amount) {
261  size_t filesOpen = AtomicAdd(&_filesOpen, amount);
262  _peakFilesOpen = std::max(_peakFilesOpen, filesOpen);
263  }
264  }
265  void logRecentlyUsed(PtexCachedReader* reader);
266 
267 private:
268  struct Purger {
271  void operator() (PtexCachedReader* reader);
272  };
273 
274  bool findFile(const char*& filename, std::string& buffer, Ptex::String& error);
275  void processMru();
276  void pruneFiles();
277  void pruneData();
278  size_t _maxFiles;
279  size_t _maxMem;
282  std::string _searchpath;
283  std::vector<std::string> _searchdirs;
287  volatile size_t _memUsed; CACHE_LINE_PAD(_memUsed,size_t);
288  volatile size_t _filesOpen; CACHE_LINE_PAD(_filesOpen,size_t);
290 
291  static const int numMruFiles = 50;
292  struct MruList {
293  volatile int next;
295  };
297  MruList* volatile _mruList;
299 
302 
303  size_t _peakMemUsed;
305  size_t _fileOpens;
306  size_t _blockReads;
307 };
308 
310 
311 #endif
PtexCachedReader::_activeFilesItem
PtexLruItem _activeFilesItem
Definition: PtexCache.h:116
PtexReaderCache::getSearchPath
virtual const char * getSearchPath()
Query the search path.
Definition: PtexCache.h:239
PtexReader::purge
void purge()
Definition: PtexReader.cpp:115
PtexCachedReader::unlock
void unlock()
Definition: PtexCache.h:124
PtexReaderCache::~PtexReaderCache
~PtexReaderCache()
Definition: PtexCache.h:211
PtexCachedReader::trylock
bool trylock()
Definition: PtexCache.h:119
PtexLruItem
Definition: PtexCache.h:50
PtexReaderCache::getStats
virtual void getStats(Stats &stats)
Get stats.
Definition: PtexCache.cpp:326
PtexReaderCache::_mruLock
Mutex _mruLock
Definition: PtexCache.h:289
PtexReader::prune
void prune()
Definition: PtexReader.cpp:104
PtexReaderCache::release
virtual void release()
Release PtexCache. Cache will be immediately destroyed and all resources will be released.
Definition: PtexCache.h:214
PtexReaderCache::adjustMemUsed
void adjustMemUsed(size_t amount)
Definition: PtexCache.h:253
PtexReaderCache::_activeFiles
PtexLruList< PtexCachedReader, &PtexCachedReader::_activeFilesItem > _activeFiles
Definition: PtexCache.h:301
PtexLruItem::pop
PtexLruItem * pop()
Definition: PtexCache.h:73
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
PtexCachedReader::getOpensChange
size_t getOpensChange()
Definition: PtexCache.h:180
PtexLruList::_end
PtexLruItem _end
Definition: PtexCache.h:85
PtexCache
File-handle and memory cache for reading ptex files.
Definition: Ptexture.h:697
PtexMutex.h
PtexReaderCache::MruList::files
PtexCachedReader *volatile files[numMruFiles]
Definition: PtexCache.h:294
PtexReaderCache::_openFiles
PtexLruList< PtexCachedReader, &PtexCachedReader::_openFilesItem > _openFiles
Definition: PtexCache.h:300
PtexCachedReader::release
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
Definition: PtexCache.cpp:83
PtexCachedReader::tryPrune
bool tryPrune(size_t &memUsedChange)
Definition: PtexCache.h:152
PtexReaderCache::pruneData
void pruneData()
Definition: PtexCache.cpp:270
PtexReaderCache::_mruLists
MruList _mruLists[2]
Definition: PtexCache.h:296
PtexReaderCache::_files
FileMap _files
Definition: PtexCache.h:285
AtomicCompareAndSwap
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:267
PtexReaderCache::purgeAll
virtual void purgeAll()
Remove all texture files from the cache.
Definition: PtexCache.cpp:319
PtexCachedReader::_opensAccountedFor
size_t _opensAccountedFor
Definition: PtexCache.h:113
PtexReaderCache::MruList::next
volatile int next
Definition: PtexCache.h:293
PtexReaderCache::_io
PtexInputHandler * _io
Definition: PtexCache.h:280
PtexReaderCache::_maxFiles
size_t _maxFiles
Definition: PtexCache.h:278
PtexErrorHandler
Custom handler interface redirecting Ptex error messages.
Definition: Ptexture.h:671
PtexReaderCache::_prevMruList
MruList *volatile _prevMruList
Definition: PtexCache.h:298
PtexCachedReader::_refCount
volatile int32_t _refCount
Definition: PtexCache.h:111
PtexCachedReader::getMemUsedChange
size_t getMemUsedChange()
Definition: PtexCache.h:173
PtexCachedReader::getBlockReadsChange
size_t getBlockReadsChange()
Definition: PtexCache.h:187
PtexReaderCache::pruneFiles
void pruneFiles()
Definition: PtexCache.cpp:254
PtexReaderCache::Purger::operator()
void operator()(PtexCachedReader *reader)
Definition: PtexCache.cpp:311
PtexReaderCache::_maxMem
size_t _maxMem
Definition: PtexCache.h:279
PtexCachedReader::ref
void ref()
Definition: PtexCache.h:138
PtexReaderCache::_premultiply
bool _premultiply
Definition: PtexCache.h:286
PtexCachedReader::unref
int32_t unref()
Definition: PtexCache.h:146
PtexLruItem::push
void push(PtexLruItem *item)
Definition: PtexCache.h:64
PtexReader::_memUsed
volatile size_t _memUsed
Definition: PtexReader.h:718
PtexReader::_blockReads
volatile size_t _blockReads
Definition: PtexReader.h:720
AtomicStore
PTEX_INLINE void AtomicStore(T volatile *target, T value)
Definition: PtexPlatform.h:273
PtexCachedReader::_cache
PtexReaderCache * _cache
Definition: PtexCache.h:110
PtexReaderCache::PtexReaderCache
PtexReaderCache(int maxFiles, size_t maxMem, bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler)
Definition: PtexCache.h:200
PtexLruList
Definition: PtexCache.h:84
PtexReaderCache
Cache for reading Ptex texture files.
Definition: PtexCache.h:198
PtexReaderCache::FileMap
PtexHashMap< StringKey, PtexCachedReader * > FileMap
Definition: PtexCache.h:284
PtexInputHandler
Custom handler interface for intercepting and redirecting Ptex input stream calls.
Definition: Ptexture.h:632
PtexLruItem::extract
void extract()
Definition: PtexCache.h:54
CACHE_LINE_PAD_INIT
#define CACHE_LINE_PAD_INIT(var)
Definition: PtexPlatform.h:290
PTEX_NAMESPACE_BEGIN
Definition: PtexSeparableKernel.cpp:42
PtexHashMap< StringKey, PtexCachedReader * >
PtexReaderCache::get
virtual PtexTexture * get(const char *path, Ptex::String &error)
Access a texture.
Definition: PtexCache.cpp:121
PtexReaderCache::_searchdirs
std::vector< std::string > _searchdirs
Definition: PtexCache.h:283
PtexReaderCache::CACHE_LINE_PAD
CACHE_LINE_PAD(_mruLock, Mutex)
PtexLruList::pop
T * pop()
Definition: PtexCache.h:95
Ptex::String
Memory-managed string.
Definition: Ptexture.h:309
Mutex
Definition: PtexPlatform.h:126
PtexReader.h
PtexReaderCache::logRecentlyUsed
void logRecentlyUsed(PtexCachedReader *reader)
Definition: PtexCache.cpp:188
PtexReaderCache::_blockReads
size_t _blockReads
Definition: PtexCache.h:306
PtexLruItem::PtexLruItem
PtexLruItem()
Definition: PtexCache.h:61
PtexTexture
Interface for reading data from a ptex file.
Definition: Ptexture.h:470
PtexReaderCache::Purger::Purger
Purger()
Definition: PtexCache.h:270
PtexReaderCache::_mruList
MruList *volatile _mruList
Definition: PtexCache.h:297
PtexReader::setPendingPurge
void setPendingPurge()
Definition: PtexReader.h:61
PtexReaderCache::Purger::memUsedChangeTotal
size_t memUsedChangeTotal
Definition: PtexCache.h:269
PtexReaderCache::_filesOpen
volatile size_t _filesOpen
Definition: PtexCache.h:288
PtexCachedReader::PtexCachedReader
PtexCachedReader(bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler, PtexReaderCache *cache)
Definition: PtexCache.h:130
PtexReaderCache::setSearchPath
virtual void setSearchPath(const char *path)
Set a search path for finding textures.
Definition: PtexCache.h:216
PtexReaderCache::CACHE_LINE_PAD
CACHE_LINE_PAD(_filesOpen, size_t)
PtexReaderCache::_memUsed
volatile size_t _memUsed
Definition: PtexCache.h:287
PtexCachedReader
Definition: PtexCache.h:109
PtexReaderCache::adjustFilesOpen
void adjustFilesOpen(size_t amount)
Definition: PtexCache.h:259
PtexUtils::max
T max(T a, T b)
Definition: PtexUtils.h:150
PtexReaderCache::_err
PtexErrorHandler * _err
Definition: PtexCache.h:281
PtexReaderCache::Purger
Definition: PtexCache.h:268
PtexCachedReader::_openFilesItem
PtexLruItem _openFilesItem
Definition: PtexCache.h:115
PtexReaderCache::_peakMemUsed
size_t _peakMemUsed
Definition: PtexCache.h:303
PtexReader
Definition: PtexReader.h:52
PtexHashMap.h
Contains PtexHashMap, a lightweight multi-threaded hash table.
PtexLruItem::_prev
PtexLruItem * _prev
Definition: PtexCache.h:51
PtexCachedReader::~PtexCachedReader
~PtexCachedReader()
Definition: PtexCache.h:136
PtexLruList::push
void push(T *node)
Definition: PtexCache.h:88
PtexReaderCache::_peakFilesOpen
size_t _peakFilesOpen
Definition: PtexCache.h:304
PtexReader::_opens
volatile size_t _opens
Definition: PtexReader.h:719
PtexReaderCache::findFile
bool findFile(const char *&filename, std::string &buffer, Ptex::String &error)
Definition: PtexCache.cpp:91
PtexLruItem::_next
PtexLruItem * _next
Definition: PtexCache.h:52
AtomicAdd
PTEX_INLINE T AtomicAdd(volatile T *target, T value)
Definition: PtexPlatform.h:198
PtexReaderCache::_searchpath
std::string _searchpath
Definition: PtexCache.h:282
PtexReaderCache::_fileOpens
size_t _fileOpens
Definition: PtexCache.h:305
PtexReaderCache::processMru
void processMru()
Definition: PtexCache.cpp:203
PtexCachedReader::_memUsedAccountedFor
size_t _memUsedAccountedFor
Definition: PtexCache.h:112
PtexCachedReader::_blockReadsAccountedFor
size_t _blockReadsAccountedFor
Definition: PtexCache.h:114
AtomicDecrement
PTEX_INLINE T AtomicDecrement(volatile T *target)
Definition: PtexPlatform.h:236
PtexCachedReader::tryPurge
bool tryPurge(size_t &memUsedChange)
Definition: PtexCache.h:162
PtexReaderCache::purge
virtual void purge(PtexTexture *)
Remove a texture file from the cache.
Definition: PtexCache.cpp:287
PtexReaderCache::CACHE_LINE_PAD
CACHE_LINE_PAD(_memUsed, size_t)
PtexReaderCache::MruList
Definition: PtexCache.h:292
PtexPlatform.h
Platform-specific classes, functions, and includes.
PtexReaderCache::numMruFiles
static const int numMruFiles
Definition: PtexCache.h:291