Inferno
0.2
|
00001 #ifndef RCHOLD_HPP 00002 #define RCHOLD_HPP 00003 00004 #include "common/common.hpp" 00005 #include "node/node.hpp" 00006 #include <inttypes.h> 00007 00008 template<typename NODE, typename RAW> 00009 class RCHold 00010 { 00011 // 00012 // This class converts between TreePtr and void * pointers and ensures that target 00013 // objects whoose TreePtr has been converted to void * remain in existance even if 00014 // the number of RCPtrs to it falls to zero. 00015 // 00016 // Target objects will be held in existance until the corresponding RCHold object 00017 // is destructed, after which only target objects with TreePtr refs will remain. 00018 // 00019 // For a set of raw pointers, create an RCHold object whose lifetime is a minimal 00020 // superset of the union of the raw pointers' lifetimes. Do all assignment to/from 00021 // those raw pointers using ToRaw() and FromRaw(). Note: always assign the return 00022 // of new/malloc to an TreePtr and then convert to a raw ptr using ToRaw() if required, 00023 // otherwise the required extra ref will not be created. 00024 // 00025 // TODO: (done) 00026 // TODO: Consider supporting the new DeleteX() virtuals in the clang action interface, 00027 // but most likely don't bother since we'll tear down anyway. 00028 00029 public: 00030 RCHold() : 00031 id( ((uintptr_t)this % 255+1) << 24 ) // 8-bit hash of this pointer, never zero, placed in top 8 bits 00032 { 00033 } 00034 00035 00036 RAW ToRaw( TreePtr<NODE> p ) 00037 { 00038 ASSERT( p )( "Cannot convert NULL pointer to raw" ); 00039 uintptr_t i = (unsigned)hold_list.size(); // the index of the next push_back() 00040 ASSERT( (i & 0xFF000000) == 0 )( "gone over maximum number of elements, probably due to infinite loop, if not rejig id" ); 00041 i |= id; // embed an id for the current hold object 00042 //TRACE("ToRaw 0x%08x\n", i ); 00043 void *vp = reinterpret_cast<void *>( i ); 00044 hold_list.push_back( p ); 00045 ASSERT(vp); // cannot return a NULL pointer, since clang inteprets that as an error 00046 return vp; 00047 } 00048 00049 TreePtr<NODE> FromRaw( RAW p ) 00050 { 00051 ASSERT( p != 0 )( "this raw value is uninitialised"); 00052 uintptr_t i = reinterpret_cast<uintptr_t>(p); 00053 //TRACE("FromRaw 0x%08x (id=0x%08x)\n", i, id ); 00054 ASSERT( (i & 0xFF000000) == id )( "this raw value was stored to a different holder or uninitialised"); 00055 i &= 0x00FFFFFF; 00056 return hold_list[i]; 00057 } 00058 00059 private: 00060 // When this object is destructed, all the members of the vector will be 00061 // destructed and targets that then have no refs will be destructed. 00062 const unsigned id; 00063 vector< TreePtr< NODE > > hold_list; // TODO does this need to be a vector? 00064 }; 00065 00066 00067 #endif