34 #include <boost/format.hpp> 47 ThreadPrivate(T
const& t) : _init(t) {
48 int ret = pthread_key_create(&_key, del);
51 "Could not create key");
55 T* d =
reinterpret_cast<T*
>(pthread_getspecific(_key));
58 pthread_setspecific(_key, d);
67 static void del(
void* data) {
68 T* d =
reinterpret_cast<T*
>(data);
73 static ThreadPrivate<dafBase::Citizen::memId> perThreadId(1);
74 static ThreadPrivate<bool> perThreadPersistFlag(
false);
79 int ret = pthread_rwlock_init(&_lock, 0);
82 "Could not create Citizen lock");
86 int ret = pthread_rwlock_wrlock(&_lock);
89 "Could not acquire Citizen write lock");
93 int ret = pthread_rwlock_rdlock(&_lock);
94 if (ret == 0)
return true;
95 if (ret == EDEADLK)
return false;
97 "Could not acquire Citizen read lock");
100 int ret = pthread_rwlock_unlock(&_lock);
103 "Could not release Citizen lock");
108 pthread_rwlock_t _lock;
111 static RwLock citizenLock;
115 ReadGuard(RwLock& lock) : _lock(lock) {
116 _mustUnlock = _lock.rdlock();
119 if (_mustUnlock) _lock.unlock();
129 WriteGuard(RwLock& lock) : _lock(lock) {
161 memId cid = _nextMemIdAndIncrement();
162 WriteGuard guard(citizenLock);
163 if (_shouldPersistCitizens()) {
169 _newId += _newCallback(cid);
175 _sentinel(magicSentinel),
176 _CitizenId(_addCitizen(this)),
177 _typeName(type.name()) {
182 _CitizenId(_addCitizen(this)),
183 _typeName(citizen._typeName) {
188 WriteGuard guard(citizenLock);
189 if (_CitizenId == _deleteId) {
190 _deleteId += _deleteCallback(
this);
194 (void)_hasBeenCorrupted();
195 _sentinel = 0x0000dead;
197 bool corrupt =
false;
199 WriteGuard guard(citizenLock);
200 size_t nActive = _activeCitizens.
erase(
this);
201 corrupt = nActive > 1 ||
202 (nActive == 0 && _persistentCitizens.
erase(
this) != 1);
205 (void)_corruptionCallback(
this);
215 volatile int dummy = 1;
235 return perThreadId.getRef();
240 return perThreadId.getRef()++;
246 return boost::str(boost::format(
"%d: %08x %s")
255 WriteGuard guard(citizenLock);
256 _persistentCitizens[
this] = _activeCitizens[
this];
257 _activeCitizens.
erase(
this);
271 if (startingMemId == 0) {
272 ReadGuard guard(citizenLock);
273 return _activeCitizens.
size();
277 ReadGuard guard(citizenLock);
278 for (table::iterator cur = _activeCitizens.
begin();
279 cur != _activeCitizens.
end(); cur++) {
280 if (cur->first->_CitizenId >= startingMemId) {
294 ReadGuard guard(citizenLock);
299 citizen != end; ++citizen) {
300 if ((*citizen)->getId() >= startingMemId) {
301 stream << (*citizen)->repr() <<
"\n";
325 ReadGuard guard(citizenLock);
328 for (table::iterator cur = _activeCitizens.
begin();
329 cur != _activeCitizens.
end(); cur++) {
330 vec->
push_back(dynamic_cast<Citizen const*>(cur->first));
343 bool dafBase::Citizen::_hasBeenCorrupted()
const {
348 (void)_corruptionCallback(
this);
354 ReadGuard guard(citizenLock);
355 for (table::iterator cur = _activeCitizens.
begin();
356 cur != _activeCitizens.
end(); cur++) {
357 if (cur->first->_hasBeenCorrupted()) {
361 for (table::iterator cur = _persistentCitizens.
begin();
362 cur != _persistentCitizens.
end(); cur++) {
363 if (cur->first->_hasBeenCorrupted()) {
379 WriteGuard guard(citizenLock);
390 WriteGuard guard(citizenLock);
426 _deleteCallback = func;
436 _corruptionCallback = func;
451 std::cerr << boost::format(
"Allocating memId %d\n") % cid;
460 std::cerr << boost::format(
"Deleting memId %s\n") % ptr->
repr();
469 str(boost::format(
"Citizen \"%s\" is corrupted") % ptr->
repr()));
474 bool& dafBase::Citizen::_shouldPersistCitizens(
void) {
475 return perThreadPersistFlag.getRef();
484 dafBase::Citizen::table dafBase::Citizen::_activeCitizens;
485 dafBase::Citizen::table dafBase::Citizen::_persistentCitizens;
493 Citizen::_shouldPersistCitizens() =
true;
497 Citizen::_shouldPersistCitizens() =
false;
unsigned long memId
Type of the block's ID.
std::string demangleType(std::string const _typeName)
dafBase::Citizen::memId defaultDeleteCallback(dafBase::Citizen const *ptr)
Default DeleteCallback.
static int init()
Called once when the memory system is being initialised.
~PersistentCitizenScope()
dafBase::Citizen::memId defaultNewCallback(dafBase::Citizen::memId const cid)
Default callbacks.
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.
static memId setDeleteCallbackId(memId id)
Call the current DeleteCallback when block is deleted.
memId getId() const
Return the Citizen's ID.
#define LSST_EXCEPT(type,...)
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...
dafBase::Citizen::memId defaultCorruptionCallback(dafBase::Citizen const *ptr)
Default CorruptionCallback.
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.