alpar@1977: /* -*- C++ -*- alpar@1977: * alpar@1977: * This file is a part of LEMON, a generic C++ optimization library alpar@1977: * alpar@2553: * Copyright (C) 2003-2008 alpar@1977: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@1977: * (Egervary Research Group on Combinatorial Optimization, EGRES). alpar@1977: * alpar@1977: * Permission to use, modify and distribute this software is granted alpar@1977: * provided that this copyright notice appears in all copies. For alpar@1977: * precise terms see the accompanying LICENSE file. alpar@1977: * alpar@1977: * This software is provided "AS IS" with no warranty of any kind, alpar@1977: * express or implied, and with no claim as to its suitability for any alpar@1977: * purpose. alpar@1977: * alpar@1977: */ alpar@1977: alpar@1977: #ifndef LEMON_REFPTR_H alpar@1977: #define LEMON_REFPTR_H alpar@1977: alpar@1977: ///\ingroup misc alpar@1977: ///\file alpar@1977: ///\brief A reference counted pointer implementation. alpar@1977: /// alpar@1977: ///\todo Undocumented alpar@1977: alpar@1977: alpar@1977: namespace lemon { alpar@1977: alpar@1977: alpar@1977: ///Reference counted pointer alpar@1977: alpar@1977: ///This is a simple implementation of a reference counted pointer. alpar@1977: /// alpar@1977: ///\warning Current implementation is far from being thread-safe. alpar@1977: template alpar@1977: class RefPtr alpar@1977: { alpar@1977: mutable RefPtr *prev, *next; alpar@1977: T *ref; alpar@1977: alpar@1977: void lock() {} alpar@1977: void unlock() {} alpar@1977: alpar@1977: void attach(RefPtr &r) alpar@1977: { alpar@2151: if(r.ref) { alpar@2151: prev=&r; next=r.next; ref=r.ref; alpar@2151: r.next=this; alpar@2151: } alpar@1977: } alpar@1977: void attach(const T *p) alpar@1977: { alpar@1977: prev=0; next=0; ref=p; alpar@1977: } alpar@1977: void release() alpar@1977: { alpar@1977: if(ref) { alpar@1977: bool fr=true; alpar@1977: if(prev) { fr=false; prev->next=next; } alpar@1977: if(next) { fr=false; next->prev=prev; } alpar@1977: if(fr) delete ref; alpar@1977: ref=0; alpar@1977: } alpar@1977: } alpar@1977: alpar@1977: public: alpar@1977: ///\e alpar@1977: RefPtr() : ref(0) {} alpar@1977: alpar@1977: ///\e alpar@1977: RefPtr(const RefPtr &r) { alpar@1977: lock(); alpar@1977: attach(const_cast(r)); alpar@1977: unlock(); alpar@1977: } alpar@1977: alpar@1977: ///\e alpar@1977: RefPtr(T *p) : prev(0), next(0), ref(p) {} alpar@1977: alpar@1977: ///\e alpar@1977: ~RefPtr() { alpar@1977: lock(); alpar@1977: release(); alpar@1977: unlock(); alpar@1977: } alpar@1977: alpar@1977: ///\e alpar@1977: const RefPtr &operator=(const RefPtr &r) { alpar@1977: if(ref!=r.ref) { alpar@1977: lock(); alpar@1977: release(); attach(const_cast(r)); alpar@1977: unlock(); alpar@1977: } alpar@1977: return *this; alpar@1977: } alpar@1977: alpar@1977: ///\e alpar@1977: const RefPtr &operator=(const T* &p) { alpar@1977: if(ref!=p) { lock(); release(); attach(p); unlock(); } alpar@1977: return *this; alpar@1977: } alpar@1977: alpar@1977: ///\e alpar@1977: void swap(RefPtr &r) { alpar@1977: RefPtr *p; alpar@1977: T *tp; alpar@1977: lock(); alpar@1977: p=prev; prev=r.prev; r.prev=p; alpar@1977: p=next; next=r.next; r.next=p; alpar@1977: tp=ref; ref=r.ref; r.ref=tp; alpar@1977: unlock(); alpar@1977: } alpar@1977: alpar@1977: ///\e alpar@1977: void clear() { lock(); release(); unlock(); } alpar@1977: alpar@1977: ///\e alpar@1977: T * operator->() { return ref; } alpar@1977: ///\e alpar@1977: const T * operator->() const { return ref; } alpar@1977: ///\e alpar@1977: operator T *() { return ref; } alpar@1977: ///\e alpar@1977: operator const T *() const { return ref; } alpar@1977: alpar@1977: ///\e alpar@1977: bool operator<(const RefPtr &r) const { return this->ref < r.ref; } alpar@1977: ///\e alpar@1977: bool operator<=(const RefPtr &r) const { return this->ref <= r.ref; } alpar@1977: ///\e alpar@1977: bool operator==(const RefPtr &r) const { return this->ref == r.ref; } alpar@1977: ///\e alpar@1977: bool operator>=(const RefPtr &r) const { return this->ref >= r.ref; } alpar@1977: ///\e alpar@1977: bool operator>(const RefPtr &r) const { return this->ref > r.ref; } alpar@1977: ///\e alpar@1977: bool operator!=(const RefPtr &r) const { return this->ref != r.ref; } alpar@1977: alpar@1977: ///\e alpar@1977: operator bool() const { return ref; } alpar@1977: alpar@2151: ///\e alpar@2151: const RefPtr &borrow(const T* &p) { alpar@2151: lock(); alpar@2151: if(ref==p) { alpar@2151: if(prev) prev->next=next; alpar@2151: if(next) next->prev=prev; alpar@2151: } alpar@2151: else release(); alpar@2151: ref=p; alpar@2151: next=prev=this; alpar@2151: unlock(); alpar@2151: return *this; alpar@2151: } alpar@2151: alpar@2151: ///\e alpar@2151: const RefPtr &borrow() { alpar@2151: lock(); alpar@2151: if(prev) prev->next=next; alpar@2151: if(next) next->prev=prev; alpar@2151: next=prev=this; alpar@2151: unlock(); alpar@2151: return *this; alpar@2151: } alpar@2151: alpar@1977: }; //END OF CLASS REFPTR alpar@1977: alpar@1977: } //END OF NAMESPACE LEMON alpar@1977: alpar@1977: #endif