34 #include <boost/format.hpp> 46 ThreadPrivate(T
const& t) : _init(t) {
47 int ret = pthread_key_create(&_key, del);
53 T* d =
reinterpret_cast<T*
>(pthread_getspecific(_key));
56 pthread_setspecific(_key, d);
65 static void del(
void*
data) {
66 T* d =
reinterpret_cast<T*
>(
data);
71 static ThreadPrivate<dafBase::Citizen::memId> perThreadId(1);
72 static ThreadPrivate<bool> perThreadPersistFlag(
false);
77 int ret = pthread_rwlock_init(&_lock, 0);
83 int ret = pthread_rwlock_wrlock(&_lock);
89 int ret = pthread_rwlock_rdlock(&_lock);
90 if (ret == 0)
return true;
91 if (ret == EDEADLK)
return false;
95 int ret = pthread_rwlock_unlock(&_lock);
102 pthread_rwlock_t _lock;
105 static RwLock citizenLock;
109 ReadGuard(RwLock& lock) : _lock(lock) { _mustUnlock = _lock.rdlock(); };
111 if (_mustUnlock) _lock.unlock();
121 WriteGuard(RwLock& lock) : _lock(lock) { _lock.lock(); };
122 ~WriteGuard(
void) { _lock.unlock(); };
150 memId cid = _nextMemIdAndIncrement();
151 WriteGuard guard(citizenLock);
152 if (_shouldPersistCitizens()) {
158 _newId += _newCallback(cid);
164 : _sentinel(magicSentinel), _CitizenId(_addCitizen(this)), _typeName(type.
name()) {}
167 : _sentinel(
magicSentinel), _CitizenId(_addCitizen(this)), _typeName(citizen._typeName) {}
171 WriteGuard guard(citizenLock);
172 if (_CitizenId == _deleteId) {
173 _deleteId += _deleteCallback(
this);
177 (void)_hasBeenCorrupted();
178 _sentinel = 0x0000dead;
180 bool corrupt =
false;
182 WriteGuard guard(citizenLock);
183 size_t nActive = _activeCitizens.
erase(
this);
184 corrupt = nActive > 1 || (nActive == 0 && _persistentCitizens.
erase(
this) != 1);
187 (void)_corruptionCallback(
this);
197 volatile int dummy = 1;
226 WriteGuard guard(citizenLock);
227 _persistentCitizens[
this] = _activeCitizens[
this];
228 _activeCitizens.
erase(
this);
241 if (startingMemId == 0) {
242 ReadGuard guard(citizenLock);
243 return _activeCitizens.
size();
247 ReadGuard guard(citizenLock);
248 for (table::iterator cur = _activeCitizens.
begin(); cur != _activeCitizens.
end(); cur++) {
249 if (cur->first->_CitizenId >= startingMemId) {
262 ReadGuard guard(citizenLock);
267 citizen !=
end; ++citizen) {
268 if ((*citizen)->getId() >= startingMemId) {
269 stream << (*citizen)->repr() <<
"\n";
289 ReadGuard guard(citizenLock);
292 for (table::iterator cur = _activeCitizens.
begin(); cur != _activeCitizens.
end(); cur++) {
293 vec->
push_back(dynamic_cast<Citizen const*>(cur->first));
306 bool dafBase::Citizen::_hasBeenCorrupted()
const {
311 (void)_corruptionCallback(
this);
317 ReadGuard guard(citizenLock);
318 for (table::iterator cur = _activeCitizens.
begin(); cur != _activeCitizens.
end(); cur++) {
319 if (cur->first->_hasBeenCorrupted()) {
323 for (table::iterator cur = _persistentCitizens.
begin(); cur != _persistentCitizens.
end(); cur++) {
324 if (cur->first->_hasBeenCorrupted()) {
339 WriteGuard guard(citizenLock);
349 WriteGuard guard(citizenLock);
385 _deleteCallback = func;
395 _corruptionCallback = func;
433 bool& dafBase::Citizen::_shouldPersistCitizens(
void) {
return perThreadPersistFlag.getRef(); }
441 dafBase::Citizen::table dafBase::Citizen::_activeCitizens;
442 dafBase::Citizen::table dafBase::Citizen::_persistentCitizens;
unsigned long memId
Type of the block's ID.
std::string demangleType(std::string const _typeName)
static int init()
Called once when the memory system is being initialised.
~PersistentCitizenScope()
dafBase::Citizen::memId defaultDeleteCallback(dafBase::Citizen const *ptr)
Default DeleteCallback.
Called once when the memory system is being initialised.
static memCallback setCorruptionCallback(memCallback func)
Set the CorruptionCallback function.
void markPersistent(void)
Mark a Citizen as persistent and not destroyed until process end.
static memId setNewCallbackId(memId id)
Call the NewCallback when block is allocated.
static memNewCallback setNewCallback(memNewCallback func)
Set the NewCallback function.
static bool hasBeenCorrupted()
Check all allocated blocks for corruption.
std::string repr() const
Return a string representation of a Citizen.
dafBase::Citizen::memId defaultNewCallback(dafBase::Citizen::memId const cid)
Default callbacks.
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
static memId setDeleteCallbackId(memId id)
Call the current DeleteCallback when block is deleted.
memId getId() const
Return the Citizen's ID.
memId(* memNewCallback)(const memId cid)
A function used to register a callback.
Citizen(const std::type_info &)
static memCallback setDeleteCallback(memCallback func)
Set the DeleteCallback function.
memId(* memCallback)(const Citizen *ptr)
Citizen is a class that should be among all LSST classes base classes, and handles basic memory manag...
static memId getNextMemId()
Return the memId of the next object to be allocated.
static const std::vector< const Citizen * > * census()
Return a (newly allocated) std::vector of active Citizens sorted by ID.
dafBase::Citizen::memId defaultCorruptionCallback(dafBase::Citizen const *ptr)
Default CorruptionCallback.