historical/toontown-classic.git/panda/include/vertexDataPage.I
2024-01-16 11:20:27 -06:00

224 lines
5.8 KiB
Text

/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file vertexDataPage.I
* @author drose
* @date 2007-06-04
*/
/**
* Returns the current ram class of the array. If this is other than
* RC_resident, the array data is not resident in memory.
*/
INLINE VertexDataPage::RamClass VertexDataPage::
get_ram_class() const {
MutexHolder holder(_lock);
return _ram_class;
}
/**
* Returns the pending ram class of the array. If this is different from
* get_ram_class(), this page has been queued to be processed by the thread.
* Eventually the page will be set to this ram class.
*/
INLINE VertexDataPage::RamClass VertexDataPage::
get_pending_ram_class() const {
MutexHolder holder(_lock);
return _pending_ram_class;
}
/**
* Ensures that the page will become resident soon. Future calls to
* get_page_data() will eventually return non-NULL.
*/
INLINE void VertexDataPage::
request_resident() {
MutexHolder holder(_lock);
if (_ram_class != RC_resident) {
request_ram_class(RC_resident);
}
}
/**
* Allocates a new block. Returns NULL if a block of the requested size
* cannot be allocated.
*
* To free the allocated block, call block->free(), or simply delete the block
* pointer.
*/
INLINE VertexDataBlock *VertexDataPage::
alloc(size_t size) {
MutexHolder holder(_lock);
return do_alloc(size);
}
/**
* Returns a pointer to the first allocated block, or NULL if there are no
* allocated blocks.
*/
INLINE VertexDataBlock *VertexDataPage::
get_first_block() const {
MutexHolder holder(_lock);
return (VertexDataBlock *)SimpleAllocator::get_first_block();
}
/**
* Returns a pointer to the book that owns this page.
*/
INLINE VertexDataBook *VertexDataPage::
get_book() const {
return _book;
}
/**
* Returns a pointer to the global LRU object that manages the
* VertexDataPage's with the indicated RamClass.
*/
INLINE SimpleLru *VertexDataPage::
get_global_lru(RamClass rclass) {
nassertr(rclass >= 0 && rclass < RC_end_of_list, nullptr);
return _global_lru[rclass];
}
/**
* Returns a pointer to the global LRU object that manages the
* VertexDataPage's that are pending processing by the thread.
*/
INLINE SimpleLru *VertexDataPage::
get_pending_lru() {
return &_pending_lru;
}
/**
* Returns the global VertexDataSaveFile that will be used to save vertex data
* buffers to disk when necessary.
*/
INLINE VertexDataSaveFile *VertexDataPage::
get_save_file() {
if (_save_file == nullptr) {
make_save_file();
}
return _save_file;
}
/**
* Writes the page to disk, but does not evict it from memory or affect its
* LRU status. If it gets evicted later without having been modified, it will
* not need to write itself to disk again.
*/
INLINE bool VertexDataPage::
save_to_disk() {
MutexHolder holder(_lock);
return do_save_to_disk();
}
/**
* Returns the number of threads that have been spawned to service vertex
* paging requests, or 0 if no threads have been spawned (which may mean
* either that all paging requests will be handled by the main thread, or
* simply that no paging requests have yet been issued).
*/
INLINE int VertexDataPage::
get_num_threads() {
MutexHolder holder(_tlock);
if (_thread_mgr == nullptr) {
return 0;
}
return _thread_mgr->get_num_threads();
}
/**
* Returns the number of read requests that are waiting to be serviced by a
* thread.
*/
INLINE int VertexDataPage::
get_num_pending_reads() {
MutexHolder holder(_tlock);
if (_thread_mgr == nullptr) {
return 0;
}
return _thread_mgr->get_num_pending_reads();
}
/**
* Returns the number of write requests that are waiting to be serviced by a
* thread.
*/
INLINE int VertexDataPage::
get_num_pending_writes() {
MutexHolder holder(_tlock);
if (_thread_mgr == nullptr) {
return 0;
}
return _thread_mgr->get_num_pending_writes();
}
/**
* Returns a pointer to the page's data area, or NULL if the page is not
* currently resident. If the page is not currently resident, this will
* implicitly request it to become resident soon.
*
* If force is true, this method will never return NULL, but may block until
* the page is available.
*/
INLINE unsigned char *VertexDataPage::
get_page_data(bool force) {
MutexHolder holder(_lock);
if (_ram_class != RC_resident || _pending_ram_class != RC_resident) {
if (force) {
make_resident_now();
} else {
request_ram_class(RC_resident);
if (_ram_class != RC_resident) {
return nullptr;
}
}
}
mark_used_lru();
nassertr(_size == _uncompressed_size, _page_data);
return _page_data;
}
/**
* This comparison method is used to order pages within a book.
*/
INLINE bool VertexDataPage::
operator < (const VertexDataPage &other) const {
// We sort pages so that the pages with the smallest number of available
// contiguous bytes come up first. We store our best estimate of
// continguous bytes here.
if (_book_size != other._book_size) {
return _book_size < other._book_size;
}
// For pages of equal size, we sort based on pointers, to make it easy to
// quickly find a specific page.
return this < &other;
}
/**
* Puts the data in a new ram class. Assumes the page lock is already held.
*/
INLINE void VertexDataPage::
set_ram_class(RamClass rclass) {
_ram_class = rclass;
mark_used_lru(_global_lru[rclass]);
// Changing the ram class might make our effective available space 0 and
// thereby change the placement within the book.
adjust_book_size();
}
/**
* Round page_size up to the next multiple of _block_size.
*/
INLINE size_t VertexDataPage::
round_up(size_t page_size) const {
return ((page_size + _block_size - 1) / _block_size) * _block_size;
}