Fawkes API Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * refcount.cpp - reference counting base class 00004 * 00005 * Created: Fri Oct 27 13:52:08 2006 00006 * Copyright 2006 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <core/utils/refcount.h> 00025 #include <core/threading/mutex.h> 00026 #include <core/exceptions/software.h> 00027 00028 #include <unistd.h> 00029 00030 namespace fawkes { 00031 00032 /** @class RefCount core/utils/refcount.h 00033 * Reference counting base class. 00034 * Derive this class with your object if you need reference counting for the object 00035 * thus that it is not deleted while some code is still using an class instance. 00036 * 00037 * The RefCount class is NOT meant for direct usage. In most cases if you are aware 00038 * of the need of reference couting during the design of the software derive this 00039 * class. This is the recommended way. If you want to use reference counting with 00040 * a class that you cannot or do not want to modify you can use the RefCounter 00041 * template class to accomplish the desired task. 00042 * @see RefCounter 00043 * 00044 * @ingroup FCL 00045 * @author Tim Niemueller 00046 */ 00047 00048 00049 /** Constructor. */ 00050 RefCount::RefCount() 00051 { 00052 ref_mutex = new Mutex(); 00053 refc = 1; 00054 } 00055 00056 00057 /** Destructor. */ 00058 RefCount::~RefCount() 00059 { 00060 delete ref_mutex; 00061 } 00062 00063 00064 /** Increment reference count. 00065 * @exception DestructionInProgressException Thrown if the only other reference holder 00066 * for this instance was just deleting the instance when you tried to reference it. 00067 * @see recount(); 00068 */ 00069 void 00070 RefCount::ref() 00071 { 00072 ref_mutex->lock(); 00073 if ( refc == 0 ) { 00074 throw DestructionInProgressException("Tried to reference that is currently being deleted"); 00075 } 00076 ++refc; 00077 ref_mutex->unlock(); 00078 } 00079 00080 00081 /** Decrement reference count and conditionally delete this instance. 00082 * This method will decrement the reference count of this message. If the reference count 00083 * reaches zero the message will be deleted automatically. So it is not safe to use this 00084 * instance after is has been unref()'ed. 00085 * For the code calling 00086 * @code 00087 * obj->unref(); 00088 * @endcode 00089 * should be considered equivalent to 00090 * @code 00091 * delete obj; 00092 * @endcode. 00093 * There is no guarantee whatsover that the object can still be used afterwards. 00094 * It is however guaranteed, that the instance is not deleted/free from memory if 00095 * there are still other applications using this instance that properly ref()'ed 00096 * this instance before conditional delete was called. 00097 */ 00098 void 00099 RefCount::unref() 00100 { 00101 00102 ref_mutex->lock(); 00103 if ( refc == 0 ) { 00104 throw DestructionInProgressException("Tried to reference that is currently being deleted"); 00105 } 00106 if ( refc > 0 ) --refc; 00107 if ( refc == 0 ) { 00108 // commit suicide 00109 delete this; 00110 return; 00111 } 00112 ref_mutex->unlock(); 00113 } 00114 00115 00116 /** Get reference count for this instance. 00117 * The reference count is used to determine if a message should really be destructed 00118 * or not. 00119 * Do not rely on this value, as race-conditions may ruin your code! Do only use the 00120 * atomic ref() and unref() operations. This function is only provided to output 00121 * informational debugging output! 00122 * @return reference count 00123 */ 00124 unsigned int 00125 RefCount::refcount() 00126 { 00127 return refc; 00128 } 00129 00130 00131 } // end namespace fawkes