ATLAS Offline Software
Public Member Functions | Protected Member Functions | Protected Attributes | Static Protected Attributes | Friends | List of all members
ObjContainer< T_Obj > Class Template Reference

Helper classes to manage shared objects in a scope. More...

#include <ObjContainer.h>

Collaboration diagram for ObjContainer< T_Obj >:

Public Member Functions

 ObjContainer (unsigned int min_size=0)
 
 ~ObjContainer () noexcept(false)
 
bool isValid (ObjRef ref) const
 
std::pair< short, bool > search (T_Obj *obj) const
 
unsigned short size () const
 Return the current number of slots on the container. More...
 

Protected Member Functions

ObjRef registerObj (T_Obj &obj)
 Manage an external object. More...
 
ObjRef registerObj (T_Obj *obj)
 manage a new object. More...
 
ObjRef share (ObjRef ref)
 Increase the share count of a given object. More...
 
void drop (ObjRef &ref)
 Decrease the share count of the referenced object and eventually destroy it. More...
 
const T_Obj * get (ObjRef ref) const
 Get a pointer to a managed object. More...
 
T_Obj * get (ObjRef ref)
 Get a pointer to a managed object. More...
 
T_Obj * release (ObjRef ref)
 Remove ownership over the given object from the container. More...
 
bool isOwned (ObjRef ref) const
 Return true if this container owns the object. More...
 
bool isShared (ObjRef ref) const
 Return true if the object is referred to by more than one ObjPtr. More...
 
bool isExtern (ObjRef ref) const
 Return true if the object is external i.e. More...
 
short count (ObjRef ref) const
 
ObjRef find (T_Obj *obj) const
 Search for an object in the container. More...
 
void ensureValidity (ObjRef ref) const
 Will throw an exception if the reference is not valid. More...
 
void ensureExists (ObjRef ref) const
 Will throw an exception if the referenced object does not exist. More...
 
void checkCapacity ()
 Will throw an exception if the maximum capacity of the container is exceeded. More...
 
ObjRef registerObj (T_Obj *obj, short initial_count)
 Register an object with a given state (external, released, shared) More...
 

Protected Attributes

std::vector< std::pair< T_Obj *, short > > m_objs
 The storage for the object pointers. More...
 
unsigned short m_freeIdx =std::numeric_limits<unsigned short>::max()
 

Static Protected Attributes

constexpr static short s_externalObj = -2
 "share count" of external objects More...
 
constexpr static short s_releasedObj = -1
 "share count" of released objects More...
 

Friends

template<class T_Obj_ >
class ObjPtr
 

Detailed Description

template<class T_Obj>
class ObjContainer< T_Obj >

Helper classes to manage shared objects in a scope.

Container for managed objects.

Implements smart pointer which allow mixing external i.e. unmanaged resources, resources which are shared or released ( out of the scope.). The pointer to all objects are stored in a central container which tags external and released resources and performs reference counting for shared resources. Non external or released resources are freed if the container goes out scope.

The template cloneObj may have to be specialised if the copy constructor of the container object base class does not properly clone the managed objects.

Objects can be either external (unmanaged), released (ownership changed to external), or shared. The methods of this class are mostly not meant to be used directly but rather through ObjPtr. Managed objects are referred to by ObjPtr and references (ObjRef) to the objects can be passed functions. While ObjPtr guarantee that objects stay alive, the references ObjRef do not provide such guarantees.

For example:

* using Cont = ObjContainer<...>;
* using Ptr  = ObjPtr<...>;
* using Ref  = ObjRef<...>;
* ... inner(Cont &cont, Ref ref) {
*    Ptr b_ptr(cont,ref);
*    ...
* }
* ... outer() {
*    Cont cont;
*    Ptr a_ptr(cont, ...);
*    inner(cont, a_ptr.index());
*    ...
* }
* 

Lifetime guarantee of object referred to by a_ptr in outer, provided because the instance a_ptr will stay alive while inner is called, thus ref will point to a valid object in the container.

This will not work:

* ... inner(Cont &cont, Ref ref) {
*    Ptr b_ptr(cont,ref);
*    ...
* }
* ... outer() {
*    Cont cont;
*    Ref dangling_ref;
*    {
*      Ptr a_ptr(cont, ...);
*      dangling_ref=a_ptr.index(); // BAD: dangling_ref has wider scope than a_ptr
*    }
*    // object referred to by a_ptr / dangling_ref got deleted
*    // thus dangling_ref now refers to an invalid object.
*    inner(cont, dangling_ref);
*    ...
* }
* 

Definition at line 30 of file ObjContainer.h.

Constructor & Destructor Documentation

◆ ObjContainer()

template<class T_Obj >
ObjContainer< T_Obj >::ObjContainer ( unsigned int  min_size = 0)
inline

Definition at line 215 of file ObjContainer.h.

215 { m_objs.reserve(min_size); }

◆ ~ObjContainer()

template<class T_Obj >
ObjContainer< T_Obj >::~ObjContainer ( )
inlinenoexcept

Definition at line 217 of file ObjContainer.h.

217  {
218  for (std::pair<T_Obj *, short> &elm : m_objs) {
219  if (elm.second>0) {
220  this->throwObjectStillAlive(elm.first,static_cast<size_t>(elm.second));
221  }
222  if (elm.first && elm.second>0) {
223  this->throwObjectStillAlive(elm.first,static_cast<size_t>(elm.second));
224  }
225  }
226  }

Member Function Documentation

◆ checkCapacity()

template<class T_Obj >
void ObjContainer< T_Obj >::checkCapacity ( )
inlineprotected

Will throw an exception if the maximum capacity of the container is exceeded.

Definition at line 412 of file ObjContainer.h.

412  {
414  this->throwMaximumCapacitiyExceeded(m_objs.size());
415  }
416  }

◆ count()

template<class T_Obj >
short ObjContainer< T_Obj >::count ( ObjRef  ref) const
inlineprotected

Definition at line 374 of file ObjContainer.h.

374  {
375  return m_objs[ref.idx() ].second;
376  }

◆ drop()

template<class T_Obj >
void ObjContainer< T_Obj >::drop ( ObjRef ref)
inlineprotected

Decrease the share count of the referenced object and eventually destroy it.

Will destroy "shared" objects if the share count drops to zero, but external or released objects will not be touched.

Definition at line 289 of file ObjContainer.h.

289  {
291  switch(m_objs[ref.idx()].second) {
292  case s_externalObj: { return ; }
293 
294  case s_releasedObj: { this->warnShareDropAfterRelease( ref.idx() );
295  return ; }
296 
297  case 0: this->throwObjectAlreadyDeleted( ref.idx());
298  [[fallthrough]]; // throws exception
299 
300  default: { break; }
301  }
302 
303  if (--(m_objs[ref.idx()].second) == 0) {
304  T_Obj *obj=m_objs[ref.idx()].first;
305  delete obj;
306  m_objs[ref.idx()].first=nullptr;
307  assert(!find(obj)); // Ensure that deleted objects are not referenced anymore
309  m_freeIdx=ref.idx();
310  }
311  ref= ObjRef();
312  }
313  }

◆ ensureExists()

template<class T_Obj >
void ObjContainer< T_Obj >::ensureExists ( ObjRef  ref) const
inlineprotected

Will throw an exception if the referenced object does not exist.

Definition at line 405 of file ObjContainer.h.

405  {
407  if (m_objs[ref.idx() ].second == 0) { this->throwObjectAlreadyDeleted( ref.idx()); }
408  }

◆ ensureValidity()

template<class T_Obj >
void ObjContainer< T_Obj >::ensureValidity ( ObjRef  ref) const
inlineprotected

Will throw an exception if the reference is not valid.

Definition at line 399 of file ObjContainer.h.

399  {
400  if (!isValid(ref)) this->throwInvalidObject( ref.idx(), m_objs.size());
401  }

◆ find()

template<class T_Obj >
ObjRef ObjContainer< T_Obj >::find ( T_Obj *  obj) const
inlineprotected

Search for an object in the container.

Returns
a valid reference if the object is found or otherwise an invalid reference.

Definition at line 382 of file ObjContainer.h.

382  {
383  for (typename std::vector< std::pair<T_Obj *, short> >::const_reverse_iterator
384  iter =m_objs.rbegin();
385  iter != m_objs.rend();
386  ++iter) {
387  if (iter->first == obj) {
388  assert( m_objs.at(m_objs.rend()-iter-1).first == obj);
389  ObjRef ref( static_cast<unsigned short>(m_objs.rend()-iter-1) ); // @TODO std::distance ?
391  return ref;
392  }
393  }
394  return ObjRef();
395  }

◆ get() [1/2]

template<class T_Obj >
T_Obj* ObjContainer< T_Obj >::get ( ObjRef  ref)
inlineprotected

Get a pointer to a managed object.

Parameters
refreference to the object.
Exceptions
ifthe reference is invalid or the object does not exist.

Definition at line 328 of file ObjContainer.h.

328  {
329  ensureExists(ref);
330  return m_objs[ref.idx()].first;
331  }

◆ get() [2/2]

template<class T_Obj >
const T_Obj* ObjContainer< T_Obj >::get ( ObjRef  ref) const
inlineprotected

Get a pointer to a managed object.

Parameters
refreference to the object.
Exceptions
ifthe reference is invalid or the object does not exist.

Definition at line 319 of file ObjContainer.h.

319  {
320  ensureExists(ref);
321  return m_objs[ref.idx()].first;
322  }

◆ isExtern()

template<class T_Obj >
bool ObjContainer< T_Obj >::isExtern ( ObjRef  ref) const
inlineprotected

Return true if the object is external i.e.

not owned by this container.

Definition at line 370 of file ObjContainer.h.

370  {
371  return count(ref) == s_externalObj;
372  }

◆ isOwned()

template<class T_Obj >
bool ObjContainer< T_Obj >::isOwned ( ObjRef  ref) const
inlineprotected

Return true if this container owns the object.

Definition at line 358 of file ObjContainer.h.

358  {
359  return count(ref) == 1;
360  }

◆ isShared()

template<class T_Obj >
bool ObjContainer< T_Obj >::isShared ( ObjRef  ref) const
inlineprotected

Return true if the object is referred to by more than one ObjPtr.

Definition at line 364 of file ObjContainer.h.

364  {
365  return count(ref) > 1;
366  }

◆ isValid()

template<class T_Obj >
bool ObjContainer< T_Obj >::isValid ( ObjRef  ref) const
inline

Definition at line 228 of file ObjContainer.h.

228  {
229  return ref.idx() < m_objs.size() && m_objs[ref.idx()].first; // @TODO the latter test should not be necessary
230  }

◆ registerObj() [1/3]

template<class T_Obj >
ObjRef ObjContainer< T_Obj >::registerObj ( T_Obj &  obj)
inlineprotected

Manage an external object.

Parameters
objto an external object. The ownership is not taken by the container.

Definition at line 247 of file ObjContainer.h.

247  {
248  return registerObj(&obj, s_externalObj);
249  }

◆ registerObj() [2/3]

template<class T_Obj >
ObjRef ObjContainer< T_Obj >::registerObj ( T_Obj *  obj)
inlineprotected

manage a new object.

Parameters
objthe object to be managed. This passes ownership to the container.

Definition at line 255 of file ObjContainer.h.

255  {
256  return registerObj(obj, 0);
257  }

◆ registerObj() [3/3]

template<class T_Obj >
ObjRef ObjContainer< T_Obj >::registerObj ( T_Obj *  obj,
short  initial_count 
)
inlineprotected

Register an object with a given state (external, released, shared)

Definition at line 420 of file ObjContainer.h.

420  {
421  if (!obj) return ObjRef{};
422  checkCapacity();
423 
424  ObjRef ref = find(obj);
425  if (isValid(ref)) {
426  switch(m_objs.at(ref.idx()).second) {
427  case 0: {
428  break;
429  }
430  case s_releasedObj:
431  if (initial_count == s_externalObj) {
432  break;
433  }
434  [[fallthrough]];
435  default:
436  this->throwObjectExistsAlready( obj);
437  }
438  // return ref;
439  }
440  if (m_freeIdx == std::numeric_limits<unsigned short>::max() && m_objs.size() >= m_objs.capacity()) {
441  for (typename std::vector< std::pair<T_Obj *, short> >::const_reverse_iterator
442  iter =m_objs.rbegin();
443  iter != m_objs.rend();
444  ++iter) {
445  if (iter->second==0) {
446  m_freeIdx=m_objs.rend()-iter-1;
447  }
448  }
449  }
451  ref=ObjRef(static_cast<unsigned short>(m_objs.size()));
452  m_objs.push_back(std::make_pair(obj, initial_count));
453  } else {
454  m_objs[m_freeIdx] = std::make_pair( obj,initial_count);
457  }
459  return ref;
460  }

◆ release()

template<class T_Obj >
T_Obj* ObjContainer< T_Obj >::release ( ObjRef  ref)
inlineprotected

Remove ownership over the given object from the container.

Parameters
refreference to the object.
Exceptions
willthrow an exception if the reference is invalid. Will remove ownership over the referenced object from the container. The object is still accessible like an external object. Thus, it is up to the user to ensure that released objects remain alive at least as long as the object container. If the object is an external object or was released already a clone is created.

Definition at line 341 of file ObjContainer.h.

341  {
343  switch (m_objs[ref.idx() ].second) {
344  case 0: this->throwObjectAlreadyDeleted( ref.idx());
345  [[fallthrough]]; // will not fall through, because of exception
346  case s_releasedObj:
347  [[fallthrough]]; // indeed, should also clone the object
348  case s_externalObj: return cloneObj(m_objs[ref.idx()].first);
349  default:
350  m_objs[ref.idx()].second = s_releasedObj;
351 
352  return m_objs[ref.idx()].first;
353  }
354  }

◆ search()

template<class T_Obj >
std::pair<short, bool > ObjContainer< T_Obj >::search ( T_Obj *  obj) const
inline

Definition at line 233 of file ObjContainer.h.

233  {
234  ObjRef ref(find(obj));
235  return std::make_pair( ref ? m_objs[ref.idx()].second : short{}, ref.isValid() );
236  }

◆ share()

template<class T_Obj >
ObjRef ObjContainer< T_Obj >::share ( ObjRef  ref)
inlineprotected

Increase the share count of a given object.

Parameters
refa reference to the object that is to be shared.

Definition at line 262 of file ObjContainer.h.

262  {
264  switch(m_objs[ref.idx()].second) {
265  case s_externalObj: { return ref; }
266 
267  case s_releasedObj: { this->warnShareDropAfterRelease( ref.idx() );
268 
269  return ref; }
270 
271  case 0: if (!m_objs[ref.idx()].first) {this->throwObjectAlreadyDeleted( ref.idx());}
272  [[fallthrough]]; // throws exception
273 
274  default: { break; }
275  }
276 
277  if (m_objs[ref.idx()].second >= std::numeric_limits<short>::max()) {
278  this->throwMaximumNumberOfSharesExceeded(std::numeric_limits<short>::max()); // clone object and add new slot ?
279  }
280  ++(m_objs[ref.idx()].second);
281 
282  return ref;
283  }

◆ size()

template<class T_Obj >
unsigned short ObjContainer< T_Obj >::size ( ) const
inline

Return the current number of slots on the container.

Not each slot may point to an object.

Definition at line 241 of file ObjContainer.h.

241 { return static_cast<unsigned short>(m_objs.size()); }

Friends And Related Function Documentation

◆ ObjPtr

template<class T_Obj >
template<class T_Obj_ >
friend class ObjPtr
friend

Definition at line 213 of file ObjContainer.h.

Member Data Documentation

◆ m_freeIdx

template<class T_Obj >
unsigned short ObjContainer< T_Obj >::m_freeIdx =std::numeric_limits<unsigned short>::max()
protected

Definition at line 466 of file ObjContainer.h.

◆ m_objs

template<class T_Obj >
std::vector< std::pair<T_Obj *, short> > ObjContainer< T_Obj >::m_objs
protected

The storage for the object pointers.

Definition at line 465 of file ObjContainer.h.

◆ s_externalObj

template<class T_Obj >
constexpr static short ObjContainer< T_Obj >::s_externalObj = -2
staticconstexprprotected

"share count" of external objects

Definition at line 462 of file ObjContainer.h.

◆ s_releasedObj

template<class T_Obj >
constexpr static short ObjContainer< T_Obj >::s_releasedObj = -1
staticconstexprprotected

"share count" of released objects

Definition at line 463 of file ObjContainer.h.


The documentation for this class was generated from the following file:
ObjContainer::s_externalObj
constexpr static short s_externalObj
"share count" of external objects
Definition: ObjContainer.h:462
max
#define max(a, b)
Definition: cfImp.cxx:41
cloneObj
T_Obj * cloneObj(const T_Obj *obj)
Template to be specialised if object cloning is not handled by the copy operator of the container obj...
Definition: ObjContainer.h:42
ObjContainer::s_releasedObj
constexpr static short s_releasedObj
"share count" of released objects
Definition: ObjContainer.h:463
ObjContainer::ensureValidity
void ensureValidity(ObjRef ref) const
Will throw an exception if the reference is not valid.
Definition: ObjContainer.h:399
ObjContainer::checkCapacity
void checkCapacity()
Will throw an exception if the maximum capacity of the container is exceeded.
Definition: ObjContainer.h:412
ObjContainer::m_freeIdx
unsigned short m_freeIdx
Definition: ObjContainer.h:466
ObjContainer::registerObj
ObjRef registerObj(T_Obj &obj)
Manage an external object.
Definition: ObjContainer.h:247
ObjContainer::isValid
bool isValid(ObjRef ref) const
Definition: ObjContainer.h:228
ObjContainer::m_objs
std::vector< std::pair< T_Obj *, short > > m_objs
The storage for the object pointers.
Definition: ObjContainer.h:465
ObjContainer::find
ObjRef find(T_Obj *obj) const
Search for an object in the container.
Definition: ObjContainer.h:382
ObjRef
Helper class to refer to objects in the container ObjContainer.
Definition: ObjContainer.h:61
ref
const boost::regex ref(r_ef)
ObjContainer::count
short count(ObjRef ref) const
Definition: ObjContainer.h:374
ObjContainer::ensureExists
void ensureExists(ObjRef ref) const
Will throw an exception if the referenced object does not exist.
Definition: ObjContainer.h:405
python.PyAthena.obj
obj
Definition: PyAthena.py:132