Panda3D
geomCacheManager.cxx
1 // Filename: geomCacheManager.cxx
2 // Created by: drose (11Mar05)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "geomCacheManager.h"
16 #include "geomCacheEntry.h"
17 #include "lightMutexHolder.h"
18 #include "clockObject.h"
19 
20 GeomCacheManager *GeomCacheManager::_global_ptr = NULL;
21 
22 PStatCollector GeomCacheManager::_geom_cache_size_pcollector("Geom cache size");
23 PStatCollector GeomCacheManager::_geom_cache_active_pcollector("Geom cache size:Active");
24 PStatCollector GeomCacheManager::_geom_cache_record_pcollector("Geom cache operations:record");
25 PStatCollector GeomCacheManager::_geom_cache_erase_pcollector("Geom cache operations:erase");
26 PStatCollector GeomCacheManager::_geom_cache_evict_pcollector("Geom cache operations:evict");
27 
28 ////////////////////////////////////////////////////////////////////
29 // Function: GeomCacheManager::Constructor
30 // Access: Protected
31 // Description:
32 ////////////////////////////////////////////////////////////////////
33 GeomCacheManager::
34 GeomCacheManager() :
35  _lock("GeomCacheManager"),
36  _total_size(0)
37 {
38  // We deliberately hang on to this pointer forever.
39  _list = new GeomCacheEntry;
40  _list->ref();
41  _list->_next = _list;
42  _list->_prev = _list;
43 }
44 
45 ////////////////////////////////////////////////////////////////////
46 // Function: GeomCacheManager::Destructor
47 // Access: Protected
48 // Description:
49 ////////////////////////////////////////////////////////////////////
50 GeomCacheManager::
51 ~GeomCacheManager() {
52  // Shouldn't be deleting this global object.
53  nassertv(false);
54 }
55 
56 ////////////////////////////////////////////////////////////////////
57 // Function: GeomCacheManager::flush
58 // Access: Published
59 // Description: Immediately empties all elements in the cache.
60 ////////////////////////////////////////////////////////////////////
62 flush() {
63  LightMutexHolder holder(_lock);
64  evict_old_entries(0, false);
65 }
66 
67 ////////////////////////////////////////////////////////////////////
68 // Function: GeomCacheManager::get_global_ptr
69 // Access: Published, Static
70 // Description: Returns the global cache manager pointer.
71 ////////////////////////////////////////////////////////////////////
74  if (_global_ptr == (GeomCacheManager *)NULL) {
75  _global_ptr = new GeomCacheManager;
76  }
77  return _global_ptr;
78 }
79 
80 ////////////////////////////////////////////////////////////////////
81 // Function: GeomCacheManager::evict_old_entries
82 // Access: Public
83 // Description: Trims the cache size down to the specified size by
84 // evicting old cache entries as needed. It is assumed
85 // that you already hold the lock before calling this
86 // method.
87 ////////////////////////////////////////////////////////////////////
89 evict_old_entries(int max_size, bool keep_current) {
90  int current_frame = ClockObject::get_global_clock()->get_frame_count();
91  int min_frames = geom_cache_min_frames;
92 
93  while (_total_size > max_size) {
94  PT(GeomCacheEntry) entry = _list->_next;
95  nassertv(entry != _list);
96 
97  if (keep_current && current_frame - entry->_last_frame_used < min_frames) {
98  // Never mind, this one is too new.
99  if (gobj_cat.is_debug()) {
100  gobj_cat.debug()
101  << "Oldest element in cache is "
102  << current_frame - entry->_last_frame_used
103  << " frames; keeping cache at " << _total_size << " entries.\n";
104  }
105  break;
106  }
107 
108  entry->unref();
109 
110  if (gobj_cat.is_debug()) {
111  gobj_cat.debug()
112  << "cache total_size = " << _total_size << " entries, max_size = "
113  << max_size << ", removing " << *entry << "\n";
114  }
115 
116  entry->evict_callback();
117 
119  if (entry->_last_frame_used == current_frame) {
120  GeomCacheManager::_geom_cache_active_pcollector.sub_level(1);
121  }
122  }
123 
124  --_total_size;
125  entry->remove_from_list();
126  _geom_cache_evict_pcollector.add_level(1);
127  }
128  _geom_cache_size_pcollector.set_level(_total_size);
129 }
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:271
A lightweight class that represents a single element that may be timed and/or counted via stats...
int get_frame_count(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of times tick() has been called since the ClockObject was created, or since it was last reset.
Definition: clockObject.I:113
Similar to MutexHolder, but for a light mutex.
This is used to keep track of, and limit the size of, the cache of munged vertices, which would otherwise be distributed through all of the GeomVertexData objects in the system.
void flush()
Immediately empties all elements in the cache.
void ref() const
Explicitly increments the reference count.
void evict_old_entries()
Trims the cache size down to get_max_size() by evicting old cache entries as needed.
static bool is_connected()
Returns true if the client believes it is connected to a working PStatServer, false otherwise...
Definition: pStatClient.h:269
This object contains a single cache entry in the GeomCacheManager.
static GeomCacheManager * get_global_ptr()
Returns the global cache manager pointer.