1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "VariablesViewStateHistory.h" 8 9 #include <new> 10 11 #include "FunctionID.h" 12 #include "VariablesViewState.h" 13 14 15 // #pragma mark - Key 16 17 18 struct VariablesViewStateHistory::Key { 19 thread_id threadID; 20 FunctionID* functionID; 21 22 Key(thread_id threadID, FunctionID* functionID) 23 : 24 threadID(threadID), 25 functionID(functionID) 26 { 27 } 28 29 uint32 HashValue() const 30 { 31 return functionID->HashValue() ^ threadID; 32 } 33 34 bool operator==(const Key& other) const 35 { 36 return threadID == other.threadID && *functionID == *other.functionID; 37 } 38 }; 39 40 41 // #pragma mark - StateEntry 42 43 44 struct VariablesViewStateHistory::StateEntry : Key, VariablesViewNodeInfo { 45 StateEntry* next; 46 VariablesViewState* state; 47 48 StateEntry(thread_id threadID, FunctionID* functionID) 49 : 50 Key(threadID, functionID), 51 state(NULL) 52 { 53 functionID->AcquireReference(); 54 } 55 56 ~StateEntry() 57 { 58 functionID->ReleaseReference(); 59 if (state != NULL) 60 state->ReleaseReference(); 61 } 62 63 void SetState(VariablesViewState* state) 64 { 65 if (state == this->state) 66 return; 67 68 if (state != NULL) 69 state->AcquireReference(); 70 71 if (this->state != NULL) 72 this->state->ReleaseReference(); 73 74 this->state = state; 75 } 76 }; 77 78 79 struct VariablesViewStateHistory::StateEntryHashDefinition { 80 typedef Key KeyType; 81 typedef StateEntry ValueType; 82 83 size_t HashKey(const Key& key) const 84 { 85 return key.HashValue(); 86 } 87 88 size_t Hash(const StateEntry* value) const 89 { 90 return HashKey(*value); 91 } 92 93 bool Compare(const Key& key, const StateEntry* value) const 94 { 95 return key == *value; 96 } 97 98 StateEntry*& GetLink(StateEntry* value) const 99 { 100 return value->next; 101 } 102 }; 103 104 105 VariablesViewStateHistory::VariablesViewStateHistory() 106 : 107 fStates(NULL) 108 { 109 } 110 111 112 VariablesViewStateHistory::~VariablesViewStateHistory() 113 { 114 if (fStates != NULL) { 115 StateEntry* entry = fStates->Clear(true); 116 117 while (entry != NULL) { 118 StateEntry* next = entry->next; 119 delete entry; 120 entry = next; 121 } 122 123 delete fStates; 124 } 125 } 126 127 128 status_t 129 VariablesViewStateHistory::Init() 130 { 131 fStates = new(std::nothrow) StateTable; 132 if (fStates == NULL) 133 return B_NO_MEMORY; 134 135 return fStates->Init(); 136 } 137 138 139 VariablesViewState* 140 VariablesViewStateHistory::GetState(thread_id threadID, FunctionID* functionID) 141 const 142 { 143 // first try an exact match with the thread ID 144 if (threadID >= 0) { 145 StateEntry* stateEntry = fStates->Lookup(Key(threadID, functionID)); 146 if (stateEntry != NULL) 147 return stateEntry->state; 148 } 149 150 // just match the function ID 151 StateEntry* stateEntry = fStates->Lookup(Key(-1, functionID)); 152 return stateEntry != NULL ? stateEntry->state : NULL; 153 } 154 155 156 VariablesViewState* 157 VariablesViewStateHistory::GetState(FunctionID* functionID) const 158 { 159 StateEntry* stateEntry = fStates->Lookup(Key(-1, functionID)); 160 return stateEntry != NULL ? stateEntry->state : NULL; 161 } 162 163 164 status_t 165 VariablesViewStateHistory::SetState(thread_id threadID, FunctionID* functionID, 166 VariablesViewState* state) 167 { 168 // Make sure the default entry for the function exists. 169 StateEntry* defaultEntry = fStates->Lookup(Key(-1, functionID)); 170 bool newDefaultEntry = false; 171 172 if (defaultEntry == NULL) { 173 defaultEntry = new(std::nothrow) StateEntry(-1, functionID); 174 if (defaultEntry == NULL) 175 return B_NO_MEMORY; 176 fStates->Insert(defaultEntry); 177 newDefaultEntry = true; 178 } 179 180 // If we have a valid thread ID, make sure the respective entry for the 181 // function exists. 182 StateEntry* threadEntry = NULL; 183 if (threadID >= 0) { 184 threadEntry = fStates->Lookup(Key(threadID, functionID)); 185 186 if (threadEntry == NULL) { 187 threadEntry = new(std::nothrow) StateEntry(threadID, functionID); 188 if (threadEntry == NULL) { 189 if (newDefaultEntry) { 190 fStates->Remove(defaultEntry); 191 delete defaultEntry; 192 } 193 return B_NO_MEMORY; 194 } 195 fStates->Insert(threadEntry); 196 } 197 } 198 199 defaultEntry->SetState(state); 200 if (threadEntry != NULL) 201 threadEntry->SetState(state); 202 203 return B_OK; 204 } 205