# HG changeset patch # User alpar # Date 1140525420 0 # Node ID 8ef02f0c42454ec2a115b1d22252a27b2ca0050e # Parent a71f388045f9a67c0bfd08e5b4dbee07b0f9da3a RefPtr: a reference counted pointer class diff -r a71f388045f9 -r 8ef02f0c4245 lemon/Makefile.am --- a/lemon/Makefile.am Tue Feb 21 08:48:11 2006 +0000 +++ b/lemon/Makefile.am Tue Feb 21 12:37:00 2006 +0000 @@ -68,6 +68,7 @@ prim.h \ radix_heap.h \ radix_sort.h \ + refptr.h \ simann.h \ smart_graph.h \ sub_graph.h \ diff -r a71f388045f9 -r 8ef02f0c4245 lemon/refptr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/refptr.h Tue Feb 21 12:37:00 2006 +0000 @@ -0,0 +1,146 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2006 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_REFPTR_H +#define LEMON_REFPTR_H + +///\ingroup misc +///\file +///\brief A reference counted pointer implementation. +/// +///\todo Undocumented + + +namespace lemon { + + + ///Reference counted pointer + + ///This is a simple implementation of a reference counted pointer. + /// + ///\warning Current implementation is far from being thread-safe. + template + class RefPtr + { + mutable RefPtr *prev, *next; + T *ref; + + void lock() {} + void unlock() {} + + void attach(RefPtr &r) + { + prev=&r; next=r.next; ref=r.ref; + r.next=this; + } + void attach(const T *p) + { + prev=0; next=0; ref=p; + } + void release() + { + if(ref) { + bool fr=true; + if(prev) { fr=false; prev->next=next; } + if(next) { fr=false; next->prev=prev; } + if(fr) delete ref; + ref=0; + } + } + + public: + ///\e + RefPtr() : ref(0) {} + + ///\e + RefPtr(const RefPtr &r) { + lock(); + attach(const_cast(r)); + unlock(); + } + + ///\e + RefPtr(T *p) : prev(0), next(0), ref(p) {} + + ///\e + ~RefPtr() { + lock(); + release(); + unlock(); + } + + ///\e + const RefPtr &operator=(const RefPtr &r) { + if(ref!=r.ref) { + lock(); + release(); attach(const_cast(r)); + unlock(); + } + return *this; + } + + ///\e + const RefPtr &operator=(const T* &p) { + if(ref!=p) { lock(); release(); attach(p); unlock(); } + return *this; + } + + ///\e + void swap(RefPtr &r) { + RefPtr *p; + T *tp; + lock(); + p=prev; prev=r.prev; r.prev=p; + p=next; next=r.next; r.next=p; + tp=ref; ref=r.ref; r.ref=tp; + unlock(); + } + + ///\e + void clear() { lock(); release(); unlock(); } + + ///\e + T * operator->() { return ref; } + ///\e + const T * operator->() const { return ref; } + ///\e + operator T *() { return ref; } + ///\e + operator const T *() const { return ref; } + + ///\e + bool operator<(const RefPtr &r) const { return this->ref < r.ref; } + ///\e + bool operator<=(const RefPtr &r) const { return this->ref <= r.ref; } + ///\e + bool operator==(const RefPtr &r) const { return this->ref == r.ref; } + ///\e + bool operator>=(const RefPtr &r) const { return this->ref >= r.ref; } + ///\e + bool operator>(const RefPtr &r) const { return this->ref > r.ref; } + ///\e + bool operator!=(const RefPtr &r) const { return this->ref != r.ref; } + + ///\e + operator bool() const { return ref; } + + }; //END OF CLASS REFPTR + +} //END OF NAMESPACE LEMON + +#endif diff -r a71f388045f9 -r 8ef02f0c4245 test/Makefile.am --- a/test/Makefile.am Tue Feb 21 08:48:11 2006 +0000 +++ b/test/Makefile.am Tue Feb 21 12:37:00 2006 +0000 @@ -30,6 +30,7 @@ path_test \ preflow_test \ radix_sort_test \ + refptr_test \ test_tools_fail \ test_tools_pass \ time_measure_test \ @@ -67,6 +68,7 @@ suurballe_test_SOURCES = suurballe_test.cc path_test_SOURCES = path_test.cc radix_sort_test_SOURCES = radix_sort_test.cc +refptr_test_SOURCES = refptr_test.cc preflow_test_SOURCES = preflow_test.cc time_measure_test_SOURCES = time_measure_test.cc test_tools_fail_SOURCES = test_tools_fail.cc diff -r a71f388045f9 -r 8ef02f0c4245 test/refptr_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/refptr_test.cc Tue Feb 21 12:37:00 2006 +0000 @@ -0,0 +1,61 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2006 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include +#include "test_tools.h" +#include + +class Test +{ + int &_counter; +public: + Test(int &co) : _counter(co) + { + std::cerr << "Init\n"; + _counter++; + } + ~Test() + { + std::cerr << "Destroy\n"; + _counter--; + } + int &counter() { return _counter; } + +}; + +int main() +{ + int c=0; + + { + RefPtr a = new Test(c); + check(a->counter() == 1, "Wrong number of initialization"); + { + RefPtr b = a; + check((*b).counter() == 1, "Wrong number of initialization"); + b=a; + a=b; + check((*a).counter() == 1, "Wrong number of initialization"); + } + check(a->counter() == 1, "Wrong number of initialization"); + } + check(c == 0, "Wrong number of initialization"); + + return 0; +} +