blob: a843fec953f8f15076ff95a2418823e50169b9ce [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// 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 <ucommon-config.h>
40#include <commoncpp/config.h>
41#include <commoncpp/export.h>
42#include <commoncpp/thread.h>
43#include <commoncpp/object.h>
44
45using namespace COMMONCPP_NAMESPACE;
46
47MapIndex& MapIndex::operator=(MapObject *theObject)
48{
49 thisObject = theObject;
50 return *this;
51}
52
53MapIndex& MapIndex::operator++()
54{
55 if ( thisObject == NULL )
56 return *this;
57
58 if (thisObject->nextObject != NULL) {
59 thisObject = thisObject->nextObject;
60 }
61 else if (thisObject->table != NULL) {
62 MapObject* obj = NULL;
63 unsigned i = thisObject->table->getIndex(thisObject->idObject) + 1;
64
65
66 thisObject->table->enterMutex();
67 for ( ; obj == NULL && i < thisObject->table->range; i++)
68 obj = thisObject->table->map[i];
69 thisObject->table->leaveMutex();
70
71 thisObject = obj;
72 }
73
74 return *this;
75}
76
77MapTable::MapTable(unsigned size) :
78Mutex()
79{
80 map = new MapObject *[size + 1];
81 memset(map, 0, sizeof(MapObject *) * (size + 1));
82 range = size;
83 count = 0;
84}
85
86MapTable::~MapTable()
87{
88 cleanup();
89}
90
91void MapTable::cleanup(void)
92{
93 enterMutex();
94 if(map)
95 delete[] map;
96 map = NULL;
97 leaveMutex();
98}
99
100unsigned MapTable::getIndex(const char *id)
101{
102 unsigned key = 0;
103
104 while(*id)
105 key = (key << 1) ^ (*(id++) & 0x1f);
106
107 return key % range;
108}
109
110void *MapTable::getObject(const char *id)
111{
112 if(!map)
113 return NULL;
114
115 enterMutex();
116 MapObject *obj = map[getIndex(id)];
117
118 while(obj) {
119 if(!stricmp(obj->idObject, id))
120 break;
121 obj = obj->nextObject;
122 }
123 leaveMutex();
124 return (void *)obj;
125}
126
127void *MapTable::getFirst()
128{
129 MapObject *obj;
130
131 if(!map)
132 return NULL;
133
134 enterMutex();
135 obj = *map;
136 for (register unsigned i = 0; obj == NULL && i < range; i++)
137 obj = map[i];
138 leaveMutex();
139 return obj;
140}
141
142void *MapTable::getLast()
143{
144 MapObject *obj = NULL;
145
146 if(!map)
147 return NULL;
148
149 enterMutex();
150 for (register int i = range - 1; obj == NULL && i >= 0; i--)
151 obj = map[i];
152
153 if ( obj != NULL )
154 while ( obj->nextObject != NULL )
155 obj = obj->nextObject;
156 leaveMutex();
157 return obj;
158}
159
160void *MapTable::getFree(void)
161{
162 enterMutex();
163 MapObject *obj = map[range];
164 if(obj)
165 map[range] = obj->nextObject;
166 leaveMutex();
167 return obj;
168}
169
170void MapTable::addFree(MapObject *obj)
171{
172 obj->detach();
173 enterMutex();
174 obj->nextObject = map[range];
175 map[range] = obj;
176 leaveMutex();
177}
178
179void MapTable::addObject(MapObject &obj)
180{
181 unsigned idx = getIndex(obj.idObject);
182
183 if(obj.table == this || !map)
184 return;
185
186 obj.detach();
187 enterMutex();
188 obj.nextObject = map[idx];
189 map[idx] = &obj;
190 obj.table = this;
191 count++;
192 leaveMutex();
193}
194
195MapTable &MapTable::operator+=(MapObject &obj)
196{
197 addObject(obj);
198 return *this;
199}
200
201MapTable &MapTable::operator-=(MapObject &obj)
202{
203 if(obj.table == this)
204 obj.detach();
205 return *this;
206}
207
208MapObject::MapObject(const char *id)
209{
210 table = NULL;
211 idObject = id;
212}
213
214void MapObject::detach(void)
215{
216 MapObject *node, *prev = NULL;
217 unsigned idx;
218
219 if(!table)
220 return;
221
222 idx = table->getIndex(idObject);
223 table->enterMutex();
224 node = table->map[idx];
225
226 while(node) {
227 if(node == this)
228 break;
229 prev = node;
230 node = prev->nextObject;
231 }
232
233 if(node && !prev)
234 table->map[idx] = nextObject;
235 else if(node)
236 prev->nextObject = nextObject;
237 table->count--;
238 table->leaveMutex();
239 table = NULL;
240}