00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "copyOnWritePointer.h"
00016 #include "mutexHolder.h"
00017 #include "config_util.h"
00018 #include "config_pipeline.h"
00019
00020 #ifdef COW_THREADED
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 CPT(CopyOnWriteObject) CopyOnWritePointer::
00032 get_read_pointer() const {
00033 if (_object == (CopyOnWriteObject *)NULL) {
00034 return NULL;
00035 }
00036
00037 Thread *current_thread = Thread::get_current_thread();
00038
00039 MutexHolder holder(_object->_lock_mutex);
00040 while (_object->_lock_status == CopyOnWriteObject::LS_locked_write) {
00041 if (_object->_locking_thread == current_thread) {
00042 return _object;
00043 }
00044 if (util_cat.is_debug()) {
00045 util_cat.debug()
00046 << *current_thread << " waiting on " << _object->get_type()
00047 << " " << _object << ", held by " << *_object->_locking_thread
00048 << "\n";
00049 }
00050 _object->_lock_cvar.wait();
00051 }
00052
00053 _object->_lock_status = CopyOnWriteObject::LS_locked_read;
00054 _object->_locking_thread = current_thread;
00055 return _object;
00056 }
00057 #endif // COW_THREADED
00058
00059 #ifdef COW_THREADED
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 PT(CopyOnWriteObject) CopyOnWritePointer::
00074 get_write_pointer() {
00075 if (_object == (CopyOnWriteObject *)NULL) {
00076 return NULL;
00077 }
00078
00079 Thread *current_thread = Thread::get_current_thread();
00080
00081 MutexHolder holder(_object->_lock_mutex);
00082 while (_object->_lock_status == CopyOnWriteObject::LS_locked_write &&
00083 _object->_locking_thread != current_thread) {
00084 if (util_cat.is_debug()) {
00085 util_cat.debug()
00086 << *current_thread << " waiting on " << _object->get_type()
00087 << " " << _object << ", held by " << *_object->_locking_thread
00088 << "\n";
00089 }
00090 _object->_lock_cvar.wait();
00091 }
00092
00093 if (_object->_lock_status == CopyOnWriteObject::LS_locked_read) {
00094 nassertr(_object->get_ref_count() > _object->get_cache_ref_count(), NULL);
00095
00096 if (util_cat.is_debug()) {
00097 util_cat.debug()
00098 << "Making copy of " << _object->get_type()
00099 << " because it is locked in read mode.\n";
00100 }
00101 PT(CopyOnWriteObject) new_object = _object->make_cow_copy();
00102 cache_unref_delete(_object);
00103 _object = new_object;
00104 _object->cache_ref();
00105
00106 } else if (_object->get_cache_ref_count() > 1) {
00107
00108
00109
00110 if (util_cat.is_debug()) {
00111 util_cat.debug()
00112 << "Making copy of " << _object->get_type()
00113 << " because it is shared by " << _object->get_ref_count()
00114 << " pointers.\n";
00115 }
00116
00117 PT(CopyOnWriteObject) new_object = _object->make_cow_copy();
00118 cache_unref_delete(_object);
00119 _object = new_object;
00120 _object->cache_ref();
00121
00122 } else {
00123
00124
00125
00126
00127
00128
00129
00130 }
00131 _object->_lock_status = CopyOnWriteObject::LS_locked_write;
00132 _object->_locking_thread = current_thread;
00133
00134 return _object;
00135 }
00136 #endif // COW_THREADED