blob: 2cae8a7391eadce7a76e18cd2cf84cf4edd7ea40 [file] [log] [blame]
// Copyright (C) 2004-2005 Open Source Telecom Corporation.
// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
//
// This exception applies only to the code released under the name GNU
// Common C++. If you copy code from other releases into a copy of GNU
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way. To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for GNU Common C++, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.
//
#include <cc++/config.h>
#include <cc++/export.h>
#include <cc++/thread.h>
#include <cc++/object.h>
#include "private.h"
#ifdef CCXX_NAMESPACES
namespace ost {
#endif
MapIndex& MapIndex::operator=(MapObject *theObject)
{
thisObject = theObject;
return *this;
}
MapIndex& MapIndex::operator++()
{
if ( thisObject == NULL )
return *this;
if (thisObject->nextObject != NULL) {
thisObject = thisObject->nextObject;
}
else if (thisObject->table != NULL) {
MapObject* obj = NULL;
unsigned i = thisObject->table->getIndex(thisObject->idObject) + 1;
thisObject->table->enterMutex();
for ( ; obj == NULL && i < thisObject->table->range; i++)
obj = thisObject->table->map[i];
thisObject->table->leaveMutex();
thisObject = obj;
}
return *this;
}
MapTable::MapTable(unsigned size) :
Mutex()
{
map = new MapObject *[size + 1];
memset(map, 0, sizeof(MapObject *) * (size + 1));
range = size;
count = 0;
}
MapTable::~MapTable()
{
cleanup();
}
void MapTable::cleanup(void)
{
enterMutex();
if(map)
delete[] map;
map = NULL;
leaveMutex();
}
unsigned MapTable::getIndex(const char *id)
{
unsigned key = 0;
while(*id)
key = (key << 1) ^ (*(id++) & 0x1f);
return key % range;
}
void *MapTable::getObject(const char *id)
{
if(!map)
return NULL;
enterMutex();
MapObject *obj = map[getIndex(id)];
while(obj) {
if(!stricmp(obj->idObject, id))
break;
obj = obj->nextObject;
}
leaveMutex();
return (void *)obj;
}
void *MapTable::getFirst()
{
MapObject *obj;
if(!map)
return NULL;
enterMutex();
obj = *map;
for (register unsigned i = 0; obj == NULL && i < range; i++)
obj = map[i];
leaveMutex();
return obj;
}
void *MapTable::getLast()
{
MapObject *obj = NULL;
if(!map)
return NULL;
enterMutex();
for (register int i = range - 1; obj == NULL && i >= 0; i--)
obj = map[i];
if ( obj != NULL )
while ( obj->nextObject != NULL )
obj = obj->nextObject;
leaveMutex();
return obj;
}
void *MapTable::getFree(void)
{
enterMutex();
MapObject *obj = map[range];
if(obj)
map[range] = obj->nextObject;
leaveMutex();
return obj;
}
void MapTable::addFree(MapObject *obj)
{
obj->detach();
enterMutex();
obj->nextObject = map[range];
map[range] = obj;
leaveMutex();
}
void MapTable::addObject(MapObject &obj)
{
unsigned idx = getIndex(obj.idObject);
if(obj.table == this || !map)
return;
obj.detach();
enterMutex();
obj.nextObject = map[idx];
map[idx] = &obj;
obj.table = this;
count++;
leaveMutex();
}
MapTable &MapTable::operator+=(MapObject &obj)
{
addObject(obj);
return *this;
}
MapTable &MapTable::operator-=(MapObject &obj)
{
if(obj.table == this)
obj.detach();
return *this;
}
MapObject::MapObject(const char *id)
{
table = NULL;
idObject = id;
}
void MapObject::detach(void)
{
MapObject *node, *prev = NULL;
unsigned idx;
if(!table)
return;
idx = table->getIndex(idObject);
table->enterMutex();
node = table->map[idx];
while(node) {
if(node == this)
break;
prev = node;
node = prev->nextObject;
}
if(node && !prev)
table->map[idx] = nextObject;
else if(node)
prev->nextObject = nextObject;
table->count--;
table->leaveMutex();
table = NULL;
}
#ifdef CCXX_NAMESPACES
}
#endif
/** EMACS **
* Local variables:
* mode: c++
* c-basic-offset: 4
* End:
*/