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;
220 return boost::str(boost::format(
"%d: %08x %s") % _CitizenId %
this %
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;
410 std::cerr << boost::format(
"Allocating memId %d\n") % cid;
419 std::cerr << boost::format(
"Deleting memId %s\n") % ptr->
repr();
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)
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.