|
Boost : |
From: Beman Dawes (beman_at_[hidden])
Date: 2000-01-12 17:07:40
At 11:24 AM 1/12/00 -0800, Greg Colvin wrote:
>From: Beman Dawes <beman_at_[hidden]>
>> In implementing a B-tree Container for boost, I have a smart
pointer
>> need which can't be met by boost::shared_ptr<>; an intrusive
>> reference count is required. (Of the three reasons, the last one
is
>> the killer.)
>>
>> * Since the smart point goes in an iterator, it would be better
to
>> avoid the size and separate allocation penalty of shared_ptr.
>>
>> * Memory allocation should use the container's Allocator.
>>
>> * The smart pointer needs to support construction from a raw
pointer
>> when other smart pointers to the same object are known to exist,
but
>> are not available. This means there needs to be a constructor
which
>> increments the reference count rather than just setting it to 1.
>> (This need derives from a really nice cache design which holds raw
>> pointers rather than smart pointers. If smart pointers where
held,
>> the cached pages would never get released.)
>
>So you are using the raw pointers as weak pointers in this design?
Well, not really, if I understand your definition of weak_ptr. There
is no signal when the object is collected.
Here is much cut down code, called shared_in_ptr for lack of a better
name. Note the smart pointer's second constructor increments the use
count rather than setting it to 1.
Following the shared_in_ptr implementation is a usage example. Hope
this makes it clearer.
--Beman
--- shared_in_ptr header ---
// shared_in_base
// This base class meets the requirements for shared_in_ptr T, and
keeps the count
// private to prevent abuse. Note that shared_in_ptr does not
require inheriting
// from shared_in_base<> as long as shared_in_ptr<> requirements are
met
// (presumably by simply providing a member named btree_in_count).
// Requirements on RefCounter: must meet shared_in_ptr requirements.
For example,
// int or long.
template<typename RefCounter>
class shared_in_base
{
template<typename U> friend class shared_in_ptr;
RefCounter btree_in_count;
};
// shared_in_ptr
// Requirements: For px of type T*, the following are well-formed
and do not
// throw exceptions.
//
// Expression Type Effects
// ========== ======== =======
// px->btree_in_count=1 --- sets px->btree_in_count to
value of 1.
// ++px->btree_in_count --- increments px->btree_in_count
by one.
// --px->btree_in_count integral decrements px->btree_in_count
by one,
// type returns px->btree_in_count.
// px->btree_in_count integral returns px->btree_in_count.
// type
template<typename T> class shared_in_ptr {
public:
typedef T element_type;
explicit shared_in_ptr(T* p =0) : px(p) // usual ctor
{ if (px) px->btree_in_count = 1; }
shared_in_ptr(T* p, bool) : px(p) // special ctor
{ assert(px); ++px->btree_in_count; }
~shared_in_ptr() { dispose(); }
T& operator*() const throw() { return *px; }
T* operator->() const throw() { return px; }
T* get() const throw() { return px; }
private:
T* px; // contained pointer
void dispose()
{ if (px && --px->btree_in_count == 0) { delete px; } }
}; // shared_in_ptr
---- shared_in_ptr usage example -----
// definitions
typedef int id_t;
struct cached_object;
map<id_t, cached_object*> cache;
struct cached_object : shared_in_base<int> {
id_t _id
cached_object( id_t id) : _id(id)
{ cache.insert( make_pair( _id, this ) ); }
~cache_object() { cache.erase( _id ); }
// ... useful members here
};
typedef shared_in_ptr<cached_object> obj_ptr;
// function to get cached_objects given id
obj_ptr get_cached_object( id_t id )
{
cache::iterator itr = cache.find(id),
if ( itr == cache.end() )
// not found
return obj_ptr(new cached_object(id));
else
// found
return obj_ptr( itr.second, true ); // note 2nd arg
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk