Source: ../../libxorp/ref_ptr.hh
|
|
|
|
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// Copyright (c) 2001-2003 International Computer Science Institute
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software")
// to deal in the Software without restriction, subject to the conditions
// listed in the XORP LICENSE file. These conditions include: you must
// preserve this copyright notice, and you cannot mention the copyright
// holders in advertising related to the Software without their permission.
// The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
// notice is a summary of the XORP LICENSE file; the license in that file is
// legally binding.
// $XORP: xorp/libxorp/ref_ptr.hh,v 1.10 2003/08/28 16:11:05 pavlin Exp $
#ifndef __LIBXORP_REF_PTR_HH__
#define __LIBXORP_REF_PTR_HH__
#include "config.h"
#include "xorp.h"
#include <vector>
/**
* @short class for maintaining the storage of counters used by ref_ptr.
*
* The ref_counter_pool is a singleton class that maintains the counters
* for all ref_ptr objects. The counters are maintained in a vector. This
* class is used by ref_ptr and not intended any other purpose.
*/
class ref_counter_pool
{
private:
vector<int32_t> _counters;
int32_t _free_index;
int32_t _balance;
static const int32_t LAST_FREE = -1;
static ref_counter_pool _the_instance;
/**
* Expand counter storage.
*/
void grow();
public:
/**
* Create a new counter.
* @return index associated with counter.
*/
int32_t new_counter();
/**
* Increment the count associated with counter by 1.
* @param index the counter to increment.
*/
int32_t incr_counter(int32_t index);
/**
* Decrement the count associated with counter by 1.
* @param index the counter to decrement.
*/
int32_t decr_counter(int32_t index);
/**
* Get the count associated with counter.
* @param index of the counter to query.
* @return the counter value.
*/
int32_t count(int32_t index);
/**
* Recycle counter. Places counter on free-list.
* @param index of the counter to recycle.
*/
void recycle(int32_t index);
/**
* Dumps counter info to stdout. Debugging function.
*/
void dump();
/**
* Sanity check internal data structure. Debugging function.
*/
void check();
/**
* Check index is on free list.
*/
bool on_free_list(int32_t index);
/**
* Return number of valid ref pointer entries in pool.
*/
inline int32_t balance() const { return _balance; }
/**
* @return singleton ref_counter_pool.
*/
static ref_counter_pool& instance();
ref_counter_pool();
};
/**
* @short Reference Counted Pointer Class.
*
* The ref_ptr class is a strong reference class. It maintains a count of
* how many references to an object exist and releases the memory associated
* with the object when the reference count reaches zero. The reference
* pointer can be dereferenced like an ordinary pointer to call methods
* on the reference counted object.
*
* At the time of writing the only supported memory management is
* through the new and delete operators. At a future date, this class
* should support the STL allocator classes or an equivalent to
* provide greater flexibility.
*/
template <class _Tp>
class ref_ptr {
public:
typedef ref_ptr<const _Tp> const_ref_ptr;
public:
/**
* Construct a reference pointer for object.
*
* @param p pointer to object to be reference counted. p must be
* allocated using operator new as it will be destructed using delete
* when the reference count reaches zero.
*/
ref_ptr(_Tp* __p = 0)
: _M_ptr(__p), _M_counter(0)
{
if (_M_ptr)
_M_counter = ref_counter_pool::instance().new_counter();
}
/**
* Copy Constructor
*
* Constructs a reference pointer for object. Raises reference count
* associated with object by 1.
*/
ref_ptr(const ref_ptr& __r)
: _M_ptr(0), _M_counter(-1) {
ref(&__r);
}
/**
* Assignment Operator
*
* Assigns reference pointer to new object.
*/
ref_ptr& operator=(const ref_ptr& __r) {
if (&__r != this) {
unref();
ref(&__r);
}
return *this;
}
/**
* Destruct reference pointer instance and lower reference count on
* object being tracked. The object being tracked will be deleted if
* the reference count falls to zero because of the destruction of the
* reference pointer.
*/
~ref_ptr() {
unref();
}
/**
* Dereference reference counted object.
* @return reference to object.
*/
inline _Tp& operator*() const {
return *_M_ptr;
}
/**
* Dereference pointer to refence counted object.
* @return pointer to object.
*/
inline _Tp* operator->() const {
return _M_ptr;
}
/**
* Dereference pointer to refence counted object.
* @return pointer to object.
*/
inline _Tp* get() const {
return _M_ptr;
}
/**
* Equality Operator
* @return true if reference pointers refer to same object.
*/
inline bool operator==(const ref_ptr& rp) const {
return _M_ptr == rp._M_ptr;
}
/**
* Check if reference pointer refers to an object or whether it has
* been assigned a null object.
* @return true if reference pointer refers to a null object.
*/
inline bool is_empty() const {
return _M_ptr == 0;
}
/**
* @return true if reference pointer represents only reference to object.
*/
inline bool is_only() const {
return ref_counter_pool::instance().count(_M_counter) == 1;
}
/**
* @param n minimum count.
* @return true if there are at least n references to object.
*/
bool at_least(int32_t n) const {
return ref_counter_pool::instance().count(_M_counter) >= n;
}
/**
* Release reference on object. The reference pointers underlying
* object is set to null, and the former object is destructed if
* necessary.
*/
inline void release() const {
unref();
}
inline operator const_ref_ptr()
{
const_ref_ptr crp(get(), /*_M_counter*/ counter());
return crp;
}
ref_ptr(_Tp* data, int32_t counter) : _M_ptr(data), _M_counter(counter)
{
ref_counter_pool::instance().incr_counter(_M_counter);
}
protected:
inline int32_t counter() const {
return _M_counter;
}
/**
* Add reference.
*/
void ref(const ref_ptr* __r) const {
_M_ptr = __r->_M_ptr;
_M_counter = __r->_M_counter;
if (_M_ptr) {
ref_counter_pool::instance().incr_counter(_M_counter);
}
}
/**
* Remove reference.
*/
void unref() const {
if (_M_ptr &&
ref_counter_pool::instance().decr_counter(_M_counter) == 0) {
delete _M_ptr;
}
_M_ptr = 0;
}
mutable _Tp* _M_ptr;
mutable int32_t _M_counter; // index in ref_counter_pool
};
#if 0
template <typename _Tp>
ref_ptr<const _Tp>::ref_ptr(const ref_ptr<_Tp>& __r)
: _M_ptr(0), _M_counter(_r->_M_counter)
{
ref_counter_pool::instance().incr_counter(_M_counter);
}
#endif
/**
* @short class for maintaining the storage of counters used by cref_ptr.
*
* The cref_counter_pool is a singleton class that maintains the counters
* for all cref_ptr objects. The counters are maintained in a vector. This
* class is used by cref_ptr and not intended any other purpose.
*/
class cref_counter_pool
{
private:
struct pool_item {
int32_t count;
void* data;
};
vector<pool_item> _counters;
int32_t _free_index;
static const int32_t LAST_FREE = -1;
static cref_counter_pool _the_instance;
/**
* Expand counter storage.
*/
void grow();
public:
/**
* Create a new counter.
* @return index associated with counter.
*/
int32_t new_counter(void *data);
/**
* Increment the count associated with counter by 1.
* @param index the counter to increment.
*/
int32_t incr_counter(int32_t index);
/**
* Decrement the count associated with counter by 1.
* @param index the counter to decrement.
*/
int32_t decr_counter(int32_t index);
/**
* Get the count associated with counter.
* @param index of the counter to query.
* @return the counter value.
*/
int32_t count(int32_t index);
void* data(int32_t index);
/**
* Recycle counter. Places counter on free-list.
* @param index of the counter to recycle.
*/
void recycle(int32_t index);
/**
* Dumps counter info to stdout. Debugging function.
*/
void dump();
/**
* Sanity check internal data structure. Debugging function.
*/
void check();
/**
* @return singleton cref_counter_pool.
*/
static cref_counter_pool& instance();
cref_counter_pool();
};
/**
* @short Compact Reference Counted Pointer Class.
*
* The cref_ptr class is a strong reference class. It maintains a count of
* how many references to an object exist and releases the memory associated
* with the object when the reference count reaches zero. The reference
* pointer can be dereferenced like an ordinary pointer to call methods
* on the reference counted object.
*
* In contrast to the ref_ptr class, accessing the pointer requires
* two levels of indirection as the pointer is stored in the same
* table as the counter. This is a performance hit, but means each
* cref_ptr only consumes 4-bytes.
*
* At the time of writing the only supported memory management is
* through the new and delete operators. At a future date, this class
* should support the STL allocator classes or an equivalent to
* provide greater flexibility.
*/
template <class _Tp>
class cref_ptr {
public:
/**
* Construct a compact reference pointer for object.
*
* @param p pointer to object to be reference counted. p must be
* allocated using operator new as it will be destructed using delete
* when the reference count reaches zero.
*/
cref_ptr(_Tp* __p = 0)
: _M_counter(cref_counter_pool::instance().new_counter(__p))
{}
/**
* Copy Constructor
*
* Constructs a reference pointer for object. Raises reference count
* associated with object by 1.
*/
cref_ptr(const cref_ptr& __r)
: _M_counter(-1) {
ref(&__r);
}
/**
* Assignment Operator
*
* Assigns reference pointer to new object.
*/
cref_ptr& operator=(const cref_ptr& __r) {
if (&__r != this) {
unref();
ref(&__r);
}
return *this;
}
/**
* Destruct reference pointer instance and lower reference count on
* object being tracked. The object being tracked will be deleted if
* the reference count falls to zero because of the destruction of the
* reference pointer.
*/
~cref_ptr() {
unref();
}
/**
* Dereference pointer to refence counted object.
* @return pointer to object.
*/
inline _Tp* get() const {
return reinterpret_cast<_Tp*>
(cref_counter_pool::instance().data(_M_counter));
}
/**
* Dereference reference counted object.
* @return reference to object.
*/
inline _Tp& operator*() const { return *(get()); }
/**
* Dereference pointer to refence counted object.
* @return pointer to object.
*/
inline _Tp* operator->() const { return get(); }
/**
* Equality Operator
* @return true if reference pointers refer to same object.
*/
inline bool operator==(const cref_ptr& rp) const {
return get() == rp.get();
}
/**
* Check if reference pointer refers to an object or whether it has
* been assigned a null object.
* @return true if reference pointer refers to a null object.
*/
inline bool is_empty() const {
return _M_counter < 0;
}
/**
* @return true if reference pointer represents only reference to object.
*/
inline bool is_only() const {
return cref_counter_pool::instance().count(_M_counter) == 1;
}
/**
* @param n minimum count.
* @return true if there are at least n references to object.
*/
bool at_least(int32_t n) const {
return cref_counter_pool::instance().count(_M_counter) >= n;
}
/**
* Release reference on object. The reference pointers underlying
* object is set to null, and the former object is destructed if
* necessary.
*/
inline void release() const {
unref();
}
private:
/**
* Add reference.
*/
void ref(const cref_ptr* __r) const {
_M_counter = __r->_M_counter;
cref_counter_pool::instance().incr_counter(_M_counter);
}
/**
* Remove reference.
*/
void unref() const {
if (_M_counter >= 0 &&
cref_counter_pool::instance().decr_counter(_M_counter) == 0) {
delete get();
_M_counter = -1;
}
}
mutable int32_t _M_counter; // index in cref_counter_pool
};
#endif // __LIBXORP_REF_PTR_HH__
Generated by: pavlin on possum.icir.org on Thu Nov 6 23:46:46 2003, using kdoc 2.0a54+XORP. |