00001 // Filename: vertexDataPage.I 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 00016 //////////////////////////////////////////////////////////////////// 00017 // Function: VertexDataPage::get_ram_class 00018 // Access: Published 00019 // Description: Returns the current ram class of the array. If this 00020 // is other than RC_resident, the array data is not 00021 // resident in memory. 00022 //////////////////////////////////////////////////////////////////// 00023 INLINE VertexDataPage::RamClass VertexDataPage:: 00024 get_ram_class() const { 00025 MutexHolder holder(_lock); 00026 return _ram_class; 00027 } 00028 00029 //////////////////////////////////////////////////////////////////// 00030 // Function: VertexDataPage::get_pending_ram_class 00031 // Access: Published 00032 // Description: Returns the pending ram class of the array. If this 00033 // is different from get_ram_class(), this page has been 00034 // queued to be processed by the thread. Eventually the 00035 // page will be set to this ram class. 00036 //////////////////////////////////////////////////////////////////// 00037 INLINE VertexDataPage::RamClass VertexDataPage:: 00038 get_pending_ram_class() const { 00039 MutexHolder holder(_lock); 00040 return _pending_ram_class; 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: VertexDataPage::request_resident 00045 // Access: Published 00046 // Description: Ensures that the page will become resident soon. 00047 // Future calls to get_page_data() will eventually 00048 // return non-NULL. 00049 //////////////////////////////////////////////////////////////////// 00050 INLINE void VertexDataPage:: 00051 request_resident() { 00052 MutexHolder holder(_lock); 00053 if (_ram_class != RC_resident) { 00054 request_ram_class(RC_resident); 00055 } 00056 } 00057 00058 //////////////////////////////////////////////////////////////////// 00059 // Function: VertexDataPage::alloc 00060 // Access: Published 00061 // Description: Allocates a new block. Returns NULL if a block of the 00062 // requested size cannot be allocated. 00063 // 00064 // To free the allocated block, call block->free(), or 00065 // simply delete the block pointer. 00066 //////////////////////////////////////////////////////////////////// 00067 INLINE VertexDataBlock *VertexDataPage:: 00068 alloc(size_t size) { 00069 MutexHolder holder(_lock); 00070 return do_alloc(size); 00071 } 00072 00073 //////////////////////////////////////////////////////////////////// 00074 // Function: VertexDataPage::get_first_block 00075 // Access: Published 00076 // Description: Returns a pointer to the first allocated block, or 00077 // NULL if there are no allocated blocks. 00078 //////////////////////////////////////////////////////////////////// 00079 INLINE VertexDataBlock *VertexDataPage:: 00080 get_first_block() const { 00081 MutexHolder holder(_lock); 00082 return (VertexDataBlock *)SimpleAllocator::get_first_block(); 00083 } 00084 00085 //////////////////////////////////////////////////////////////////// 00086 // Function: VertexDataPage::get_book 00087 // Access: Published 00088 // Description: Returns a pointer to the book that owns this page. 00089 //////////////////////////////////////////////////////////////////// 00090 INLINE VertexDataBook *VertexDataPage:: 00091 get_book() const { 00092 return _book; 00093 } 00094 00095 //////////////////////////////////////////////////////////////////// 00096 // Function: VertexDataPage::get_global_lru 00097 // Access: Published, Static 00098 // Description: Returns a pointer to the global LRU object that 00099 // manages the VertexDataPage's with the indicated 00100 // RamClass. 00101 //////////////////////////////////////////////////////////////////// 00102 INLINE SimpleLru *VertexDataPage:: 00103 get_global_lru(RamClass rclass) { 00104 nassertr(rclass >= 0 && rclass < RC_end_of_list, NULL); 00105 return _global_lru[rclass]; 00106 } 00107 00108 //////////////////////////////////////////////////////////////////// 00109 // Function: VertexDataPage::get_pending_lru 00110 // Access: Published, Static 00111 // Description: Returns a pointer to the global LRU object that 00112 // manages the VertexDataPage's that are pending 00113 // processing by the thread. 00114 //////////////////////////////////////////////////////////////////// 00115 INLINE SimpleLru *VertexDataPage:: 00116 get_pending_lru() { 00117 return &_pending_lru; 00118 } 00119 00120 //////////////////////////////////////////////////////////////////// 00121 // Function: VertexDataPage::get_save_file 00122 // Access: Published, Static 00123 // Description: Returns the global VertexDataSaveFile that will be 00124 // used to save vertex data buffers to disk when 00125 // necessary. 00126 //////////////////////////////////////////////////////////////////// 00127 INLINE VertexDataSaveFile *VertexDataPage:: 00128 get_save_file() { 00129 if (_save_file == (VertexDataSaveFile *)NULL) { 00130 make_save_file(); 00131 } 00132 return _save_file; 00133 } 00134 00135 //////////////////////////////////////////////////////////////////// 00136 // Function: VertexDataPage::save_to_disk 00137 // Access: Published 00138 // Description: Writes the page to disk, but does not evict it from 00139 // memory or affect its LRU status. If it gets evicted 00140 // later without having been modified, it will not need 00141 // to write itself to disk again. 00142 //////////////////////////////////////////////////////////////////// 00143 INLINE bool VertexDataPage:: 00144 save_to_disk() { 00145 MutexHolder holder(_lock); 00146 return do_save_to_disk(); 00147 } 00148 00149 //////////////////////////////////////////////////////////////////// 00150 // Function: VertexDataPage::get_num_threads 00151 // Access: Published, Static 00152 // Description: Returns the number of threads that have been spawned 00153 // to service vertex paging requests, or 0 if no threads 00154 // have been spawned (which may mean either that all 00155 // paging requests will be handled by the main thread, 00156 // or simply that no paging requests have yet been 00157 // issued). 00158 //////////////////////////////////////////////////////////////////// 00159 INLINE int VertexDataPage:: 00160 get_num_threads() { 00161 MutexHolder holder(_tlock); 00162 if (_thread_mgr == (PageThreadManager *)NULL) { 00163 return 0; 00164 } 00165 return _thread_mgr->get_num_threads(); 00166 } 00167 00168 //////////////////////////////////////////////////////////////////// 00169 // Function: VertexDataPage::get_num_pending_reads 00170 // Access: Published, Static 00171 // Description: Returns the number of read requests that are waiting 00172 // to be serviced by a thread. 00173 //////////////////////////////////////////////////////////////////// 00174 INLINE int VertexDataPage:: 00175 get_num_pending_reads() { 00176 MutexHolder holder(_tlock); 00177 if (_thread_mgr == (PageThreadManager *)NULL) { 00178 return 0; 00179 } 00180 return _thread_mgr->get_num_pending_reads(); 00181 } 00182 00183 //////////////////////////////////////////////////////////////////// 00184 // Function: VertexDataPage::get_num_pending_writes 00185 // Access: Published, Static 00186 // Description: Returns the number of write requests that are waiting 00187 // to be serviced by a thread. 00188 //////////////////////////////////////////////////////////////////// 00189 INLINE int VertexDataPage:: 00190 get_num_pending_writes() { 00191 MutexHolder holder(_tlock); 00192 if (_thread_mgr == (PageThreadManager *)NULL) { 00193 return 0; 00194 } 00195 return _thread_mgr->get_num_pending_writes(); 00196 } 00197 00198 //////////////////////////////////////////////////////////////////// 00199 // Function: VertexDataPage::get_page_data 00200 // Access: Public 00201 // Description: Returns a pointer to the page's data area, or NULL if 00202 // the page is not currently resident. If the page is 00203 // not currently resident, this will implicitly request 00204 // it to become resident soon. 00205 // 00206 // If force is true, this method will never return NULL, 00207 // but may block until the page is available. 00208 //////////////////////////////////////////////////////////////////// 00209 INLINE unsigned char *VertexDataPage:: 00210 get_page_data(bool force) { 00211 MutexHolder holder(_lock); 00212 if (_ram_class != RC_resident || _pending_ram_class != RC_resident) { 00213 if (force) { 00214 make_resident_now(); 00215 } else { 00216 request_ram_class(RC_resident); 00217 if (_ram_class != RC_resident) { 00218 return NULL; 00219 } 00220 } 00221 } 00222 00223 mark_used_lru(); 00224 nassertr(_size == _uncompressed_size, _page_data); 00225 return _page_data; 00226 } 00227 00228 //////////////////////////////////////////////////////////////////// 00229 // Function: VertexDataPage::operator 00230 // Access: Public 00231 // Description: This comparison method is used to order pages within 00232 // a book. 00233 //////////////////////////////////////////////////////////////////// 00234 INLINE bool VertexDataPage:: 00235 operator < (const VertexDataPage &other) const { 00236 // We sort pages so that the pages with the smallest number of 00237 // available contiguous bytes come up first. We store our best 00238 // estimate of continguous bytes here. 00239 if (_book_size != other._book_size) { 00240 return _book_size < other._book_size; 00241 } 00242 00243 // For pages of equal size, we sort based on pointers, to make it 00244 // easy to quickly find a specific page. 00245 return this < &other; 00246 } 00247 00248 //////////////////////////////////////////////////////////////////// 00249 // Function: VertexDataPage::set_ram_class 00250 // Access: Private 00251 // Description: Puts the data in a new ram class. Assumes the page 00252 // lock is already held. 00253 //////////////////////////////////////////////////////////////////// 00254 INLINE void VertexDataPage:: 00255 set_ram_class(RamClass rclass) { 00256 _ram_class = rclass; 00257 mark_used_lru(_global_lru[rclass]); 00258 00259 // Changing the ram class might make our effective available space 0 00260 // and thereby change the placement within the book. 00261 adjust_book_size(); 00262 } 00263 00264 //////////////////////////////////////////////////////////////////// 00265 // Function: VertexDataPage::round_up 00266 // Access: Private 00267 // Description: Round page_size up to the next multiple of 00268 // _block_size. 00269 //////////////////////////////////////////////////////////////////// 00270 INLINE size_t VertexDataPage:: 00271 round_up(size_t page_size) const { 00272 return ((page_size + _block_size - 1) / _block_size) * _block_size; 00273 }