/* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #include "VariablesViewStateHistory.h" #include #include "FunctionID.h" #include "VariablesViewState.h" // #pragma mark - Key struct VariablesViewStateHistory::Key { thread_id threadID; FunctionID* functionID; Key(thread_id threadID, FunctionID* functionID) : threadID(threadID), functionID(functionID) { } uint32 HashValue() const { return functionID->HashValue() ^ threadID; } bool operator==(const Key& other) const { return threadID == other.threadID && *functionID == *other.functionID; } }; // #pragma mark - StateEntry struct VariablesViewStateHistory::StateEntry : Key, VariablesViewNodeInfo { StateEntry* next; VariablesViewState* state; StateEntry(thread_id threadID, FunctionID* functionID) : Key(threadID, functionID), state(NULL) { functionID->AcquireReference(); } ~StateEntry() { functionID->ReleaseReference(); if (state != NULL) state->ReleaseReference(); } void SetState(VariablesViewState* state) { if (state == this->state) return; if (state != NULL) state->AcquireReference(); if (this->state != NULL) this->state->ReleaseReference(); this->state = state; } }; struct VariablesViewStateHistory::StateEntryHashDefinition { typedef Key KeyType; typedef StateEntry ValueType; size_t HashKey(const Key& key) const { return key.HashValue(); } size_t Hash(const StateEntry* value) const { return HashKey(*value); } bool Compare(const Key& key, const StateEntry* value) const { return key == *value; } StateEntry*& GetLink(StateEntry* value) const { return value->next; } }; VariablesViewStateHistory::VariablesViewStateHistory() : fStates(NULL) { } VariablesViewStateHistory::~VariablesViewStateHistory() { if (fStates != NULL) { StateEntry* entry = fStates->Clear(true); while (entry != NULL) { StateEntry* next = entry->next; delete entry; entry = next; } delete fStates; } } status_t VariablesViewStateHistory::Init() { fStates = new(std::nothrow) StateTable; if (fStates == NULL) return B_NO_MEMORY; return fStates->Init(); } VariablesViewState* VariablesViewStateHistory::GetState(thread_id threadID, FunctionID* functionID) const { // first try an exact match with the thread ID if (threadID >= 0) { StateEntry* stateEntry = fStates->Lookup(Key(threadID, functionID)); if (stateEntry != NULL) return stateEntry->state; } // just match the function ID StateEntry* stateEntry = fStates->Lookup(Key(-1, functionID)); return stateEntry != NULL ? stateEntry->state : NULL; } VariablesViewState* VariablesViewStateHistory::GetState(FunctionID* functionID) const { StateEntry* stateEntry = fStates->Lookup(Key(-1, functionID)); return stateEntry != NULL ? stateEntry->state : NULL; } status_t VariablesViewStateHistory::SetState(thread_id threadID, FunctionID* functionID, VariablesViewState* state) { // Make sure the default entry for the function exists. StateEntry* defaultEntry = fStates->Lookup(Key(-1, functionID)); bool newDefaultEntry = false; if (defaultEntry == NULL) { defaultEntry = new(std::nothrow) StateEntry(-1, functionID); if (defaultEntry == NULL) return B_NO_MEMORY; fStates->Insert(defaultEntry); newDefaultEntry = true; } // If we have a valid thread ID, make sure the respective entry for the // function exists. StateEntry* threadEntry = NULL; if (threadID >= 0) { threadEntry = fStates->Lookup(Key(threadID, functionID)); if (threadEntry == NULL) { threadEntry = new(std::nothrow) StateEntry(threadID, functionID); if (threadEntry == NULL) { if (newDefaultEntry) { fStates->Remove(defaultEntry); delete defaultEntry; } return B_NO_MEMORY; } fStates->Insert(threadEntry); } } defaultEntry->SetState(state); if (threadEntry != NULL) threadEntry->SetState(state); return B_OK; }