00001 /*========================================================================== 00002 * Copyright (c) 2004 University of Massachusetts. All Rights Reserved. 00003 * 00004 * Use of the Lemur Toolkit for Language Modeling and Information Retrieval 00005 * is subject to the terms of the software license set forth in the LICENSE 00006 * file included with this software, and also available at 00007 * http://www.lemurproject.org/license.html 00008 * 00009 *========================================================================== 00010 */ 00011 00012 // 00013 // ref_ptr 00014 // 00015 // 15 December 2004 -- tds 00016 // 00017 00018 #ifndef INDRI_REFPTR_HPP 00019 #define INDRI_REFPTR_HPP 00020 00021 #include "indri/atomic.hpp" 00022 00023 namespace indri { 00024 namespace atomic 00025 { 00026 00027 template<class T> 00028 class ref_ptr { 00029 private: 00030 template<class TT> 00031 struct object_ref { 00032 TT* object; 00033 value_type counter; 00034 }; 00035 00036 typedef ref_ptr<T> my_type; 00037 mutable object_ref<T>* _ref; 00038 00039 void _removeRef() { 00040 if( _ref ) { 00041 decrement( _ref->counter ); 00042 if( _ref->counter == 0 ) { 00043 delete _ref->object; 00044 delete _ref; 00045 } 00046 } 00047 } 00048 00049 void _addRef() { 00050 if( _ref ) 00051 increment( _ref->counter ); 00052 } 00053 00054 my_type& _refAssign( const my_type& other ) { 00055 _removeRef(); 00056 _ref = other._ref; 00057 _addRef(); 00058 return *this; 00059 } 00060 00061 public: 00062 ref_ptr() : 00063 _ref(0) 00064 { 00065 } 00066 00067 ~ref_ptr() { 00068 _removeRef(); 00069 } 00070 00071 ref_ptr( const my_type& other ) : 00072 _ref(0) 00073 { 00074 _refAssign( other ); 00075 } 00076 00077 ref_ptr( T* object ) { 00078 _ref = new object_ref<T>; 00079 _ref->object = object; 00080 _ref->counter = 1; 00081 } 00082 00083 my_type& operator= ( T* object ) { 00084 _removeRef(); 00085 00086 if( object != 0 ) { 00087 _ref = new object_ref<T>; 00088 _ref->object = object; 00089 _ref->counter = 1; 00090 } else { 00091 _ref = 0; 00092 } 00093 00094 return *this; 00095 } 00096 00097 my_type& operator= ( const ref_ptr& other ) { 00098 _refAssign( other ); 00099 return *this; 00100 } 00101 00102 bool operator== ( T* other ) { 00103 if( _ref == 0 ) 00104 return other == 0; 00105 00106 return _ref->object == other; 00107 } 00108 00109 bool operator== ( ref_ptr& other ) { 00110 return _ref == other._ref; 00111 } 00112 00113 atomic::value_type references() { 00114 if( _ref ) 00115 return _ref->counter; 00116 return 0; 00117 } 00118 00119 T& operator* () { 00120 return *_ref->object; 00121 } 00122 00123 T* operator-> () { 00124 return _ref->object; 00125 } 00126 00127 T* get() { 00128 if( _ref ) 00129 return _ref->object; 00130 return 0; 00131 } 00132 }; 00133 } 00134 } 00135 00136 #endif // INDRI_REFPTR_HPP