Panda3D
vertexDataPage.h
1 // Filename: vertexDataPage.h
2 // Created by: drose (04Jun07)
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 #ifndef VERTEXDATAPAGE_H
16 #define VERTEXDATAPAGE_H
17 
18 #include "pandabase.h"
19 #include "simpleLru.h"
20 #include "simpleAllocator.h"
21 #include "pStatCollector.h"
22 #include "vertexDataSaveFile.h"
23 #include "pmutex.h"
24 #include "conditionVar.h"
25 #include "conditionVarFull.h"
26 #include "thread.h"
27 #include "mutexHolder.h"
28 #include "pdeque.h"
29 
30 class VertexDataBook;
31 class VertexDataBlock;
32 
33 ////////////////////////////////////////////////////////////////////
34 // Class : VertexDataPage
35 // Description : A block of bytes that holds one or more
36 // VertexDataBlocks. The entire page may be paged out,
37 // in the form of in-memory compression or to an on-disk
38 // cache file, if necessary.
39 ////////////////////////////////////////////////////////////////////
40 class EXPCL_PANDA_GOBJ VertexDataPage : public SimpleAllocator, public SimpleLruPage {
41 private:
42  VertexDataPage(size_t book_size);
43  VertexDataPage(VertexDataBook *book, size_t page_size, size_t block_size);
44  virtual ~VertexDataPage();
45 
46 PUBLISHED:
47  // These are used to indicate the current residency state of the
48  // page, which may or may not have been temporarily evicted to
49  // satisfy memory requirements.
50  enum RamClass {
51  RC_resident,
52  RC_compressed,
53  RC_disk,
54 
55  RC_end_of_list, // list marker; do not use
56  };
57 
58  INLINE RamClass get_ram_class() const;
59  INLINE RamClass get_pending_ram_class() const;
60  INLINE void request_resident();
61 
62  INLINE VertexDataBlock *alloc(size_t size);
63  INLINE VertexDataBlock *get_first_block() const;
64 
65  INLINE VertexDataBook *get_book() const;
66 
67  INLINE static SimpleLru *get_global_lru(RamClass rclass);
68  INLINE static SimpleLru *get_pending_lru();
69  INLINE static VertexDataSaveFile *get_save_file();
70 
71  INLINE bool save_to_disk();
72 
73  INLINE static int get_num_threads();
74  INLINE static int get_num_pending_reads();
75  INLINE static int get_num_pending_writes();
76  static void stop_threads();
77  static void flush_threads();
78 
79  virtual void output(ostream &out) const;
80  virtual void write(ostream &out, int indent_level) const;
81 
82 public:
83  INLINE unsigned char *get_page_data(bool force);
84  INLINE bool operator < (const VertexDataPage &other) const;
85 
86 protected:
87  virtual SimpleAllocatorBlock *make_block(size_t start, size_t size);
88  virtual void changed_contiguous();
89  virtual void evict_lru();
90 
91 private:
92  class PageThread;
93 
94  VertexDataBlock *do_alloc(size_t size);
95 
96  void make_resident_now();
97  void make_resident();
98  void make_compressed();
99  void make_disk();
100 
101  bool do_save_to_disk();
102  void do_restore_from_disk();
103 
104  void adjust_book_size();
105 
106  void request_ram_class(RamClass ram_class);
107  INLINE void set_ram_class(RamClass ram_class);
108  static void make_save_file();
109 
110  INLINE size_t round_up(size_t page_size) const;
111  unsigned char *alloc_page_data(size_t page_size) const;
112  void free_page_data(unsigned char *page_data, size_t page_size) const;
113 
115 
116  class PageThreadManager;
117  class EXPCL_PANDA_GOBJ PageThread : public Thread {
118  public:
119  PageThread(PageThreadManager *manager, const string &name);
120 
121  protected:
122  virtual void thread_main();
123 
124  private:
125  PageThreadManager *_manager;
126  VertexDataPage *_working_page;
127 
128  // Signaled when _working_page is set to NULL after finishing a
129  // task.
130  ConditionVar _working_cvar;
131  friend class PageThreadManager;
132  };
134 
135  class EXPCL_PANDA_GOBJ PageThreadManager : public ReferenceCount {
136  public:
137  PageThreadManager(int num_threads);
138  void add_page(VertexDataPage *page, RamClass ram_class);
139  void remove_page(VertexDataPage *page);
140  int get_num_threads() const;
141  int get_num_pending_reads() const;
142  int get_num_pending_writes() const;
143  void start_threads(int num_threads);
144  void stop_threads();
145 
146  private:
147  PendingPages _pending_writes;
148  PendingPages _pending_reads;
149  bool _shutdown;
150 
151  // Signaled when anything new is added to either of the above
152  // queues, or when _shutdown is set true. This wakes up any
153  // pending thread.
154  ConditionVarFull _pending_cvar;
155 
156  PageThreads _threads;
157  friend class PageThread;
158  };
159 
160  static PT(PageThreadManager) _thread_mgr;
161  static Mutex &_tlock; // Protects _thread_mgr and all of its members.
162 
163  unsigned char *_page_data;
164  size_t _size, _allocated_size, _uncompressed_size;
165  RamClass _ram_class;
166  PT(VertexDataSaveBlock) _saved_block;
167  size_t _book_size;
168  size_t _block_size;
169 
170  //Mutex _lock; // Inherited from SimpleAllocator. Protects above members.
171  RamClass _pending_ram_class; // Protected by _tlock.
172 
173  VertexDataBook *_book; // never changes.
174 
175  enum { deflate_page_size = 1024, inflate_page_size = 1024 };
176 
177  // We build up a temporary linked list of these while deflating
178  // (compressing) the vertex data in-memory.
179  class EXPCL_PANDA_GOBJ DeflatePage {
180  public:
181  DeflatePage() {
182  _used_size = 0;
183  _next = NULL;
184  }
185  ALLOC_DELETED_CHAIN(DeflatePage);
186 
187  unsigned char _buffer[deflate_page_size];
188  size_t _used_size;
189  DeflatePage *_next;
190 
191  public:
192  static TypeHandle get_class_type() {
193  return _type_handle;
194  }
195  static void init_type() {
196  register_type(_type_handle, "VertexDataPage::DeflatePage");
197  }
198 
199  private:
200  static TypeHandle _type_handle;
201  };
202 
203  static SimpleLru _resident_lru;
204  static SimpleLru _compressed_lru;
205  static SimpleLru _disk_lru;
206  static SimpleLru _pending_lru;
207  static SimpleLru *_global_lru[RC_end_of_list];
208 
209  static VertexDataSaveFile *_save_file;
210 
211  static Mutex _unused_mutex;
212 
213  static PStatCollector _vdata_compress_pcollector;
214  static PStatCollector _vdata_decompress_pcollector;
215  static PStatCollector _vdata_save_pcollector;
216  static PStatCollector _vdata_restore_pcollector;
217  static PStatCollector _thread_wait_pcollector;
218  static PStatCollector _alloc_pages_pcollector;
219 
220 public:
221  static TypeHandle get_class_type() {
222  return _type_handle;
223  }
224  static void init_type() {
225  register_type(_type_handle, "VertexDataPage");
226  }
227 
228 private:
229  static TypeHandle _type_handle;
230 
231  friend class PageThread;
232  friend class VertexDataBook;
233 };
234 
235 inline ostream &operator << (ostream &out, const VertexDataPage &page) {
236  page.output(out);
237  return out;
238 }
239 
240 #include "vertexDataPage.I"
241 
242 #endif
A block of bytes on the save file.
An implementation of a very simple LRU algorithm.
Definition: simpleLru.h:31
A block of bytes that holds one or more VertexDataBlocks.
A temporary file to hold the vertex data that has been evicted from memory and written to disk...
An implementation of a very simple block allocator.
SimpleAllocatorBlock * alloc(size_t size)
Allocates a new block.
A standard mutex, or mutual exclusion lock.
Definition: pmutex.h:44
A condition variable, usually used to communicate information about changing state to a thread that i...
Definition: conditionVar.h:47
A block of bytes that stores the actual raw vertex data referenced by a GeomVertexArrayData object...
A single block as returned from SimpleAllocator::alloc().
A lightweight class that represents a single element that may be timed and/or counted via stats...
virtual void evict_lru()
Evicts the page from the LRU.
Definition: simpleLru.cxx:255
One atomic piece that may be managed by a SimpleLru chain.
Definition: simpleLru.h:70
SimpleAllocatorBlock * get_first_block() const
Returns a pointer to the first allocated block, or NULL if there are no allocated blocks...
A collection of VertexDataPages, which can be used to allocate new VertexDataBlock objects...
A base class for all things that want to be reference-counted.
This class implements a condition variable; see ConditionVar for a brief introduction to this class...
A thread; that is, a lightweight process.
Definition: thread.h:51
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85