Ptex: PtexCache.h Source File

Ptex

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

PtexCache.h
Go to the documentation of this file.
1 #ifndef PtexCache_h
2 #define PtexCache_h
3
4 /*
5 PTEX SOFTWARE
6 Copyright 2009 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 <assert.h>
41
42 #include "PtexMutex.h"
43 #include "Ptexture.h"
44 #include "PtexDict.h"
45
46 #define USE_SPIN // use spinlocks instead of mutex for main cache lock
47
48 namespace PtexInternal {
49
50 #ifdef USE_SPIN
51 typedef SpinLock CacheLock;
52 #else
53 typedef Mutex CacheLock;
54 #endif
55 typedef AutoLock<CacheLock> AutoLockCache;
56
57 #ifndef NDEBUG
58 #define GATHER_STATS
59 #endif
60
61 #ifdef GATHER_STATS
62 struct CacheStats{
63 int nfilesOpened;
64 int nfilesClosed;
65 int ndataAllocated;
66 int ndataFreed;
67 int nblocksRead;
68 long int nbytesRead;
69 int nseeks;
70
71 CacheStats()
72 : nfilesOpened(0),
73 nfilesClosed(0),
74 ndataAllocated(0),
75 ndataFreed(0),
76 nblocksRead(0),
77 nbytesRead(0),
78 nseeks(0) {}
79
80 ~CacheStats();
81 void print();
82 static void inc(int& val) {
83 static SpinLock spinlock;
84 AutoSpin lock(spinlock);
85 val++;
86 }
87 static void add(long int& val, int inc) {
88 static SpinLock spinlock;
89 AutoSpin lock(spinlock);
90 val+=inc;
91 }
92 };
93 extern CacheStats stats;
94 #define STATS_INC(x) stats.inc(stats.x);
95 #define STATS_ADD(x, y) stats.add(stats.x, y);
96 #else
97 #define STATS_INC(x)
98 #define STATS_ADD(x, y)
99 #endif
100 }
101 using namespace PtexInternal;
102
104 class PtexLruItem {
105 public:
106 bool inuse() { return _prev == 0; }
107 void orphan()
108 {
109 // parent no longer wants me
110 void** p = _parent;
111 _parent = 0;
112 assert(p && *p == this);
113 if (!inuse()) delete this;
114 *p = 0;
115 }
116 template <typename T> static void orphanList(T& list)
117 {
118 for (typename T::iterator i=list.begin(); i != list.end(); i++) {
119 PtexLruItem* obj = *i;
120 if (obj) {
121 assert(obj->_parent == (void**)&*i);
122 obj->orphan();
123 }
124 }
125 }
126
127 protected:
128 PtexLruItem(void** parent=0)
129 : _parent(parent), _prev(0), _next(0) {}
130 virtual ~PtexLruItem()
131 {
132 // detach from parent (if any)
133 if (_parent) { assert(*_parent == this); *_parent = 0; }
134 // unlink from lru list (if in list)
135 if (_prev) {
136 _prev->_next = _next;
137 _next->_prev = _prev;
138 }
139 }
140
141 private:
142 friend class PtexLruList; // maintains prev/next, deletes
143 void** _parent; // pointer to this item within parent
144 PtexLruItem* _prev; // prev in lru list (0 if in-use)
145 PtexLruItem* _next; // next in lru list (0 if in-use)
146 };
147
148
149
152 class PtexLruList {
153 public:
154 PtexLruList() { _end._prev = _end._next = &_end; }
155 ~PtexLruList() { while (pop()) continue; }
156
157 void extract(PtexLruItem* node)
158 {
159 // remove from list
160 node->_prev->_next = node->_next;
161 node->_next->_prev = node->_prev;
162 node->_next = node->_prev = 0;
163 }
164
165 void push(PtexLruItem* node)
166 {
167 // delete node if orphaned
168 if (!node->_parent) delete node;
169 else {
170 // add to end of list
171 node->_next = &_end;
172 node->_prev = _end._prev;
173 _end._prev->_next = node;
174 _end._prev = node;
175 }
176 }
177
178 bool pop()
179 {
180 if (_end._next == &_end) return 0;
181 delete _end._next; // item will unlink itself
182 return 1;
183 }
184
185 private:
186 PtexLruItem _end;
187 };
188
189
192 class PtexCacheImpl : public PtexCache {
193 public:
194 PtexCacheImpl(int maxFiles, int maxMem)
195 : _pendingDelete(false),
196 _maxFiles(maxFiles), _unusedFileCount(0),
197 _maxDataSize(maxMem),
198 _unusedDataSize(0), _unusedDataCount(0)
199 {
200 /* Allow for a minimum number of data blocks so cache doesn't
201 thrash too much if there are any really big items in the
202 cache pushing over the limit. It's better to go over the
203 limit in this case and make sure there's room for at least
204 a modest number of objects in the cache.
205 */
206
207 // try to allow for at least 10 objects per file (up to 100 files)
208 _minDataCount = 10 * maxFiles;
209 // but no more than 1000
210 if (_minDataCount > 1000) _minDataCount = 1000;
211 }
212
213 virtual void release() { delete this; }
214
215 Mutex openlock;
216 CacheLock cachelock;
217
218 // internal use - only call from reader classes for deferred deletion
219 void setPendingDelete() { _pendingDelete = true; }
220 void handlePendingDelete() { if (_pendingDelete) delete this; }
221
222 // internal use - only call from PtexCachedFile, PtexCachedData
223 static void addFile() { STATS_INC(nfilesOpened); }
224 void setFileInUse(PtexLruItem* file);
225 void setFileUnused(PtexLruItem* file);
226 void removeFile();
227 static void addData() { STATS_INC(ndataAllocated); }
228 void setDataInUse(PtexLruItem* data, int size);
229 void setDataUnused(PtexLruItem* data, int size);
230 void removeData(int size);
231
232 void purgeFiles() {
233 while (_unusedFileCount > _maxFiles)
234 {
235 if (!_unusedFiles.pop()) break;
236 // note: pop will destroy item and item destructor will
237 // call removeFile which will decrement _unusedFileCount
238 }
239 }
240 void purgeData() {
241 while ((_unusedDataSize > _maxDataSize) &&
242 (_unusedDataCount > _minDataCount))
243 {
244 if (!_unusedData.pop()) break;
245 // note: pop will destroy item and item destructor will
246 // call removeData which will decrement _unusedDataSize
247 // and _unusedDataCount
248 }
249 }
250
251 protected:
252 ~PtexCacheImpl();
253
254 private:
255 bool _pendingDelete; // flag set if delete is pending
256
257 int _maxFiles, _unusedFileCount; // file limit, current unused file count
258 long int _maxDataSize, _unusedDataSize; // data limit (bytes), current size
259 int _minDataCount, _unusedDataCount; // min, current # of unused data blocks
260 PtexLruList _unusedFiles, _unusedData; // lists of unused items
261 };
262
263
265 class PtexCachedFile : public PtexLruItem
266 {
267 public:
268 PtexCachedFile(void** parent, PtexCacheImpl* cache)
269 : PtexLruItem(parent), _cache(cache), _refcount(1)
270 { _cache->addFile(); }
271 void ref() { assert(_cache->cachelock.locked()); if (!_refcount++) _cache->setFileInUse(this); }
272 void unref() { assert(_cache->cachelock.locked()); if (!--_refcount) _cache->setFileUnused(this); }
273 protected:
274 virtual ~PtexCachedFile() { _cache->removeFile(); }
275 PtexCacheImpl* _cache;
276 private:
277 int _refcount;
278 };
279
280
282 class PtexCachedData : public PtexLruItem
283 {
284 public:
285 PtexCachedData(void** parent, PtexCacheImpl* cache, int size)
286 : PtexLruItem(parent), _cache(cache), _refcount(1), _size(size)
287 { _cache->addData(); }
288 void ref() { assert(_cache->cachelock.locked()); if (!_refcount++) _cache->setDataInUse(this, _size); }
289 void unref() { assert(_cache->cachelock.locked()); if (!--_refcount) _cache->setDataUnused(this, _size); }
290 protected:
291 void incSize(int size) { _size += size; }
292 virtual ~PtexCachedData() { _cache->removeData(_size); }
293 PtexCacheImpl* _cache;
294 private:
295 int _refcount;
296 int _size;
297 };
298
299
300 #endif
PtexCacheImpl::handlePendingDelete
void handlePendingDelete()
Definition: PtexCache.h:220
PtexLruItem::_parent
void ** _parent
Definition: PtexCache.h:143
PtexLruItem::inuse
bool inuse()
Definition: PtexCache.h:106
PtexCacheImpl::_pendingDelete
bool _pendingDelete
Definition: PtexCache.h:255
PtexCachedData::incSize
void incSize(int size)
Definition: PtexCache.h:291
PtexCacheImpl::_unusedDataSize
long int _unusedDataSize
Definition: PtexCache.h:258
PtexCacheImpl::purgeData
void purgeData()
Definition: PtexCache.h:240
PtexCachedData::ref
void ref()
Definition: PtexCache.h:288
PtexCachedFile::unref
void unref()
Definition: PtexCache.h:272
PtexLruList::_end
PtexLruItem _end
Definition: PtexCache.h:186
PtexCache
File-handle and memory cache for reading ptex files.
Definition: Ptexture.h:634
PtexCacheImpl::_unusedFileCount
int _unusedFileCount
Definition: PtexCache.h:257
PtexPlatform.h
Platform-specific classes, functions, and includes.
PtexCacheImpl::setPendingDelete
void setPendingDelete()
Definition: PtexCache.h:219
STATS_INC
#define STATS_INC(x)
Definition: PtexCache.h:97
PtexCacheImpl::_unusedDataCount
int _unusedDataCount
Definition: PtexCache.h:259
PtexCachedData::_refcount
int _refcount
Definition: PtexCache.h:295
PtexCachedFile::_cache
PtexCacheImpl * _cache
Definition: PtexCache.h:275
PtexInternal::_Mutex
Definition: PtexPlatform.h:120
PtexLruList::pop
bool pop()
Definition: PtexCache.h:178
PtexCachedData::unref
void unref()
Definition: PtexCache.h:289
PtexCachedFile::~PtexCachedFile
virtual ~PtexCachedFile()
Definition: PtexCache.h:274
PtexCacheImpl::addData
static void addData()
Definition: PtexCache.h:227
PtexCacheImpl::purgeFiles
void purgeFiles()
Definition: PtexCache.h:232
PtexCachedData::_size
int _size
Definition: PtexCache.h:296
PtexCachedFile::PtexCachedFile
PtexCachedFile(void **parent, PtexCacheImpl *cache)
Definition: PtexCache.h:268
PtexCachedData::~PtexCachedData
virtual ~PtexCachedData()
Definition: PtexCache.h:292
PtexLruList::push
void push(PtexLruItem *node)
Definition: PtexCache.h:165
PtexInternal::CacheLock
SpinLock CacheLock
Definition: PtexCache.h:51
PtexLruList::~PtexLruList
~PtexLruList()
Definition: PtexCache.h:155
PtexCachedData
Cache entry for allocated memory block.
Definition: PtexCache.h:282
PtexCacheImpl::openlock
Mutex openlock
Definition: PtexCache.h:215
PtexLruItem
One item in a cache, typically an open file or a block of memory.
Definition: PtexCache.h:104
PtexLruItem::orphanList
static void orphanList(T &list)
Definition: PtexCache.h:116
PtexCachedData::_cache
PtexCacheImpl * _cache
Definition: PtexCache.h:293
PtexCacheImpl::release
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
Definition: PtexCache.h:213
PtexInternal::AutoLockCache
AutoLock< CacheLock > AutoLockCache
Definition: PtexCache.h:55
PtexLruList::PtexLruList
PtexLruList()
Definition: PtexCache.h:154
PtexInternal
For internal use only.
Definition: PtexCache.h:48
PtexMutex.h
PtexCachedData::PtexCachedData
PtexCachedData(void **parent, PtexCacheImpl *cache, int size)
Definition: PtexCache.h:285
PtexInternal::_SpinLock
Definition: PtexPlatform.h:141
PtexCachedFile::_refcount
int _refcount
Definition: PtexCache.h:277
PtexLruItem::_next
PtexLruItem * _next
Definition: PtexCache.h:145
PtexLruItem::~PtexLruItem
virtual ~PtexLruItem()
Definition: PtexCache.h:130
PtexCachedFile
Cache entry for open file handle.
Definition: PtexCache.h:265
PtexCacheImpl::cachelock
CacheLock cachelock
Definition: PtexCache.h:216
PtexCacheImpl
Ptex cache implementation.
Definition: PtexCache.h:192
PtexDict.h
Contains PtexDict, a string-keyed hash table.
PtexLruItem::_prev
PtexLruItem * _prev
Definition: PtexCache.h:144
PtexLruItem::orphan
void orphan()
Definition: PtexCache.h:107
PtexInternal::AutoLock
Automatically acquire and release lock within enclosing scope.
Definition: PtexMutex.h:58
PtexLruItem::PtexLruItem
PtexLruItem(void **parent=0)
Definition: PtexCache.h:128
PtexCacheImpl::PtexCacheImpl
PtexCacheImpl(int maxFiles, int maxMem)
Definition: PtexCache.h:194
PtexLruList
A list of items kept in least-recently-used (LRU) order.
Definition: PtexCache.h:152
PtexCacheImpl::addFile
static void addFile()
Definition: PtexCache.h:223
Ptexture.h
Public API classes for reading, writing, caching, and filtering Ptex files.
PtexCacheImpl::_unusedFiles
PtexLruList _unusedFiles
Definition: PtexCache.h:260
PtexCachedFile::ref
void ref()
Definition: PtexCache.h:271
PtexLruList::extract
void extract(PtexLruItem *node)
Definition: PtexCache.h:157