Ptex: PtexCache.h Source File

Ptex

PtexCache.h
Go to the documentation of this file.
1#ifndef PtexCache_h
2#define PtexCache_h
3
4/*
5PTEX SOFTWARE
6Copyright 2014 Disney Enterprises, Inc. All rights reserved
7
8Redistribution and use in source and binary forms, with or without
9modification, are permitted provided that the following conditions are
10met:
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
25Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
26CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
27BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
28FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
29IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
30CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
34THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36OF 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
60public:
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)
82template<class T, PtexLruItem T::*item>
83 class PtexLruList
84{
85 PtexLruItem _end;
86
87public:
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
106class 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
129public:
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 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
187 size_t getBlockReadsChange() {
188 size_t blockReadsTmp = _blockReads;
189 size_t result = blockReadsTmp - _blockReadsAccountedFor;
190 _blockReadsAccountedFor = blockReadsTmp;
191 return result;
192 }
193};
194
195
197 class PtexReaderCache : public PtexCache
198{
199public:
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]),
203 _peakMemUsed(0), _peakFilesOpen(0), _fileOpens(0), _blockReads(0)
204 {
205 memset((void*)&_mruLists[0], 0, sizeof(_mruLists));
206 CACHE_LINE_PAD_INIT(_memUsed); // keep cppcheck happy
207 CACHE_LINE_PAD_INIT(_filesOpen);
208 CACHE_LINE_PAD_INIT(_mruLock);
209 }
210
211 ~PtexReaderCache()
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
267private:
268 struct Purger {
269 size_t memUsedChangeTotal;
270 Purger() : memUsedChangeTotal(0) {}
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;
280 PtexInputHandler* _io;
281 PtexErrorHandler* _err;
282 std::string _searchpath;
283 std::vector<std::string> _searchdirs;
284 typedef PtexHashMap<StringKey,PtexCachedReader*> FileMap;
285 FileMap _files;
286 bool _premultiply;
287 volatile size_t _memUsed; CACHE_LINE_PAD(_memUsed,size_t);
288 volatile size_t _filesOpen; CACHE_LINE_PAD(_filesOpen,size_t);
289 Mutex _mruLock; CACHE_LINE_PAD(_mruLock,Mutex);
290
291 static const int numMruFiles = 50;
292 struct MruList {
293 volatile int next;
294 PtexCachedReader* volatile files[numMruFiles];
295 };
296 MruList _mruLists[2];
297 MruList* volatile _mruList;
298 MruList* volatile _prevMruList;
299
300 PtexLruList<PtexCachedReader, &PtexCachedReader::_openFilesItem> _openFiles;
301 PtexLruList<PtexCachedReader, &PtexCachedReader::_activeFilesItem> _activeFiles;
302
303 size_t _peakMemUsed;
304 size_t _peakFilesOpen;
305 size_t _fileOpens;
306 size_t _blockReads;
307};
308
309 PTEX_NAMESPACE_END
310
311#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:209
CACHE_LINE_PAD_INIT
#define CACHE_LINE_PAD_INIT(var)
Definition: PtexPlatform.h:301
AtomicDecrement
PTEX_INLINE T AtomicDecrement(volatile T *target)
Definition: PtexPlatform.h:247
AtomicStore
PTEX_INLINE void AtomicStore(T volatile *target, T value)
Definition: PtexPlatform.h:284
AtomicCompareAndSwap
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:278
PtexReader.h
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
Mutex
Definition: PtexPlatform.h:137
PtexCache
File-handle and memory cache for reading ptex files.
Definition: Ptexture.h:684
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:146
PtexCachedReader::tryPurge
bool tryPurge(size_t &memUsedChange)
Definition: PtexCache.h:162
PtexCachedReader::getMemUsedChange
size_t getMemUsedChange()
Definition: PtexCache.h:173
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:152
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:187
PtexCachedReader::unlock
void unlock()
Definition: PtexCache.h:124
PtexCachedReader::getOpensChange
size_t getOpensChange()
Definition: PtexCache.h:180
PtexCachedReader::_refCount
volatile int32_t _refCount
Definition: PtexCache.h:111
PtexErrorHandler
Custom handler interface redirecting Ptex error messages.
Definition: Ptexture.h:658
PtexHashMap< StringKey, PtexCachedReader * >
PtexInputHandler
Custom handler interface for intercepting and redirecting Ptex input stream calls.
Definition: Ptexture.h:619
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:198
PtexReaderCache::_activeFiles
PtexLruList< PtexCachedReader, &PtexCachedReader::_activeFilesItem > _activeFiles
Definition: PtexCache.h:301
PtexReaderCache::_searchpath
std::string _searchpath
Definition: PtexCache.h:282
PtexReaderCache::_io
PtexInputHandler * _io
Definition: PtexCache.h:280
PtexReaderCache::~PtexReaderCache
~PtexReaderCache()
Definition: PtexCache.h:211
PtexReaderCache::_maxMem
size_t _maxMem
Definition: PtexCache.h:279
PtexReaderCache::adjustFilesOpen
void adjustFilesOpen(size_t amount)
Definition: PtexCache.h:259
PtexReaderCache::_fileOpens
size_t _fileOpens
Definition: PtexCache.h:305
PtexReaderCache::_memUsed
volatile size_t _memUsed
Definition: PtexCache.h:287
PtexReaderCache::_mruLock
Mutex _mruLock
Definition: PtexCache.h:289
PtexReaderCache::logRecentlyUsed
void logRecentlyUsed(PtexCachedReader *reader)
Definition: PtexCache.cpp:188
PtexReaderCache::pruneFiles
void pruneFiles()
Definition: PtexCache.cpp:254
PtexReaderCache::_prevMruList
MruList *volatile _prevMruList
Definition: PtexCache.h:298
PtexReaderCache::_files
FileMap _files
Definition: PtexCache.h:285
PtexReaderCache::adjustMemUsed
void adjustMemUsed(size_t amount)
Definition: PtexCache.h:253
PtexReaderCache::_premultiply
bool _premultiply
Definition: PtexCache.h:286
PtexReaderCache::_peakMemUsed
size_t _peakMemUsed
Definition: PtexCache.h:303
PtexReaderCache::release
virtual void release()
Release PtexCache. Cache will be immediately destroyed and all resources will be released.
Definition: PtexCache.h:214
PtexReaderCache::setSearchPath
virtual void setSearchPath(const char *path)
Set a search path for finding textures.
Definition: PtexCache.h:216
PtexReaderCache::getSearchPath
virtual const char * getSearchPath()
Query the search path.
Definition: PtexCache.h:239
PtexReaderCache::get
virtual PtexTexture * get(const char *path, Ptex::String &error)
Access a texture.
Definition: PtexCache.cpp:121
PtexReaderCache::findFile
bool findFile(const char *&filename, std::string &buffer, Ptex::String &error)
Definition: PtexCache.cpp:91
PtexReaderCache::getStats
virtual void getStats(Stats &stats)
Get stats.
Definition: PtexCache.cpp:326
PtexReaderCache::pruneData
void pruneData()
Definition: PtexCache.cpp:270
PtexReaderCache::PtexReaderCache
PtexReaderCache(int maxFiles, size_t maxMem, bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler)
Definition: PtexCache.h:200
PtexReaderCache::numMruFiles
static const int numMruFiles
Definition: PtexCache.h:291
PtexReaderCache::_maxFiles
size_t _maxFiles
Definition: PtexCache.h:278
PtexReaderCache::_peakFilesOpen
size_t _peakFilesOpen
Definition: PtexCache.h:304
PtexReaderCache::_err
PtexErrorHandler * _err
Definition: PtexCache.h:281
PtexReaderCache::CACHE_LINE_PAD
CACHE_LINE_PAD(_memUsed, size_t)
PtexReaderCache::_openFiles
PtexLruList< PtexCachedReader, &PtexCachedReader::_openFilesItem > _openFiles
Definition: PtexCache.h:300
PtexReaderCache::FileMap
PtexHashMap< StringKey, PtexCachedReader * > FileMap
Definition: PtexCache.h:284
PtexReaderCache::processMru
void processMru()
Definition: PtexCache.cpp:203
PtexReaderCache::purgeAll
virtual void purgeAll()
Remove all texture files from the cache.
Definition: PtexCache.cpp:319
PtexReaderCache::_blockReads
size_t _blockReads
Definition: PtexCache.h:306
PtexReaderCache::_filesOpen
volatile size_t _filesOpen
Definition: PtexCache.h:288
PtexReaderCache::_mruList
MruList *volatile _mruList
Definition: PtexCache.h:297
PtexReaderCache::purge
virtual void purge(PtexTexture *)
Remove a texture file from the cache.
Definition: PtexCache.cpp:287
PtexReaderCache::_mruLists
MruList _mruLists[2]
Definition: PtexCache.h:296
PtexReaderCache::_searchdirs
std::vector< std::string > _searchdirs
Definition: PtexCache.h:283
PtexReader
Definition: PtexReader.h:52
PtexReader::setPendingPurge
void setPendingPurge()
Definition: PtexReader.h:61
PtexReader::_opens
volatile size_t _opens
Definition: PtexReader.h:719
PtexReader::purge
void purge()
Definition: PtexReader.cpp:115
PtexReader::prune
void prune()
Definition: PtexReader.cpp:104
PtexReader::_memUsed
volatile size_t _memUsed
Definition: PtexReader.h:718
PtexReader::_blockReads
volatile size_t _blockReads
Definition: PtexReader.h:720
PtexTexture
Interface for reading data from a ptex file.
Definition: Ptexture.h:457
Ptex::String
Memory-managed string.
Definition: Ptexture.h:296
PTEX_NAMESPACE_BEGIN
Definition: PtexSeparableKernel.cpp:42
PtexUtils::max
T max(T a, T b)
Definition: PtexUtils.h:151
PtexReaderCache::MruList
Definition: PtexCache.h:292
PtexReaderCache::MruList::files
PtexCachedReader *volatile files[numMruFiles]
Definition: PtexCache.h:294
PtexReaderCache::MruList::next
volatile int next
Definition: PtexCache.h:293
PtexReaderCache::Purger
Definition: PtexCache.h:268
PtexReaderCache::Purger::operator()
void operator()(PtexCachedReader *reader)
Definition: PtexCache.cpp:311
PtexReaderCache::Purger::memUsedChangeTotal
size_t memUsedChangeTotal
Definition: PtexCache.h:269
PtexReaderCache::Purger::Purger
Purger()
Definition: PtexCache.h:270