blob: 2cae8a7391eadce7a76e18cd2cf84cf4edd7ea40 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 2004-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17//
18// As a special exception, you may use this file as part of a free software
19// library without restriction. Specifically, if other files instantiate
20// templates or use macros or inline functions from this file, or you compile
21// this file and link it with other files to produce an executable, this
22// file does not by itself cause the resulting executable to be covered by
23// the GNU General Public License. This exception does not however
24// invalidate any other reasons why the executable file might be covered by
25// the GNU General Public License.
26//
27// This exception applies only to the code released under the name GNU
28// Common C++. If you copy code from other releases into a copy of GNU
29// Common C++, as the General Public License permits, the exception does
30// not apply to the code that you add in this way. To avoid misleading
31// anyone as to the status of such modified files, you must delete
32// this exception notice from them.
33//
34// If you write modifications of your own for GNU Common C++, it is your choice
35// whether to permit this exception to apply to your modifications.
36// If you do not wish that, delete this exception notice.
37//
38
39#include <cc++/config.h>
40#include <cc++/export.h>
41#include <cc++/thread.h>
42#include <cc++/object.h>
43#include "private.h"
44
45#ifdef CCXX_NAMESPACES
46namespace ost {
47#endif
48
49MapIndex& MapIndex::operator=(MapObject *theObject)
50{
51 thisObject = theObject;
52 return *this;
53}
54
55MapIndex& MapIndex::operator++()
56{
57 if ( thisObject == NULL )
58 return *this;
59
60 if (thisObject->nextObject != NULL) {
61 thisObject = thisObject->nextObject;
62 }
63 else if (thisObject->table != NULL) {
64 MapObject* obj = NULL;
65 unsigned i = thisObject->table->getIndex(thisObject->idObject) + 1;
66
67
68 thisObject->table->enterMutex();
69 for ( ; obj == NULL && i < thisObject->table->range; i++)
70 obj = thisObject->table->map[i];
71 thisObject->table->leaveMutex();
72
73 thisObject = obj;
74 }
75
76 return *this;
77}
78
79MapTable::MapTable(unsigned size) :
80Mutex()
81{
82 map = new MapObject *[size + 1];
83 memset(map, 0, sizeof(MapObject *) * (size + 1));
84 range = size;
85 count = 0;
86}
87
88MapTable::~MapTable()
89{
90 cleanup();
91}
92
93void MapTable::cleanup(void)
94{
95 enterMutex();
96 if(map)
97 delete[] map;
98 map = NULL;
99 leaveMutex();
100}
101
102unsigned MapTable::getIndex(const char *id)
103{
104 unsigned key = 0;
105
106 while(*id)
107 key = (key << 1) ^ (*(id++) & 0x1f);
108
109 return key % range;
110}
111
112void *MapTable::getObject(const char *id)
113{
114 if(!map)
115 return NULL;
116
117 enterMutex();
118 MapObject *obj = map[getIndex(id)];
119
120 while(obj) {
121 if(!stricmp(obj->idObject, id))
122 break;
123 obj = obj->nextObject;
124 }
125 leaveMutex();
126 return (void *)obj;
127}
128
129void *MapTable::getFirst()
130{
131 MapObject *obj;
132
133 if(!map)
134 return NULL;
135
136 enterMutex();
137 obj = *map;
138 for (register unsigned i = 0; obj == NULL && i < range; i++)
139 obj = map[i];
140 leaveMutex();
141 return obj;
142}
143
144void *MapTable::getLast()
145{
146 MapObject *obj = NULL;
147
148 if(!map)
149 return NULL;
150
151 enterMutex();
152 for (register int i = range - 1; obj == NULL && i >= 0; i--)
153 obj = map[i];
154
155 if ( obj != NULL )
156 while ( obj->nextObject != NULL )
157 obj = obj->nextObject;
158 leaveMutex();
159 return obj;
160}
161
162void *MapTable::getFree(void)
163{
164 enterMutex();
165 MapObject *obj = map[range];
166 if(obj)
167 map[range] = obj->nextObject;
168 leaveMutex();
169 return obj;
170}
171
172void MapTable::addFree(MapObject *obj)
173{
174 obj->detach();
175 enterMutex();
176 obj->nextObject = map[range];
177 map[range] = obj;
178 leaveMutex();
179}
180
181void MapTable::addObject(MapObject &obj)
182{
183 unsigned idx = getIndex(obj.idObject);
184
185 if(obj.table == this || !map)
186 return;
187
188 obj.detach();
189 enterMutex();
190 obj.nextObject = map[idx];
191 map[idx] = &obj;
192 obj.table = this;
193 count++;
194 leaveMutex();
195}
196
197MapTable &MapTable::operator+=(MapObject &obj)
198{
199 addObject(obj);
200 return *this;
201}
202
203MapTable &MapTable::operator-=(MapObject &obj)
204{
205 if(obj.table == this)
206 obj.detach();
207 return *this;
208}
209
210MapObject::MapObject(const char *id)
211{
212 table = NULL;
213 idObject = id;
214}
215
216void MapObject::detach(void)
217{
218 MapObject *node, *prev = NULL;
219 unsigned idx;
220
221 if(!table)
222 return;
223
224 idx = table->getIndex(idObject);
225 table->enterMutex();
226 node = table->map[idx];
227
228 while(node) {
229 if(node == this)
230 break;
231 prev = node;
232 node = prev->nextObject;
233 }
234
235 if(node && !prev)
236 table->map[idx] = nextObject;
237 else if(node)
238 prev->nextObject = nextObject;
239 table->count--;
240 table->leaveMutex();
241 table = NULL;
242}
243
244#ifdef CCXX_NAMESPACES
245}
246#endif
247
248/** EMACS **
249 * Local variables:
250 * mode: c++
251 * c-basic-offset: 4
252 * End:
253 */