open_toontown_panda3d/panda/src/express/weakReferenceList.cxx

102 lines
2.6 KiB
C++

/**
* 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 weakReferenceList.cxx
* @author drose
* @date 2004-09-27
*/
#include "weakReferenceList.h"
#include "weakPointerToVoid.h"
#include "pnotify.h"
/**
*
*/
WeakReferenceList::
WeakReferenceList() : _count(_alive_offset) {
}
/**
* The destructor tells all of the owned references that we're gone.
*/
WeakReferenceList::
~WeakReferenceList() {
nassertv(_count == 0);
}
/**
* Adds the callback to the list of callbacks that will be called when the
* underlying pointer is deleted. If it has already been deleted, it will
* be called immediately.
*
* The data pointer can be an arbitrary pointer and is passed as only argument
* to the callback.
*
* @since 1.10.0
*/
void WeakReferenceList::
add_callback(WeakPointerCallback *callback, void *data) {
nassertv(callback != nullptr);
_lock.lock();
// We need to check again whether the object is deleted after grabbing the
// lock, despite having already done this in weakPointerTo.I, since it may
// have been deleted in the meantime.
bool deleted = was_deleted();
if (!deleted) {
_callbacks.insert(std::make_pair(callback, data));
}
_lock.unlock();
if (deleted) {
callback->wp_callback(data);
}
}
/**
* Intended to be called only by WeakPointerTo (or by any class implementing a
* weak reference-counting pointer), this removes the indicated PointerToVoid
* structure from the list of such structures that are maintaining a weak
* pointer to this object.
*
* @since 1.10.0
*/
void WeakReferenceList::
remove_callback(WeakPointerCallback *callback) {
nassertv(callback != nullptr);
_lock.lock();
_callbacks.erase(callback);
_lock.unlock();
}
/**
* Called only by the ReferenceCount pointer to indicate that it has been
* deleted.
*
* @since 1.10.0
*/
void WeakReferenceList::
mark_deleted() {
_lock.lock();
Callbacks::iterator ci;
for (ci = _callbacks.begin(); ci != _callbacks.end(); ++ci) {
(*ci).first->wp_callback((*ci).second);
}
_callbacks.clear();
// Decrement the special offset added to the weak pointer count to indicate
// that it can be deleted when all the weak references have gone.
AtomicAdjust::Integer result = AtomicAdjust::add(_count, -_alive_offset);
_lock.unlock();
if (result == 0) {
// There are no weak references remaining either, so delete this.
delete this;
}
nassertv(result >= 0);
}