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