Panda3D
|
00001 // Filename: vertexDataPage.h 00002 // Created by: drose (04Jun07) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef VERTEXDATAPAGE_H 00016 #define VERTEXDATAPAGE_H 00017 00018 #include "pandabase.h" 00019 #include "simpleLru.h" 00020 #include "simpleAllocator.h" 00021 #include "pStatCollector.h" 00022 #include "vertexDataSaveFile.h" 00023 #include "pmutex.h" 00024 #include "conditionVar.h" 00025 #include "conditionVarFull.h" 00026 #include "thread.h" 00027 #include "mutexHolder.h" 00028 #include "pdeque.h" 00029 00030 class VertexDataBook; 00031 class VertexDataBlock; 00032 00033 //////////////////////////////////////////////////////////////////// 00034 // Class : VertexDataPage 00035 // Description : A block of bytes that holds one or more 00036 // VertexDataBlocks. The entire page may be paged out, 00037 // in the form of in-memory compression or to an on-disk 00038 // cache file, if necessary. 00039 //////////////////////////////////////////////////////////////////// 00040 class EXPCL_PANDA_GOBJ VertexDataPage : public SimpleAllocator, public SimpleLruPage { 00041 private: 00042 VertexDataPage(size_t book_size); 00043 VertexDataPage(VertexDataBook *book, size_t page_size, size_t block_size); 00044 virtual ~VertexDataPage(); 00045 00046 PUBLISHED: 00047 // These are used to indicate the current residency state of the 00048 // page, which may or may not have been temporarily evicted to 00049 // satisfy memory requirements. 00050 enum RamClass { 00051 RC_resident, 00052 RC_compressed, 00053 RC_disk, 00054 00055 RC_end_of_list, // list marker; do not use 00056 }; 00057 00058 INLINE RamClass get_ram_class() const; 00059 INLINE RamClass get_pending_ram_class() const; 00060 INLINE void request_resident(); 00061 00062 INLINE VertexDataBlock *alloc(size_t size); 00063 INLINE VertexDataBlock *get_first_block() const; 00064 00065 INLINE VertexDataBook *get_book() const; 00066 00067 INLINE static SimpleLru *get_global_lru(RamClass rclass); 00068 INLINE static SimpleLru *get_pending_lru(); 00069 INLINE static VertexDataSaveFile *get_save_file(); 00070 00071 INLINE bool save_to_disk(); 00072 00073 INLINE static int get_num_threads(); 00074 INLINE static int get_num_pending_reads(); 00075 INLINE static int get_num_pending_writes(); 00076 static void stop_threads(); 00077 static void flush_threads(); 00078 00079 virtual void output(ostream &out) const; 00080 virtual void write(ostream &out, int indent_level) const; 00081 00082 public: 00083 INLINE unsigned char *get_page_data(bool force); 00084 INLINE bool operator < (const VertexDataPage &other) const; 00085 00086 protected: 00087 virtual SimpleAllocatorBlock *make_block(size_t start, size_t size); 00088 virtual void changed_contiguous(); 00089 virtual void evict_lru(); 00090 00091 private: 00092 class PageThread; 00093 00094 VertexDataBlock *do_alloc(size_t size); 00095 00096 void make_resident_now(); 00097 void make_resident(); 00098 void make_compressed(); 00099 void make_disk(); 00100 00101 bool do_save_to_disk(); 00102 void do_restore_from_disk(); 00103 00104 void adjust_book_size(); 00105 00106 void request_ram_class(RamClass ram_class); 00107 INLINE void set_ram_class(RamClass ram_class); 00108 static void make_save_file(); 00109 00110 INLINE size_t round_up(size_t page_size) const; 00111 unsigned char *alloc_page_data(size_t page_size) const; 00112 void free_page_data(unsigned char *page_data, size_t page_size) const; 00113 00114 typedef pdeque<VertexDataPage *> PendingPages; 00115 00116 class PageThreadManager; 00117 class PageThread : public Thread { 00118 public: 00119 PageThread(PageThreadManager *manager, const string &name); 00120 00121 protected: 00122 virtual void thread_main(); 00123 00124 private: 00125 PageThreadManager *_manager; 00126 VertexDataPage *_working_page; 00127 00128 // Signaled when _working_page is set to NULL after finishing a 00129 // task. 00130 ConditionVar _working_cvar; 00131 friend class PageThreadManager; 00132 }; 00133 typedef pvector<PT(PageThread) > PageThreads; 00134 00135 class PageThreadManager : public ReferenceCount { 00136 public: 00137 PageThreadManager(int num_threads); 00138 void add_page(VertexDataPage *page, RamClass ram_class); 00139 void remove_page(VertexDataPage *page); 00140 int get_num_threads() const; 00141 int get_num_pending_reads() const; 00142 int get_num_pending_writes() const; 00143 void start_threads(int num_threads); 00144 void stop_threads(); 00145 00146 private: 00147 PendingPages _pending_writes; 00148 PendingPages _pending_reads; 00149 bool _shutdown; 00150 00151 // Signaled when anything new is added to either of the above 00152 // queues, or when _shutdown is set true. This wakes up any 00153 // pending thread. 00154 ConditionVarFull _pending_cvar; 00155 00156 PageThreads _threads; 00157 friend class PageThread; 00158 }; 00159 00160 static PT(PageThreadManager) _thread_mgr; 00161 static Mutex &_tlock; // Protects _thread_mgr and all of its members. 00162 00163 unsigned char *_page_data; 00164 size_t _size, _allocated_size, _uncompressed_size; 00165 RamClass _ram_class; 00166 PT(VertexDataSaveBlock) _saved_block; 00167 size_t _book_size; 00168 size_t _block_size; 00169 00170 //Mutex _lock; // Inherited from SimpleAllocator. Protects above members. 00171 RamClass _pending_ram_class; // Protected by _tlock. 00172 00173 VertexDataBook *_book; // never changes. 00174 00175 enum { deflate_page_size = 1024, inflate_page_size = 1024 }; 00176 00177 // We build up a temporary linked list of these while deflating 00178 // (compressing) the vertex data in-memory. 00179 class DeflatePage { 00180 public: 00181 DeflatePage() { 00182 _used_size = 0; 00183 _next = NULL; 00184 } 00185 ALLOC_DELETED_CHAIN(DeflatePage); 00186 00187 unsigned char _buffer[deflate_page_size]; 00188 size_t _used_size; 00189 DeflatePage *_next; 00190 00191 public: 00192 static TypeHandle get_class_type() { 00193 return _type_handle; 00194 } 00195 static void init_type() { 00196 register_type(_type_handle, "VertexDataPage::DeflatePage"); 00197 } 00198 00199 private: 00200 static TypeHandle _type_handle; 00201 }; 00202 00203 static SimpleLru _resident_lru; 00204 static SimpleLru _compressed_lru; 00205 static SimpleLru _disk_lru; 00206 static SimpleLru _pending_lru; 00207 static SimpleLru *_global_lru[RC_end_of_list]; 00208 00209 static VertexDataSaveFile *_save_file; 00210 00211 static Mutex _unused_mutex; 00212 00213 static PStatCollector _vdata_compress_pcollector; 00214 static PStatCollector _vdata_decompress_pcollector; 00215 static PStatCollector _vdata_save_pcollector; 00216 static PStatCollector _vdata_restore_pcollector; 00217 static PStatCollector _thread_wait_pcollector; 00218 static PStatCollector _alloc_pages_pcollector; 00219 00220 public: 00221 static TypeHandle get_class_type() { 00222 return _type_handle; 00223 } 00224 static void init_type() { 00225 register_type(_type_handle, "VertexDataPage"); 00226 } 00227 00228 private: 00229 static TypeHandle _type_handle; 00230 00231 friend class PageThread; 00232 friend class VertexDataBook; 00233 }; 00234 00235 inline ostream &operator << (ostream &out, const VertexDataPage &page) { 00236 page.output(out); 00237 return out; 00238 } 00239 00240 #include "vertexDataPage.I" 00241 00242 #endif