mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
Fix rare mutex error at shutdown: "MutexPosixImpl::acquire(): Assertion `result == 0' failed."
This commit is contained in:
parent
7a681dc993
commit
b486de2700
@ -15,9 +15,7 @@
|
|||||||
#include "lightMutexHolder.h"
|
#include "lightMutexHolder.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
GraphicsStateGuardianBase::GSGs GraphicsStateGuardianBase::_gsgs;
|
AtomicAdjust::Pointer GraphicsStateGuardianBase::_gsg_list;
|
||||||
GraphicsStateGuardianBase *GraphicsStateGuardianBase::_default_gsg;
|
|
||||||
LightMutex GraphicsStateGuardianBase::_lock;
|
|
||||||
TypeHandle GraphicsStateGuardianBase::_type_handle;
|
TypeHandle GraphicsStateGuardianBase::_type_handle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,8 +28,13 @@ TypeHandle GraphicsStateGuardianBase::_type_handle;
|
|||||||
*/
|
*/
|
||||||
GraphicsStateGuardianBase *GraphicsStateGuardianBase::
|
GraphicsStateGuardianBase *GraphicsStateGuardianBase::
|
||||||
get_default_gsg() {
|
get_default_gsg() {
|
||||||
LightMutexHolder holder(_lock);
|
GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list);
|
||||||
return _default_gsg;
|
if (gsg_list == NULL) {
|
||||||
|
// Nobody created a GSG list, so we won't have any GSGs either.
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
LightMutexHolder holder(gsg_list->_lock);
|
||||||
|
return gsg_list->_default_gsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,22 +43,35 @@ get_default_gsg() {
|
|||||||
*/
|
*/
|
||||||
void GraphicsStateGuardianBase::
|
void GraphicsStateGuardianBase::
|
||||||
set_default_gsg(GraphicsStateGuardianBase *default_gsg) {
|
set_default_gsg(GraphicsStateGuardianBase *default_gsg) {
|
||||||
LightMutexHolder holder(_lock);
|
GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list);
|
||||||
if (find(_gsgs.begin(), _gsgs.end(), default_gsg) == _gsgs.end()) {
|
if (gsg_list == NULL) {
|
||||||
|
// Nobody ever created a GSG list. How could we have a GSG?
|
||||||
|
nassertv(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LightMutexHolder holder(gsg_list->_lock);
|
||||||
|
if (find(gsg_list->_gsgs.begin(), gsg_list->_gsgs.end(), default_gsg) == gsg_list->_gsgs.end()) {
|
||||||
// The specified GSG doesn't exist or it has already destructed.
|
// The specified GSG doesn't exist or it has already destructed.
|
||||||
nassertv(false);
|
nassertv(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_default_gsg = default_gsg;
|
gsg_list->_default_gsg = default_gsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the total number of GSG's in the universe.
|
* Returns the total number of GSG's in the universe.
|
||||||
*/
|
*/
|
||||||
int GraphicsStateGuardianBase::
|
size_t GraphicsStateGuardianBase::
|
||||||
get_num_gsgs() {
|
get_num_gsgs() {
|
||||||
return _gsgs.size();
|
GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list);
|
||||||
|
if (gsg_list == NULL) {
|
||||||
|
// Nobody created a GSG list, so we won't have any GSGs either.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LightMutexHolder holder(gsg_list->_lock);
|
||||||
|
return gsg_list->_gsgs.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,9 +79,13 @@ get_num_gsgs() {
|
|||||||
* and remove themselves from this list as they are created and destroyed.
|
* and remove themselves from this list as they are created and destroyed.
|
||||||
*/
|
*/
|
||||||
GraphicsStateGuardianBase *GraphicsStateGuardianBase::
|
GraphicsStateGuardianBase *GraphicsStateGuardianBase::
|
||||||
get_gsg(int n) {
|
get_gsg(size_t n) {
|
||||||
nassertr(n >= 0 && n < (int)_gsgs.size(), NULL);
|
GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list);
|
||||||
return _gsgs[n];
|
nassertr(gsg_list != NULL, NULL);
|
||||||
|
|
||||||
|
LightMutexHolder holder(gsg_list->_lock);
|
||||||
|
nassertr(n < gsg_list->_gsgs.size(), NULL);
|
||||||
|
return gsg_list->_gsgs[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,17 +94,32 @@ get_gsg(int n) {
|
|||||||
*/
|
*/
|
||||||
void GraphicsStateGuardianBase::
|
void GraphicsStateGuardianBase::
|
||||||
add_gsg(GraphicsStateGuardianBase *gsg) {
|
add_gsg(GraphicsStateGuardianBase *gsg) {
|
||||||
LightMutexHolder holder(_lock);
|
GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list);
|
||||||
|
if (gsg_list == NULL) {
|
||||||
|
gsg_list = new GSGList;
|
||||||
|
gsg_list->_default_gsg = NULL;
|
||||||
|
|
||||||
if (find(_gsgs.begin(), _gsgs.end(), gsg) != _gsgs.end()) {
|
GSGList *orig_gsg_list = (GSGList *)
|
||||||
|
AtomicAdjust::compare_and_exchange_ptr(_gsg_list, NULL, gsg_list);
|
||||||
|
|
||||||
|
if (orig_gsg_list != NULL) {
|
||||||
|
// Another thread beat us to it. No problem, we'll use that.
|
||||||
|
delete gsg_list;
|
||||||
|
gsg_list = orig_gsg_list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LightMutexHolder holder(gsg_list->_lock);
|
||||||
|
|
||||||
|
if (find(gsg_list->_gsgs.begin(), gsg_list->_gsgs.end(), gsg) != gsg_list->_gsgs.end()) {
|
||||||
// Already on the list.
|
// Already on the list.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_gsgs.push_back(gsg);
|
gsg_list->_gsgs.push_back(gsg);
|
||||||
|
|
||||||
if (_default_gsg == (GraphicsStateGuardianBase *)NULL) {
|
if (gsg_list->_default_gsg == (GraphicsStateGuardianBase *)NULL) {
|
||||||
_default_gsg = gsg;
|
gsg_list->_default_gsg = gsg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,21 +128,28 @@ add_gsg(GraphicsStateGuardianBase *gsg) {
|
|||||||
*/
|
*/
|
||||||
void GraphicsStateGuardianBase::
|
void GraphicsStateGuardianBase::
|
||||||
remove_gsg(GraphicsStateGuardianBase *gsg) {
|
remove_gsg(GraphicsStateGuardianBase *gsg) {
|
||||||
LightMutexHolder holder(_lock);
|
GSGList *gsg_list = (GSGList *)AtomicAdjust::get_ptr(_gsg_list);
|
||||||
|
if (gsg_list == NULL) {
|
||||||
|
// No GSGs were added yet, or the program is destructing anyway.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GSGs::iterator gi = find(_gsgs.begin(), _gsgs.end(), gsg);
|
LightMutexHolder holder(gsg_list->_lock);
|
||||||
if (gi == _gsgs.end()) {
|
|
||||||
|
GSGList::GSGs::iterator gi;
|
||||||
|
gi = find(gsg_list->_gsgs.begin(), gsg_list->_gsgs.end(), gsg);
|
||||||
|
if (gi == gsg_list->_gsgs.end()) {
|
||||||
// Already removed, or never added.
|
// Already removed, or never added.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_gsgs.erase(gi);
|
gsg_list->_gsgs.erase(gi);
|
||||||
|
|
||||||
if (_default_gsg == gsg) {
|
if (gsg_list->_default_gsg == gsg) {
|
||||||
if (!_gsgs.empty()) {
|
if (!gsg_list->_gsgs.empty()) {
|
||||||
_default_gsg = *_gsgs.begin();
|
gsg_list->_default_gsg = *gsg_list->_gsgs.begin();
|
||||||
} else {
|
} else {
|
||||||
_default_gsg = NULL;
|
gsg_list->_default_gsg = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,8 +223,8 @@ PUBLISHED:
|
|||||||
static GraphicsStateGuardianBase *get_default_gsg();
|
static GraphicsStateGuardianBase *get_default_gsg();
|
||||||
static void set_default_gsg(GraphicsStateGuardianBase *default_gsg);
|
static void set_default_gsg(GraphicsStateGuardianBase *default_gsg);
|
||||||
|
|
||||||
static int get_num_gsgs();
|
static size_t get_num_gsgs();
|
||||||
static GraphicsStateGuardianBase *get_gsg(int n);
|
static GraphicsStateGuardianBase *get_gsg(size_t n);
|
||||||
MAKE_SEQ(get_gsgs, get_num_gsgs, get_gsg);
|
MAKE_SEQ(get_gsgs, get_num_gsgs, get_gsg);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -232,10 +232,14 @@ public:
|
|||||||
static void remove_gsg(GraphicsStateGuardianBase *gsg);
|
static void remove_gsg(GraphicsStateGuardianBase *gsg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef pvector<GraphicsStateGuardianBase *> GSGs;
|
struct GSGList {
|
||||||
static GSGs _gsgs;
|
LightMutex _lock;
|
||||||
static GraphicsStateGuardianBase *_default_gsg;
|
|
||||||
static LightMutex _lock;
|
typedef pvector<GraphicsStateGuardianBase *> GSGs;
|
||||||
|
GSGs _gsgs;
|
||||||
|
GraphicsStateGuardianBase *_default_gsg;
|
||||||
|
};
|
||||||
|
static AtomicAdjust::Pointer _gsg_list;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user