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
46 PTEX_NAMESPACE_BEGIN
47
48// Intrusive LRU list item (to be used only by PtexLruList)
49 class PtexLruItem
50{
51 PtexLruItem* _prev;
52 PtexLruItem* _next;
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)
73 PtexLruItem* pop() {
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>
83 class PtexLruList
84{
85 PtexLruItem _end;
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
108 class PtexCachedReader : public PtexReader
109{
110 PtexReaderCache* _cache;
111 volatile int32_t _refCount;
112 size_t _memUsedAccountedFor;
113 size_t _opensAccountedFor;
114 size_t _blockReadsAccountedFor;
115 PtexLruItem _openFilesItem;
116 PtexLruItem _activeFilesItem;
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),
132 _memUsedAccountedFor(0), _opensAccountedFor(0), _blockReadsAccountedFor(0)
133 {
134 }
135
136 ~PtexCachedReader() {}
137
138 void ref() {
139 // Note: a negative ref count indicates the texture is locked, e.g. for pruning or purging.
140 // This should happen rarely, and only for a brief instant, but when it does we must wait
141 // for the ref count to become non-negative again. We do so by making CompareAndSwap fail
142 // when the old value is negative.
143 while (1) {
144 int32_t oldCount = std::max(0, int32_t(_refCount));
145 int32_t newCount = oldCount+1;
146 if (AtomicCompareAndSwap(&_refCount, oldCount, newCount))
147 return;
148 }
149 }
150
151 int32_t unref() {
152 int32_t newCount = AtomicDecrement(&_refCount);
153 if (newCount < 0) {
154 // A negative ref count here indicates an application error. The negative ref count also
155 // means the texture is now inadvertently locked. Set an error state, unlock the
156 // texture.
157 setError("PtexTexture Error: unref() called with refCount <= 0");
158 unlock();
159 }
160 return newCount;
161 }
162
163 virtual void release();
164
165 bool tryPrune(size_t& memUsedChange) {
166 if (trylock()) {
167 prune();
168 memUsedChange = getMemUsedChange();
169 unlock();
170 return true;
171 }
172 return false;
173 }
174
175 bool tryPurge(size_t& memUsedChange) {
176 if (trylock()) {
177 purge();
178 memUsedChange = getMemUsedChange();
179 unlock();
180 return true;
181 }
182 setPendingPurge();
183 return false;
184 }
185
186 size_t getMemUsedChange() {
187 size_t memUsedTmp = _memUsed;
188 size_t result = memUsedTmp - _memUsedAccountedFor;
189 _memUsedAccountedFor = memUsedTmp;
190 return result;
191 }
192
193 size_t getOpensChange() {
194 size_t opensTmp = _opens;
195 size_t result = opensTmp - _opensAccountedFor;
196 _opensAccountedFor = opensTmp;
197 return result;
198 }
199
200 size_t getBlockReadsChange() {
201 size_t blockReadsTmp = _blockReads;
202 size_t result = blockReadsTmp - _blockReadsAccountedFor;
203 _blockReadsAccountedFor = blockReadsTmp;
204 return result;
205 }
206};
207
208
210 class PtexReaderCache : public PtexCache
211{
212 public:
213 PtexReaderCache(int maxFiles, size_t maxMem, bool premultiply, PtexInputHandler* inputHandler, PtexErrorHandler* errorHandler)
214 : _maxFiles(maxFiles), _maxMem(maxMem), _io(inputHandler), _err(errorHandler), _premultiply(premultiply),
215 _memUsed(sizeof(*this)), _filesOpen(0), _mruList(&_mruLists[0]), _prevMruList(&_mruLists[1]),
216 _peakMemUsed(0), _peakFilesOpen(0), _fileOpens(0), _blockReads(0)
217 {
218 memset((void*)&_mruLists[0], 0, sizeof(_mruLists));
219 CACHE_LINE_PAD_INIT(_memUsed); // keep cppcheck happy
220 CACHE_LINE_PAD_INIT(_filesOpen);
221 CACHE_LINE_PAD_INIT(_mruLock);
222 }
223
224 ~PtexReaderCache()
225 {}
226
227 virtual void release() { delete this; }
228
229 virtual void setSearchPath(const char* path)
230 {
231 // record path
232 _searchpath = path ? path : "";
233
234 // split into dirs
235 _searchdirs.clear();
236
237 if (path) {
238 const char* cp = path;
239 while (1) {
240 const char* delim = strchr(cp, ':');
241 if (!delim) {
242 if (*cp) _searchdirs.push_back(cp);
243 break;
244 }
245 int len = int(delim-cp);
246 if (len) _searchdirs.push_back(std::string(cp, len));
247 cp = delim+1;
248 }
249 }
250 }
251
252 virtual const char* getSearchPath()
253 {
254 return _searchpath.c_str();
255 }
256
257 virtual PtexTexture* get(const char* path, Ptex::String& error);
258
259 virtual void purge(PtexTexture* /*texture*/);
260 virtual void purge(const char* /*filename*/);
261 virtual void purgeAll();
262 virtual void getStats(Stats& stats);
263
264 void purge(PtexCachedReader* reader);
265
266 void adjustMemUsed(size_t amount) {
267 if (amount) {
268 size_t memUsed = AtomicAdd(&_memUsed, amount);
269 _peakMemUsed = std::max(_peakMemUsed, memUsed);
270 }
271 }
272 void adjustFilesOpen(size_t amount) {
273 if (amount) {
274 size_t filesOpen = AtomicAdd(&_filesOpen, amount);
275 _peakFilesOpen = std::max(_peakFilesOpen, filesOpen);
276 }
277 }
278 void logRecentlyUsed(PtexCachedReader* reader);
279
280 private:
281 struct Purger {
282 size_t memUsedChangeTotal;
283 Purger() : memUsedChangeTotal(0) {}
284 void operator() (PtexCachedReader* reader);
285 };
286
287 bool findFile(const char*& filename, std::string& buffer, Ptex::String& error);
288 void processMru();
289 void pruneFilesIfNeeded();
290 void pruneDataIfNeeded();
291 size_t _maxFiles;
292 size_t _maxMem;
293 PtexInputHandler* _io;
294 PtexErrorHandler* _err;
295 std::string _searchpath;
296 std::vector<std::string> _searchdirs;
297 typedef PtexHashMap<StringKey,PtexCachedReader*> FileMap;
298 FileMap _files;
299 bool _premultiply;
300 volatile size_t _memUsed; CACHE_LINE_PAD(_memUsed,size_t);
301 volatile size_t _filesOpen; CACHE_LINE_PAD(_filesOpen,size_t);
302 Mutex _mruLock; CACHE_LINE_PAD(_mruLock,Mutex);
303
304 static constexpr int maxMruFiles = 50;
305 struct MruList {
306 volatile int next;
307 PtexCachedReader* volatile files[maxMruFiles];
308 };
309 MruList _mruLists[2];
310 MruList* volatile _mruList;
311 MruList* volatile _prevMruList;
312
313 PtexLruList<PtexCachedReader, &PtexCachedReader::_openFilesItem> _openFiles;
314 PtexLruList<PtexCachedReader, &PtexCachedReader::_activeFilesItem> _activeFiles;
315
316 size_t _peakMemUsed;
317 size_t _peakFilesOpen;
318 size_t _fileOpens;
319 size_t _blockReads;
320};
321
322 PTEX_NAMESPACE_END
323
324#endif
PtexHashMap.h
Contains PtexHashMap, a lightweight multi-threaded hash table.
PtexMutex.h
PtexPlatform.h
Platform-specific classes, functions, and includes.
AtomicAdd
PTEX_INLINE T AtomicAdd(volatile T *target, T value)
Definition PtexPlatform.h:211
CACHE_LINE_PAD_INIT
#define CACHE_LINE_PAD_INIT(var)
Definition PtexPlatform.h:303
AtomicDecrement
PTEX_INLINE T AtomicDecrement(volatile T *target)
Definition PtexPlatform.h:249
CACHE_LINE_PAD
#define CACHE_LINE_PAD(var, type)
Definition PtexPlatform.h:302
AtomicStore
PTEX_INLINE void AtomicStore(T volatile *target, T value)
Definition PtexPlatform.h:286
AtomicCompareAndSwap
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
Definition PtexPlatform.h:280
PtexReader.h
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition PtexVersion.h:62
Mutex
Definition PtexPlatform.h:139
PtexCache
File-handle and memory cache for reading ptex files.
Definition Ptexture.h:693
PtexCachedReader
Definition PtexCache.h:109
PtexCachedReader::trylock
bool trylock()
Definition PtexCache.h:119
PtexCachedReader::_memUsedAccountedFor
size_t _memUsedAccountedFor
Definition PtexCache.h:112
PtexCachedReader::_cache
PtexReaderCache * _cache
Definition PtexCache.h:110
PtexCachedReader::_opensAccountedFor
size_t _opensAccountedFor
Definition PtexCache.h:113
PtexCachedReader::unref
int32_t unref()
Definition PtexCache.h:151
PtexCachedReader::PtexReaderCache
friend class PtexReaderCache
Definition PtexCache.h:117
PtexCachedReader::tryPurge
bool tryPurge(size_t &memUsedChange)
Definition PtexCache.h:175
PtexCachedReader::getMemUsedChange
size_t getMemUsedChange()
Definition PtexCache.h:186
PtexCachedReader::PtexCachedReader
PtexCachedReader(bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler, PtexReaderCache *cache)
Definition PtexCache.h:130
PtexCachedReader::tryPrune
bool tryPrune(size_t &memUsedChange)
Definition PtexCache.h:165
PtexCachedReader::~PtexCachedReader
~PtexCachedReader()
Definition PtexCache.h:136
PtexCachedReader::release
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
Definition PtexCache.cpp:83
PtexCachedReader::_activeFilesItem
PtexLruItem _activeFilesItem
Definition PtexCache.h:116
PtexCachedReader::ref
void ref()
Definition PtexCache.h:138
PtexCachedReader::_blockReadsAccountedFor
size_t _blockReadsAccountedFor
Definition PtexCache.h:114
PtexCachedReader::_openFilesItem
PtexLruItem _openFilesItem
Definition PtexCache.h:115
PtexCachedReader::getBlockReadsChange
size_t getBlockReadsChange()
Definition PtexCache.h:200
PtexCachedReader::unlock
void unlock()
Definition PtexCache.h:124
PtexCachedReader::getOpensChange
size_t getOpensChange()
Definition PtexCache.h:193
PtexCachedReader::_refCount
volatile int32_t _refCount
Definition PtexCache.h:111
PtexErrorHandler
Custom handler interface redirecting Ptex error messages.
Definition Ptexture.h:667
PtexHashMap
Definition PtexHashMap.h:133
PtexInputHandler
Custom handler interface for intercepting and redirecting Ptex input stream calls.
Definition Ptexture.h:628
PtexLruItem
Definition PtexCache.h:50
PtexLruItem::pop
PtexLruItem * pop()
Definition PtexCache.h:73
PtexLruItem::extract
void extract()
Definition PtexCache.h:54
PtexLruItem::_prev
PtexLruItem * _prev
Definition PtexCache.h:51
PtexLruItem::PtexLruItem
PtexLruItem()
Definition PtexCache.h:61
PtexLruItem::push
void push(PtexLruItem *item)
Definition PtexCache.h:64
PtexLruItem::_next
PtexLruItem * _next
Definition PtexCache.h:52
PtexLruList
Definition PtexCache.h:84
PtexLruList::_end
PtexLruItem _end
Definition PtexCache.h:85
PtexLruList::pop
T * pop()
Definition PtexCache.h:95
PtexLruList::push
void push(T *node)
Definition PtexCache.h:88
PtexReaderCache
Cache for reading Ptex texture files.
Definition PtexCache.h:211
PtexReaderCache::_activeFiles
PtexLruList< PtexCachedReader, &PtexCachedReader::_activeFilesItem > _activeFiles
Definition PtexCache.h:314
PtexReaderCache::_searchpath
std::string _searchpath
Definition PtexCache.h:295
PtexReaderCache::_io
PtexInputHandler * _io
Definition PtexCache.h:293
PtexReaderCache::~PtexReaderCache
~PtexReaderCache()
Definition PtexCache.h:224
PtexReaderCache::_maxMem
size_t _maxMem
Definition PtexCache.h:292
PtexReaderCache::adjustFilesOpen
void adjustFilesOpen(size_t amount)
Definition PtexCache.h:272
PtexReaderCache::_fileOpens
size_t _fileOpens
Definition PtexCache.h:318
PtexReaderCache::_memUsed
volatile size_t _memUsed
Definition PtexCache.h:300
PtexReaderCache::_mruLock
Mutex _mruLock
Definition PtexCache.h:302
PtexReaderCache::logRecentlyUsed
void logRecentlyUsed(PtexCachedReader *reader)
Definition PtexCache.cpp:184
PtexReaderCache::_prevMruList
MruList *volatile _prevMruList
Definition PtexCache.h:311
PtexReaderCache::pruneFilesIfNeeded
void pruneFilesIfNeeded()
Definition PtexCache.cpp:249
PtexReaderCache::_files
FileMap _files
Definition PtexCache.h:298
PtexReaderCache::adjustMemUsed
void adjustMemUsed(size_t amount)
Definition PtexCache.h:266
PtexReaderCache::_premultiply
bool _premultiply
Definition PtexCache.h:299
PtexReaderCache::_peakMemUsed
size_t _peakMemUsed
Definition PtexCache.h:316
PtexReaderCache::release
virtual void release()
Release PtexCache. Cache will be immediately destroyed and all resources will be released.
Definition PtexCache.h:227
PtexReaderCache::setSearchPath
virtual void setSearchPath(const char *path)
Set a search path for finding textures.
Definition PtexCache.h:229
PtexReaderCache::getSearchPath
virtual const char * getSearchPath()
Query the search path.
Definition PtexCache.h:252
PtexReaderCache::get
virtual PtexTexture * get(const char *path, Ptex::String &error)
Access a texture.
Definition PtexCache.cpp:125
PtexReaderCache::findFile
bool findFile(const char *&filename, std::string &buffer, Ptex::String &error)
Definition PtexCache.cpp:95
PtexReaderCache::maxMruFiles
static constexpr int maxMruFiles
Definition PtexCache.h:304
PtexReaderCache::getStats
virtual void getStats(Stats &stats)
Get stats.
Definition PtexCache.cpp:331
PtexReaderCache::PtexReaderCache
PtexReaderCache(int maxFiles, size_t maxMem, bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler)
Definition PtexCache.h:213
PtexReaderCache::_maxFiles
size_t _maxFiles
Definition PtexCache.h:291
PtexReaderCache::_peakFilesOpen
size_t _peakFilesOpen
Definition PtexCache.h:317
PtexReaderCache::_err
PtexErrorHandler * _err
Definition PtexCache.h:294
PtexReaderCache::_openFiles
PtexLruList< PtexCachedReader, &PtexCachedReader::_openFilesItem > _openFiles
Definition PtexCache.h:313
PtexReaderCache::FileMap
PtexHashMap< StringKey, PtexCachedReader * > FileMap
Definition PtexCache.h:297
PtexReaderCache::processMru
void processMru()
Definition PtexCache.cpp:200
PtexReaderCache::purgeAll
virtual void purgeAll()
Remove all texture files from the cache.
Definition PtexCache.cpp:324
PtexReaderCache::_blockReads
size_t _blockReads
Definition PtexCache.h:319
PtexReaderCache::pruneDataIfNeeded
void pruneDataIfNeeded()
Definition PtexCache.cpp:268
PtexReaderCache::_filesOpen
volatile size_t _filesOpen
Definition PtexCache.h:301
PtexReaderCache::_mruList
MruList *volatile _mruList
Definition PtexCache.h:310
PtexReaderCache::purge
virtual void purge(PtexTexture *)
Remove a texture file from the cache.
Definition PtexCache.cpp:292
PtexReaderCache::_mruLists
MruList _mruLists[2]
Definition PtexCache.h:309
PtexReaderCache::_searchdirs
std::vector< std::string > _searchdirs
Definition PtexCache.h:296
PtexReader::setPendingPurge
void setPendingPurge()
Definition PtexReader.h:62
PtexReader::_opens
volatile size_t _opens
Definition PtexReader.h:709
PtexReader::purge
void purge()
Definition PtexReader.cpp:117
PtexReader::PtexReader
PtexReader(bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler)
Definition PtexReader.cpp:73
PtexReader::setError
void setError(const char *error, bool ioError=false)
Definition PtexReader.h:549
PtexReader::prune
void prune()
Definition PtexReader.cpp:106
PtexReader::_memUsed
volatile size_t _memUsed
Definition PtexReader.h:708
PtexReader::_blockReads
volatile size_t _blockReads
Definition PtexReader.h:710
PtexTexture
Interface for reading data from a ptex file.
Definition Ptexture.h:460
Ptex::String
Memory-managed string.
Definition Ptexture.h:299
PTEX_NAMESPACE_BEGIN
Definition PtexSeparableKernel.cpp:42
PtexReaderCache::MruList
Definition PtexCache.h:305
PtexReaderCache::MruList::files
PtexCachedReader *volatile files[maxMruFiles]
Definition PtexCache.h:307
PtexReaderCache::MruList::next
volatile int next
Definition PtexCache.h:306
PtexReaderCache::Purger::operator()
void operator()(PtexCachedReader *reader)
Definition PtexCache.cpp:316
PtexReaderCache::Purger::memUsedChangeTotal
size_t memUsedChangeTotal
Definition PtexCache.h:282
PtexReaderCache::Purger::Purger
Purger()
Definition PtexCache.h:283