//****************************************************************************************
//
//
// This implementation file contains classes and templates needed
// to implement standard interfaces used in the
// engine. The two sections are the interface holder class
// and the API database class.
//
//
//****************************************************************************************
//for other functions and symbols
#include "ltbasedefs.h"
//the module headers.
#include "ltmodule.h"
//****************************************************************************************
//****************************************************************************************
//
// Template classes that might be moved to a widely accessible location.
//
//****************************************************************************************
//****************************************************************************************
//
//Sorted array of pointers to objects.
//
//The compare and find functions return RELATION_LESS if the relation of
//the given objects is "less than", RELATION_EQUAL if they are "equal",
//and RELATION_GREATER if the relation of the given objects is "greater than".
//The find function operates in a similar way but instead takes only
//one object and a templated-type ID.
//
enum RELATION {
RELATION_LESS,
RELATION_EQUAL,
RELATION_GREATER,
};
template <class C, class id_type>
class database_array {
public:
database_array();
~database_array();
//returns the number of items in the array.
uint32 Num();
//adds an item to the array. takes the compare function to use.
void add(C *item, RELATION (*compare_func)(C *other, C *obj));
//gets an item, given its ID and find function.
C *get(id_type identifier, RELATION (*find_func)(id_type identifier, C *obj));
//removes an item, given its ID and a find function.
C *remove(id_type identifier, RELATION (*find_func)(id_type identifier, C *obj));
//removes the last item in the array.
C *remove_last();
//removes the given item. returns true if the item was actually removed.
bool remove(C *item);
//removes the item at the given index.
void remove(uint32 index);
//gets the item at the given index.
C *get(uint32 index);
protected:
//the number of items in the array.
uint32 num_items;
//the length of our array
uint32 array_len;
//the array of pointers.
C **items;
//lengthens the array.
void lengthen();
//searches with the find function for the index of an item with the given identifier.
//returns -1 if it could not find an item.
int32 index(id_type identifier, RELATION (*find_func)(id_type identifier, C *obj));
//inserts the element into the array at the given index, which
//can be any value >= 0 and <= num_items. Items below are shifted
//down.
void insert(C *item, uint32 index);
//removes the item from the array, items after it are all shifted up.
void remove_shift(uint32 index);
};
//
//Database list template. Used to store unsorted collections of elements.
//
template <class C>
class database_list {
public:
database_list();
~database_list();
//returns the number of items in the array.
uint32 Num();
//adds an item to end of the array
void add(C *item);
//removes the item at the given index and returns it.
C *remove(uint32 index);
//removes the given item. returns true if the item was actually removed.
//the last item is moved up in the array to fill the space vacated by the
//removed item.
bool remove(C *item);
//same as remove, but shifts elements below the removed one to fill the gap
bool remove_shift(C *item);
//gets the item at the given index.
C *get(uint32 index);
protected:
//the number of items in the array.
uint32 num_items;
//the length of our array
uint32 array_len;
//the array of pointers.
C **items;
//lengthens the array.
void lengthen();
};
//****************************************************************************************
//****************************************************************************************
//
//
// API Database implementation.
//
//
//****************************************************************************************
//****************************************************************************************
//struct to hold local pointers to our database. We put them in a struct
//and allocate the struct when we need to use the pointers so that
//the pointer constructors will get called before operations try to use them
//within other global variable constructors.
//The pointers themselves have a different lifetime than the database.
//Our local pointers will be destroyed as soon as all the APIs and holders from this
//executable (EXE or DLL) have been removed from the database, or when the executable
//itself is unloaded. The lifetime of the database itself is separate from these
//pointers; it will be deallocated when it is empty of all APIs and holders
//gathered from all executables.
class CDatabasePtrs {
public:
//Our database. When the first API is registered when this EXE or DLL is loaded,
//the object will be allocated and the API inserted.
CPointerTracked<CInterfaceDatabase> local_database;
//The master database. If we are informed of the existence of the master,
//we will transfer our data to it and use it from then on.
CPointerTracked<CInterfaceDatabase> master_database;
//The database we actually will use. It could be either our local database
//or the master database.
CPointerTracked<CInterfaceDatabase> use_database;
};
//allocated structure of pointers.
static CDatabasePtrs *ptrs = NULL;
//a count of APIs/holders/choosers that we have in the database from this EXE/DLL
static int32 database_item_count = 0;
//Allocates the pointers if they aren't already allocated.
static __inline void check_create_pointers()
{
if (ptrs == NULL)
{
LT_MEM_TRACK_ALLOC(ptrs = new CDatabasePtrs, LT_MEM_TYPE_INTERFACEDB);
}
}
//Deletes the pointers if we have no apis/holders
//from this DLL/EXE in the database.
static __inline void check_delete_pointers()
{
if (ptrs != NULL && database_item_count < 1)
{
delete ptrs;
ptrs = NULL;
}
}
void CInterfaceDatabase::DatabaseItemCountInc() {
//increment the global count.
database_item_count++;
//create the pointers struct.
check_create_pointers();
}
void CInterfaceDatabase::DatabaseItemCountDec() {
//decrement the global count.
database_item_count--;
//check if we should delete the pointers structure
check_delete_pointers();
}
//make sure we deallocate our pointers on shutdown.
//We either delete the pointers at the time we remove
//the last api or holder that we added to it, or we
//delete it here if we never added/removed any api's or
//holders.
FILE_SHUTDOWN(ltmod_database)
{
//check if we should delete them now.
check_delete_pointers();
}
CInterfaceDatabase::CInterfaceDatabase()
{
//allocate our array.
typedef database_array<CInterfaceNameMgr, const char *> TAllocType;
LT_MEM_TRACK_ALLOC(interfaces = new TAllocType, LT_MEM_TYPE_INTERFACEDB);
}
CInterfaceDatabase::~CInterfaceDatabase() {