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) {
110 _mustUnlock = _lock.rdlock();
113 if (_mustUnlock) _lock.unlock();
123 WriteGuard(RwLock& lock) : _lock(lock) {
155 memId cid = _nextMemIdAndIncrement();
156 WriteGuard guard(citizenLock);
157 if (_shouldPersistCitizens()) {
163 _newId += _newCallback(cid);
169 _sentinel(magicSentinel),
170 _CitizenId(_addCitizen(this)),
171 _typeName(type.name()) {
176 _CitizenId(_addCitizen(this)),
177 _typeName(citizen._typeName) {
182 WriteGuard guard(citizenLock);
183 if (_CitizenId == _deleteId) {
184 _deleteId += _deleteCallback(
this);
188 (void)_hasBeenCorrupted();
189 _sentinel = 0x0000dead;
191 bool corrupt =
false;
193 WriteGuard guard(citizenLock);
194 size_t nActive = _activeCitizens.
erase(
this);
195 corrupt = nActive > 1 ||
196 (nActive == 0 && _persistentCitizens.
erase(
this) != 1);
199 (void)_corruptionCallback(
this);
209 volatile int dummy = 1;
229 return perThreadId.getRef();
234 return perThreadId.getRef()++;
240 return boost::str(boost::format(
"%d: %08x %s")
249 WriteGuard guard(citizenLock);
250 _persistentCitizens[
this] = _activeCitizens[
this];
251 _activeCitizens.
erase(
this);
265 if (startingMemId == 0) {
266 ReadGuard guard(citizenLock);
267 return _activeCitizens.
size();
271 ReadGuard guard(citizenLock);
272 for (table::iterator cur = _activeCitizens.
begin();
273 cur != _activeCitizens.
end(); cur++) {
274 if (cur->first->_CitizenId >= startingMemId) {
288 ReadGuard guard(citizenLock);
293 citizen != end; ++citizen) {
294 if ((*citizen)->getId() >= startingMemId) {
295 stream << (*citizen)->repr() <<
"\n";
319 ReadGuard guard(citizenLock);
322 for (table::iterator cur = _activeCitizens.
begin();
323 cur != _activeCitizens.
end(); cur++) {
324 vec->
push_back(dynamic_cast<Citizen const*>(cur->first));
337 bool dafBase::Citizen::_hasBeenCorrupted()
const {
342 (void)_corruptionCallback(
this);
348 ReadGuard guard(citizenLock);
349 for (table::iterator cur = _activeCitizens.
begin();
350 cur != _activeCitizens.
end(); cur++) {
351 if (cur->first->_hasBeenCorrupted()) {
355 for (table::iterator cur = _persistentCitizens.
begin();
356 cur != _persistentCitizens.
end(); cur++) {
357 if (cur->first->_hasBeenCorrupted()) {
373 WriteGuard guard(citizenLock);
384 WriteGuard guard(citizenLock);
420 _deleteCallback = func;
430 _corruptionCallback = func;
445 std::cerr << boost::format(
"Allocating memId %d\n") % cid;
454 std::cerr << boost::format(
"Deleting memId %s\n") % ptr->
repr();
467 bool& dafBase::Citizen::_shouldPersistCitizens(
void) {
468 return perThreadPersistFlag.getRef();
477 dafBase::Citizen::table dafBase::Citizen::_activeCitizens;
478 dafBase::Citizen::table dafBase::Citizen::_persistentCitizens;
486 Citizen::_shouldPersistCitizens() =
true;
490 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.
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.