xorp

ref_ptr.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 // vim:set sts=4 ts=8:
00003 
00004 // Copyright (c) 2001-2011 XORP, Inc and Others
00005 //
00006 // This program is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU Lesser General Public License, Version
00008 // 2.1, June 1999 as published by the Free Software Foundation.
00009 // Redistribution and/or modification of this program under the terms of
00010 // any other version of the GNU Lesser General Public License is not
00011 // permitted.
00012 // 
00013 // This program is distributed in the hope that it will be useful, but
00014 // WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00016 // see the GNU Lesser General Public License, Version 2.1, a copy of
00017 // which can be found in the XORP LICENSE.lgpl file.
00018 // 
00019 // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00020 // http://xorp.net
00021 
00022 // $XORP: xorp/libxorp/ref_ptr.hh,v 1.26 2008/10/02 21:57:32 bms Exp $
00023 
00024 #ifndef __LIBXORP_REF_PTR_HH__
00025 #define __LIBXORP_REF_PTR_HH__
00026 
00027 #include "libxorp/xorp.h"
00028 
00029 
00030 
00031 
00039 class ref_counter_pool
00040 {
00041 private:
00042     vector<int32_t> _counters;
00043     int32_t     _free_index;
00044     int32_t     _balance;
00045 
00046     static const int32_t LAST_FREE = -1;
00047     static ref_counter_pool _the_instance;
00048 
00052     void grow();
00053 
00054 public:
00059     int32_t new_counter();
00060 
00065     int32_t incr_counter(int32_t index);
00066 
00071     int32_t decr_counter(int32_t index);
00072 
00078     int32_t count(int32_t index);
00079 
00084     void recycle(int32_t index);
00085 
00089     void dump();
00090 
00094     void check();
00095 
00099     bool on_free_list(int32_t index);
00100 
00104     int32_t balance() const { return _balance; }
00105 
00109     static ref_counter_pool& instance();
00110 
00111     ref_counter_pool();
00112 };
00113 
00128 template <class _Tp>
00129 class ref_ptr {
00130 public:
00138     ref_ptr(_Tp* __p = 0)
00139         : _M_ptr(__p), _M_index(0)
00140     {
00141     if (_M_ptr)
00142         _M_index = ref_counter_pool::instance().new_counter();
00143     }
00144 
00151     ref_ptr(const ref_ptr& __r)
00152         : _M_ptr(0), _M_index(-1) {
00153         ref(&__r);
00154     }
00155 
00161     ref_ptr& operator=(const ref_ptr& __r) {
00162         if (&__r != this) {
00163             unref();
00164             ref(&__r);
00165         }
00166         return *this;
00167     }
00168 
00175     ~ref_ptr() {
00176         unref();
00177     }
00178 
00183     _Tp& operator*() const { return *_M_ptr; }
00184 
00189     _Tp* operator->() const { return _M_ptr; }
00190 
00195     _Tp* get() const { return _M_ptr; }
00196 
00197 #ifdef XORP_USE_USTL
00198 
00199     // Compare pointed-to items.
00200     bool operator==(const ref_ptr& rp) const {
00201     if (_M_ptr == rp._M_ptr)
00202         return true;
00203     if (_M_ptr && rp._M_ptr)
00204         return (*_M_ptr == *rp._M_ptr);
00205     return false;
00206     }
00207 
00208     // Compare pointed-to items.
00209     bool operator< (const ref_ptr& b) {
00210     if (_M_ptr && b._M_ptr)
00211         return (*_M_ptr < *b._M_ptr);
00212     if (_M_ptr == b._M_ptr)
00213         return false;
00214     if (b._M_ptr)
00215         return true;
00216     }
00217 
00218 #else
00219 
00223     bool operator==(const ref_ptr& rp) const { return _M_ptr == rp._M_ptr; }
00224 #endif
00225 
00231     bool is_empty() const { return _M_ptr == 0; }
00232 
00236     bool is_only() const {
00237     return ref_counter_pool::instance().count(_M_index) == 1;
00238     }
00239 
00244     bool at_least(int32_t n) const {
00245     return ref_counter_pool::instance().count(_M_index) >= n;
00246     }
00247 
00253     void release() const { unref(); }
00254     /* mimic functionality of boost weak_ptr, same as release()
00255      */
00256     void reset() const { unref(); }
00257 
00258     ref_ptr(_Tp* data, int32_t index) : _M_ptr(data), _M_index(index)
00259     {
00260     ref_counter_pool::instance().incr_counter(_M_index);
00261     }
00262 
00263 protected:
00264 
00268     void ref(const ref_ptr* __r) const {
00269     _M_ptr = __r->_M_ptr;
00270     _M_index = __r->_M_index;
00271     if (_M_ptr) {
00272         ref_counter_pool::instance().incr_counter(_M_index);
00273     }
00274     }
00275 
00279     void unref() const {
00280     if (_M_ptr &&
00281         ref_counter_pool::instance().decr_counter(_M_index) == 0) {
00282         delete _M_ptr;
00283     }
00284     _M_ptr = 0;
00285     }
00286 
00287     mutable _Tp*    _M_ptr;
00288     mutable int32_t _M_index;   // index in ref_counter_pool
00289 };
00290 
00291 #if 0
00292 template <typename _Tp>
00293 ref_ptr<const _Tp>::ref_ptr(const ref_ptr<_Tp>& __r)
00294     : _M_ptr(0), _M_index(_r->_M_index)
00295 {
00296     ref_counter_pool::instance().incr_counter(_M_index);
00297 }
00298 #endif
00299 
00307 class cref_counter_pool
00308 {
00309 private:
00310     struct pool_item {
00311     int32_t count;
00312     void*   data;
00313     };
00314     vector<pool_item> _counters;
00315     int32_t       _free_index;
00316 
00317     static const int32_t LAST_FREE = -1;
00318     static cref_counter_pool _the_instance;
00319 
00323     void grow();
00324 
00325 public:
00330     int32_t new_counter(void *data);
00331 
00336     int32_t incr_counter(int32_t index);
00337 
00342     int32_t decr_counter(int32_t index);
00343 
00349     int32_t count(int32_t index);
00350 
00351     void* data(int32_t index);
00352 
00357     void recycle(int32_t index);
00358 
00362     void dump();
00363 
00367     void check();
00368 
00372     static cref_counter_pool& instance();
00373 
00374     cref_counter_pool();
00375 };
00376 
00396 template <class _Tp>
00397 class cref_ptr {
00398 public:
00406     cref_ptr(_Tp* __p = 0)
00407         : _M_index(cref_counter_pool::instance().new_counter(__p))
00408     {}
00409 
00416     cref_ptr(const cref_ptr& __r)
00417         : _M_index(-1) {
00418         ref(&__r);
00419     }
00420 
00426     cref_ptr& operator=(const cref_ptr& __r) {
00427         if (&__r != this) {
00428             unref();
00429             ref(&__r);
00430         }
00431         return *this;
00432     }
00433 
00440     ~cref_ptr() {
00441         unref();
00442     }
00443 
00448     _Tp* get() const {
00449     return reinterpret_cast<_Tp*>
00450         (cref_counter_pool::instance().data(_M_index));
00451     }
00452 
00457     _Tp& operator*() const { return *(get()); }
00458 
00463     _Tp* operator->() const { return get(); }
00464 
00469     bool operator==(const cref_ptr& rp) const { return get() == rp.get(); }
00470 
00476     bool is_empty() const { return _M_index < 0 || 0 == get(); }
00477 
00481     bool is_only() const {
00482     return cref_counter_pool::instance().count(_M_index) == 1;
00483     }
00484 
00489     bool at_least(int32_t n) const {
00490     return cref_counter_pool::instance().count(_M_index) >= n;
00491     }
00492 
00498     void release() const { unref(); }
00499 
00500 private:
00504     void ref(const cref_ptr* __r) const {
00505     _M_index = __r->_M_index;
00506     cref_counter_pool::instance().incr_counter(_M_index);
00507     }
00508 
00512     void unref() const {
00513     if (_M_index >= 0 &&
00514         cref_counter_pool::instance().decr_counter(_M_index) == 0) {
00515         delete get();
00516         _M_index = -1;
00517     }
00518     }
00519 
00520     mutable int32_t _M_index;   // index in cref_counter_pool
00521 };
00522 
00523 #endif // __LIBXORP_REF_PTR_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations