|
|
@@ -20,6 +20,7 @@
|
|
|
#include "configVariableInt.h"
|
|
|
#include "vertexDataSaveFile.h"
|
|
|
#include "pStatTimer.h"
|
|
|
+#include "mutexHolder.h"
|
|
|
|
|
|
#ifdef HAVE_ZLIB
|
|
|
#include <zlib.h>
|
|
|
@@ -100,6 +101,8 @@ VertexDataBook::
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
VertexDataBlock *VertexDataBook::
|
|
|
alloc(size_t size) {
|
|
|
+ MutexHolder holder(_lock);
|
|
|
+
|
|
|
// First, try to allocate from the last page that worked; then
|
|
|
// continue to the end of the list.
|
|
|
size_t pi = _next_pi;
|
|
|
@@ -175,7 +178,7 @@ VertexDataPage(size_t page_size) : SimpleAllocator(page_size), SimpleLruPage(pag
|
|
|
_size = page_size;
|
|
|
_uncompressed_size = _size;
|
|
|
_total_page_size += _size;
|
|
|
- get_class_type().inc_memory_usage(TypeHandle::MC_array, _size);
|
|
|
+ get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)_size);
|
|
|
set_ram_class(RC_resident);
|
|
|
}
|
|
|
|
|
|
@@ -187,7 +190,7 @@ VertexDataPage(size_t page_size) : SimpleAllocator(page_size), SimpleLruPage(pag
|
|
|
VertexDataPage::
|
|
|
~VertexDataPage() {
|
|
|
_total_page_size -= _size;
|
|
|
- get_class_type().dec_memory_usage(TypeHandle::MC_array, _size);
|
|
|
+ get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_size);
|
|
|
|
|
|
if (_page_data != NULL) {
|
|
|
delete[] _page_data;
|
|
|
@@ -195,10 +198,90 @@ VertexDataPage::
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-// Function: VertexDataPage::make_resident
|
|
|
+// Function: VertexDataPage::alloc
|
|
|
// Access: Published
|
|
|
+// Description: 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.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+VertexDataBlock *VertexDataPage::
|
|
|
+alloc(size_t size) {
|
|
|
+ MutexHolder holder(_lock);
|
|
|
+ check_resident();
|
|
|
+
|
|
|
+ VertexDataBlock *block = (VertexDataBlock *)SimpleAllocator::alloc(size);
|
|
|
+
|
|
|
+ if (block != (VertexDataBlock *)NULL) {
|
|
|
+ // When we allocate a new block within the page, we have to clear
|
|
|
+ // the disk cache (since we have just invalidated it).
|
|
|
+ _saved_block.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ return block;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: VertexDataPage::make_block
|
|
|
+// Access: Protected, Virtual
|
|
|
+// Description: Creates a new SimpleAllocatorBlock object. Override
|
|
|
+// this function to specialize the block type returned.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+SimpleAllocatorBlock *VertexDataPage::
|
|
|
+make_block(size_t start, size_t size) {
|
|
|
+ return new VertexDataBlock(this, start, size);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: VertexDataPage::evict_lru
|
|
|
+// Access: Public, Virtual
|
|
|
+// Description: Evicts the page from the LRU. Called internally when
|
|
|
+// the LRU determines that it is full. May also be
|
|
|
+// called externally when necessary to explicitly evict
|
|
|
+// the page.
|
|
|
+//
|
|
|
+// It is legal for this method to either evict the page
|
|
|
+// as requested, do nothing (in which case the eviction
|
|
|
+// will be requested again at the next epoch), or
|
|
|
+// requeue itself on the tail of the queue (in which
|
|
|
+// case the eviction will be requested again much
|
|
|
+// later).
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void VertexDataPage::
|
|
|
+evict_lru() {
|
|
|
+ MutexHolder holder(_lock);
|
|
|
+
|
|
|
+ switch (_ram_class) {
|
|
|
+ case RC_resident:
|
|
|
+ if (_compressed_lru.get_max_size() == 0) {
|
|
|
+ make_disk();
|
|
|
+ } else {
|
|
|
+ make_compressed();
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case RC_compressed:
|
|
|
+ make_disk();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case RC_disk:
|
|
|
+ gobj_cat.warning()
|
|
|
+ << "Cannot evict array data from disk.\n";
|
|
|
+ break;
|
|
|
+
|
|
|
+ case RC_end_of_list:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: VertexDataPage::make_resident
|
|
|
+// Access: Private
|
|
|
// Description: Moves the page to fully resident status by
|
|
|
// expanding it or reading it from disk as necessary.
|
|
|
+//
|
|
|
+// Assumes the lock is already held.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void VertexDataPage::
|
|
|
make_resident() {
|
|
|
@@ -209,7 +292,7 @@ make_resident() {
|
|
|
}
|
|
|
|
|
|
if (_ram_class == RC_disk) {
|
|
|
- restore_from_disk();
|
|
|
+ do_restore_from_disk();
|
|
|
}
|
|
|
|
|
|
if (_ram_class == RC_compressed) {
|
|
|
@@ -231,14 +314,14 @@ make_resident() {
|
|
|
}
|
|
|
nassertv(dest_len == _uncompressed_size);
|
|
|
|
|
|
- get_class_type().dec_memory_usage(TypeHandle::MC_array, _size);
|
|
|
+ get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_size);
|
|
|
_total_page_size -= _size;
|
|
|
|
|
|
delete[] _page_data;
|
|
|
_page_data = new_data;
|
|
|
_size = _uncompressed_size;
|
|
|
|
|
|
- get_class_type().inc_memory_usage(TypeHandle::MC_array, _size);
|
|
|
+ get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)_size);
|
|
|
_total_page_size += _size;
|
|
|
|
|
|
#endif
|
|
|
@@ -249,9 +332,11 @@ make_resident() {
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: VertexDataPage::make_compressed
|
|
|
-// Access: Published
|
|
|
+// Access: Private
|
|
|
// Description: Moves the page to compressed status by
|
|
|
// compressing it or reading it from disk as necessary.
|
|
|
+//
|
|
|
+// Assumes the lock is already held.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void VertexDataPage::
|
|
|
make_compressed() {
|
|
|
@@ -262,7 +347,7 @@ make_compressed() {
|
|
|
}
|
|
|
|
|
|
if (_ram_class == RC_disk) {
|
|
|
- restore_from_disk();
|
|
|
+ do_restore_from_disk();
|
|
|
}
|
|
|
|
|
|
if (_ram_class == RC_resident) {
|
|
|
@@ -289,14 +374,14 @@ make_compressed() {
|
|
|
unsigned char *new_data = new unsigned char[buffer_size];
|
|
|
memcpy(new_data, buffer, buffer_size);
|
|
|
|
|
|
- get_class_type().dec_memory_usage(TypeHandle::MC_array, _size);
|
|
|
+ get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_size);
|
|
|
_total_page_size -= _size;
|
|
|
|
|
|
delete[] _page_data;
|
|
|
_page_data = new_data;
|
|
|
_size = buffer_size;
|
|
|
|
|
|
- get_class_type().inc_memory_usage(TypeHandle::MC_array, _size);
|
|
|
+ get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)_size);
|
|
|
_total_page_size += _size;
|
|
|
|
|
|
if (gobj_cat.is_debug()) {
|
|
|
@@ -312,9 +397,11 @@ make_compressed() {
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: VertexDataPage::make_disk
|
|
|
-// Access: Published
|
|
|
-// Description: Moves the page to disk status by
|
|
|
-// writing it to disk as necessary.
|
|
|
+// Access: Private
|
|
|
+// Description: Moves the page to disk status by writing it to disk
|
|
|
+// as necessary.
|
|
|
+//
|
|
|
+// Assumes the lock is already held.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void VertexDataPage::
|
|
|
make_disk() {
|
|
|
@@ -325,13 +412,13 @@ make_disk() {
|
|
|
}
|
|
|
|
|
|
if (_ram_class == RC_resident || _ram_class == RC_compressed) {
|
|
|
- if (!save_to_disk()) {
|
|
|
+ if (!do_save_to_disk()) {
|
|
|
// Can't save it to disk for some reason.
|
|
|
mark_used_lru();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- get_class_type().dec_memory_usage(TypeHandle::MC_array, _size);
|
|
|
+ get_class_type().dec_memory_usage(TypeHandle::MC_array, (int)_size);
|
|
|
_total_page_size -= _size;
|
|
|
|
|
|
delete[] _page_data;
|
|
|
@@ -343,17 +430,18 @@ make_disk() {
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-// Function: VertexDataPage::save_to_disk
|
|
|
-// Access: Published
|
|
|
+// Function: VertexDataPage::do_save_to_disk
|
|
|
+// Access: Private
|
|
|
// Description: 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.
|
|
|
//
|
|
|
-// Returns true on success, false on failure.
|
|
|
+// Returns true on success, false on failure. Assumes
|
|
|
+// the lock is already held.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
bool VertexDataPage::
|
|
|
-save_to_disk() {
|
|
|
+do_save_to_disk() {
|
|
|
if (_ram_class == RC_resident || _ram_class == RC_compressed) {
|
|
|
PStatTimer timer(_vdata_save_pcollector);
|
|
|
|
|
|
@@ -382,14 +470,16 @@ save_to_disk() {
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-// Function: VertexDataPage::restore_from_disk
|
|
|
-// Access: Published
|
|
|
+// Function: VertexDataPage::do_restore_from_disk
|
|
|
+// Access: Private
|
|
|
// Description: Restores the page from disk and makes it
|
|
|
// either compressed or resident (according to whether
|
|
|
// it was stored compressed on disk).
|
|
|
+//
|
|
|
+// Assumes the lock is already held.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void VertexDataPage::
|
|
|
-restore_from_disk() {
|
|
|
+do_restore_from_disk() {
|
|
|
if (_ram_class == RC_disk) {
|
|
|
nassertv(_saved_block != (VertexDataSaveBlock *)NULL);
|
|
|
nassertv(_page_data == (unsigned char *)NULL && _size == 0);
|
|
|
@@ -410,7 +500,7 @@ restore_from_disk() {
|
|
|
_page_data = new_data;
|
|
|
_size = buffer_size;
|
|
|
|
|
|
- get_class_type().inc_memory_usage(TypeHandle::MC_array, _size);
|
|
|
+ get_class_type().inc_memory_usage(TypeHandle::MC_array, (int)_size);
|
|
|
_total_page_size += _size;
|
|
|
|
|
|
set_lru_size(_size);
|
|
|
@@ -422,80 +512,6 @@ restore_from_disk() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: VertexDataPage::alloc
|
|
|
-// Access: Published
|
|
|
-// Description: 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.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-VertexDataBlock *VertexDataPage::
|
|
|
-alloc(size_t size) {
|
|
|
- check_resident();
|
|
|
- VertexDataBlock *block = (VertexDataBlock *)SimpleAllocator::alloc(size);
|
|
|
-
|
|
|
- if (block != (VertexDataBlock *)NULL) {
|
|
|
- // When we allocate a new block within the page, we have to clear
|
|
|
- // the disk cache (since we have just invalidated it).
|
|
|
- _saved_block.clear();
|
|
|
- }
|
|
|
-
|
|
|
- return block;
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: VertexDataPage::make_block
|
|
|
-// Access: Protected, Virtual
|
|
|
-// Description: Creates a new SimpleAllocatorBlock object. Override
|
|
|
-// this function to specialize the block type returned.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-SimpleAllocatorBlock *VertexDataPage::
|
|
|
-make_block(size_t start, size_t size) {
|
|
|
- return new VertexDataBlock(this, start, size);
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: VertexDataPage::evict_lru
|
|
|
-// Access: Public, Virtual
|
|
|
-// Description: Evicts the page from the LRU. Called internally when
|
|
|
-// the LRU determines that it is full. May also be
|
|
|
-// called externally when necessary to explicitly evict
|
|
|
-// the page.
|
|
|
-//
|
|
|
-// It is legal for this method to either evict the page
|
|
|
-// as requested, do nothing (in which case the eviction
|
|
|
-// will be requested again at the next epoch), or
|
|
|
-// requeue itself on the tail of the queue (in which
|
|
|
-// case the eviction will be requested again much
|
|
|
-// later).
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-void VertexDataPage::
|
|
|
-evict_lru() {
|
|
|
- switch (_ram_class) {
|
|
|
- case RC_resident:
|
|
|
- if (_compressed_lru.get_max_size() == 0) {
|
|
|
- make_disk();
|
|
|
- } else {
|
|
|
- make_compressed();
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case RC_compressed:
|
|
|
- make_disk();
|
|
|
- break;
|
|
|
-
|
|
|
- case RC_disk:
|
|
|
- gobj_cat.warning()
|
|
|
- << "Cannot evict array data from disk.\n";
|
|
|
- break;
|
|
|
-
|
|
|
- case RC_end_of_list:
|
|
|
- break;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: VertexDataPage::make_save_file
|
|
|
// Access: Private, Static
|