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