xref: /haiku/src/apps/debugger/user_interface/gui/model/VariablesViewStateHistory.cpp (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
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