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
KeyVariablesViewStateHistory::Key22 Key(thread_id threadID, FunctionID* functionID)
23 :
24 threadID(threadID),
25 functionID(functionID)
26 {
27 }
28
HashValueVariablesViewStateHistory::Key29 uint32 HashValue() const
30 {
31 return functionID->HashValue() ^ threadID;
32 }
33
operator ==VariablesViewStateHistory::Key34 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
StateEntryVariablesViewStateHistory::StateEntry48 StateEntry(thread_id threadID, FunctionID* functionID)
49 :
50 Key(threadID, functionID),
51 state(NULL)
52 {
53 functionID->AcquireReference();
54 }
55
~StateEntryVariablesViewStateHistory::StateEntry56 ~StateEntry()
57 {
58 functionID->ReleaseReference();
59 if (state != NULL)
60 state->ReleaseReference();
61 }
62
SetStateVariablesViewStateHistory::StateEntry63 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
HashKeyVariablesViewStateHistory::StateEntryHashDefinition83 size_t HashKey(const Key& key) const
84 {
85 return key.HashValue();
86 }
87
HashVariablesViewStateHistory::StateEntryHashDefinition88 size_t Hash(const StateEntry* value) const
89 {
90 return HashKey(*value);
91 }
92
CompareVariablesViewStateHistory::StateEntryHashDefinition93 bool Compare(const Key& key, const StateEntry* value) const
94 {
95 return key == *value;
96 }
97
GetLinkVariablesViewStateHistory::StateEntryHashDefinition98 StateEntry*& GetLink(StateEntry* value) const
99 {
100 return value->next;
101 }
102 };
103
104
VariablesViewStateHistory()105 VariablesViewStateHistory::VariablesViewStateHistory()
106 :
107 fStates(NULL)
108 {
109 }
110
111
~VariablesViewStateHistory()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
Init()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*
GetState(thread_id threadID,FunctionID * functionID) const140 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*
GetState(FunctionID * functionID) const157 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
SetState(thread_id threadID,FunctionID * functionID,VariablesViewState * state)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