1/*
2 * Copyright 2001-2011, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Erik Jaesler (erik@cgsoftware.com)
7 *		Axel Dörfler, axeld@pinc-software.de
8 */
9
10
11#include <DirectMessageTarget.h>
12#include <TokenSpace.h>
13
14#include <Autolock.h>
15
16
17namespace BPrivate {
18
19BTokenSpace gDefaultTokens;
20	// the default token space - all handlers will go into that one
21
22
23BTokenSpace::BTokenSpace()
24	:
25	BLocker("token space"),
26	fTokenCount(1)
27{
28}
29
30
31BTokenSpace::~BTokenSpace()
32{
33}
34
35
36int32
37BTokenSpace::NewToken(int16 type, void* object)
38{
39	BAutolock locker(this);
40
41	token_info tokenInfo = { type, object, NULL };
42	int32 token = fTokenCount;
43
44	try {
45		fTokenMap[token] = tokenInfo;
46	} catch (std::bad_alloc& exception) {
47		return -1;
48	}
49
50	fTokenCount++;
51
52	return token;
53}
54
55
56/*!
57	Inserts the specified token into the token space. If that token
58	already exists, it will be overwritten.
59	Don't mix NewToken() and this method unless you know what you're
60	doing.
61*/
62bool
63BTokenSpace::SetToken(int32 token, int16 type, void* object)
64{
65	BAutolock locker(this);
66
67	token_info tokenInfo = { type, object, NULL };
68
69	try {
70		fTokenMap[token] = tokenInfo;
71	} catch (std::bad_alloc& exception) {
72		return false;
73	}
74
75	// this makes sure SetToken() plays more or less nice with NewToken()
76	if (token >= fTokenCount)
77		fTokenCount = token + 1;
78
79	return true;
80}
81
82
83bool
84BTokenSpace::RemoveToken(int32 token)
85{
86	BAutolock locker(this);
87
88	TokenMap::iterator iterator = fTokenMap.find(token);
89	if (iterator == fTokenMap.end())
90		return false;
91
92	fTokenMap.erase(iterator);
93	return true;
94}
95
96
97/*!	Checks whether or not the \a token exists with the specified
98	\a type in the token space or not.
99*/
100bool
101BTokenSpace::CheckToken(int32 token, int16 type) const
102{
103	BAutolock locker(const_cast<BTokenSpace&>(*this));
104
105	TokenMap::const_iterator iterator = fTokenMap.find(token);
106	if (iterator != fTokenMap.end() && iterator->second.type == type)
107		return true;
108
109	return false;
110}
111
112
113status_t
114BTokenSpace::GetToken(int32 token, int16 type, void** _object) const
115{
116	if (token < 1)
117		return B_ENTRY_NOT_FOUND;
118
119	BAutolock locker(const_cast<BTokenSpace&>(*this));
120
121	TokenMap::const_iterator iterator = fTokenMap.find(token);
122	if (iterator == fTokenMap.end() || iterator->second.type != type)
123		return B_ENTRY_NOT_FOUND;
124
125	*_object = iterator->second.object;
126	return B_OK;
127}
128
129
130status_t
131BTokenSpace::SetHandlerTarget(int32 token, BDirectMessageTarget* target)
132{
133	if (token < 1)
134		return B_ENTRY_NOT_FOUND;
135
136	BAutolock locker(const_cast<BTokenSpace&>(*this));
137
138	TokenMap::iterator iterator = fTokenMap.find(token);
139	if (iterator == fTokenMap.end() || iterator->second.type != B_HANDLER_TOKEN)
140		return B_ENTRY_NOT_FOUND;
141
142	if (iterator->second.target != NULL)
143		iterator->second.target->Release();
144
145	iterator->second.target = target;
146	if (target != NULL)
147		target->Acquire();
148
149	return B_OK;
150}
151
152
153status_t
154BTokenSpace::AcquireHandlerTarget(int32 token, BDirectMessageTarget** _target)
155{
156	if (token < 1)
157		return B_ENTRY_NOT_FOUND;
158
159	BAutolock locker(const_cast<BTokenSpace&>(*this));
160
161	TokenMap::const_iterator iterator = fTokenMap.find(token);
162	if (iterator == fTokenMap.end() || iterator->second.type != B_HANDLER_TOKEN)
163		return B_ENTRY_NOT_FOUND;
164
165	if (iterator->second.target != NULL)
166		iterator->second.target->Acquire();
167
168	*_target = iterator->second.target;
169	return B_OK;
170}
171
172
173void
174BTokenSpace::InitAfterFork()
175{
176	// We need to reinitialize the locker to get a new semaphore
177	new (this) BTokenSpace();
178}
179
180
181}	// namespace BPrivate
182