00001 //<<<<<< INCLUDES >>>>>> 00002 00003 #include "Iguana/Framework/interface/IgStateKey.h" 00004 #include "classlib/utils/DebugAids.h" 00005 00006 //<<<<<< PRIVATE DEFINES >>>>>> 00007 //<<<<<< PRIVATE CONSTANTS >>>>>> 00008 //<<<<<< PRIVATE TYPES >>>>>> 00009 //<<<<<< PRIVATE VARIABLE DEFINITIONS >>>>>> 00010 //<<<<<< PUBLIC VARIABLE DEFINITIONS >>>>>> 00011 //<<<<<< CLASS STRUCTURE INITIALIZATION >>>>>> 00012 00013 unsigned IgStateKey::s_count = 0; 00014 00015 //<<<<<< PRIVATE FUNCTION DEFINITIONS >>>>>> 00016 //<<<<<< PUBLIC FUNCTION DEFINITIONS >>>>>> 00017 //<<<<<< MEMBER FUNCTION DEFINITIONS >>>>>> 00018 00020 IgStateKeyDef::IgStateKeyDef (const std::string &label) 00021 : IgStateKey (create (label)), 00022 m_label (label) 00023 {} 00024 00026 IgStateKeyDef::~IgStateKeyDef (void) 00027 { remove (m_label); } 00028 00032 00033 IgStateKey::IgStateKey (unsigned value) 00034 : m_value (value) 00035 {} 00036 00038 std::string 00039 IgStateKey::label (void) const 00040 { 00041 Map &keys = keymap (); 00042 for (Map::iterator pos = keys.begin (); pos != keys.end (); ++pos) 00043 if (pos->second == m_value) 00044 return pos->first; 00045 00046 // This can occur for the unknown key (~0U, see #index()) 00047 return "<UNDEFINED>"; 00048 } 00049 00051 00053 IgStateKey::Map & 00054 IgStateKey::keymap (void) 00055 { 00056 static char buf [sizeof (Map)]; 00057 static Map *bufmap = new (buf) Map; 00058 return *bufmap; 00059 } 00060 00062 unsigned 00063 IgStateKey::create (const std::string &label) 00064 { 00065 // FIXME: Thread safety. 00066 00067 // The logic here accommodates for keys that are getting recreated 00068 // due to dynamic loading and unloading of a library. Once a key 00069 // has been created, we always keep it in the same index. If the 00070 // library is unloaded, we keep the key in the dictionary but mark 00071 // it unused by turning on the 32nd (~ top) bit. If the library 00072 // is subsequently re-loaded, we give it the same index back and 00073 // turn the bit off to indicate the index is in use again. 00074 ASSERT (! label.empty ()); 00075 Map &keys = keymap (); 00076 if (! keys.count (label)) 00077 { 00078 // Not seen this one before. Allocate a new index for this. 00079 // Make sure we don't overrun to the area of our mark bits (if 00080 // this triggers, we'll be screwed anyway as we have far too 00081 // many state elements by then in every state). 00082 ASSERT (s_count < 0x8000000); 00083 unsigned value = s_count++; 00084 keys [label] = value; 00085 return value; 00086 } 00087 else 00088 { 00089 // We've seen this before. Make sure the key index is not 00090 // active and then give it back. 00091 ASSERT (keys [label] & 0x8000000); 00092 unsigned &value = keys [label]; 00093 value &= ~0x8000000; 00094 return value; 00095 } 00096 } 00097 00099 void 00100 IgStateKey::remove (const std::string &label) 00101 { 00102 // See comments in #create() for the logic. FIXME: Thread safety. 00103 ASSERT (! label.empty ()); 00104 Map &keys = keymap (); 00105 ASSERT (keys.count (label)); 00106 ASSERT (! (keys [label] & 0x8000000)); 00107 keys [label] |= 0x8000000; 00108 } 00109 00113 IgStateKey 00114 IgStateKey::index (const std::string &label) 00115 { 00116 // FIXME: Thread safety. 00117 ASSERT (! label.empty ()); 00118 Map &keys = keymap (); 00119 Map::iterator pos = keys.find (label); 00120 return pos == keys.end () ? ~0U : pos->second; 00121 }