| Josh Dybnis on 18 Jun 2003 21:56:01 -0000 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
| Re: [ALACPP] Singleton clarification |
More C macro fun. Singleton this time; much simpler than functors. -Josh Dybnis
/****************************************************************************/
/******* C port of Singleton from Chapter 6 of "Modern C++ Design" **********/
/****************************************************************************/
/** singleton.h *************************************************************/
#define DECLARE_SINGLETON(type, name) \
type get_##name (void);
#define DEFINE_SINGLETON(type, name, destructor, longevity, constructor, ...) \
static type I_##name; \
static int I_##name##_initialized; \
static int I_##name##_destroyed; \
static void I_destroy_##name (void) \
{ \
destructor(get_##name()); \
I_##name##_destroyed = 1; \
} \
type get_##name (void) \
{ \
assert(!I_##name##_destroyed); \
if (!I_##name##_initialized) \
{ \
I_##name = constructor(__VA_ARGS__); \
DestroyAtExit(I_destroy_##name, longevity); \
I_##name##_initialized = 1; \
} \
return I_##name; \
}
typedef double longevity_t;
void DestroyAtExit (void (*destroyer)(void), longevity_t longevity);
/** singleton.c *************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
typedef struct tracker
{ void (*destroyer)(void);
longevity_t longevity;
} Tracker;
static Tracker *TrackerArray = NULL;
static unsigned int TrackerCount = 0;
static unsigned int TrackerMax = 16;
static void DestroyTop (void)
{
Tracker top;
assert(TrackerArray);
assert(TrackerCount);
top = TrackerArray[--TrackerCount];
top.destroyer();
}
void DestroyAtExit (void (*destroyer)(void), longevity_t longevity)
{
Tracker *t, *end;
/* ensure that TrackerArray is large enough to hold one more element */
if (TrackerCount == TrackerMax || !TrackerArray)
{
TrackerMax *= 2;
TrackerArray = realloc(TrackerArray, sizeof(Tracker) * TrackerMax);
if (!TrackerArray)
printf("SetLongevity(): alloc failed\n");
}
assert(TrackerArray);
/* make room for a new element at the right place in the TrackerArray */
t = TrackerArray;
end = TrackerArray + TrackerCount; /* points to one past last element */
while (t < end && t->longevity > longevity)
++t;
if (t != end)
memmove(t+1, t, (end - t) * sizeof(*t));
TrackerCount++;
/* initialize new element in the TrackerArray and register with atexit */
t->destroyer = destroyer;
t->longevity = longevity;
atexit(DestroyTop);
}
/** test.c ******************************************************************/
DECLARE_SINGLETON(int *, alpha);
DECLARE_SINGLETON(int *, beta);
int *newFoo (int i)
{
int *p;
p = (int *) malloc(sizeof(int));
*p = i;
return p;
}
void deleteInt(int *p)
{
printf("deleteInt(): %d\n", *p);
free(p);
};
DEFINE_SINGLETON (int *, alpha, deleteInt, 1, newFoo, 5);
DEFINE_SINGLETON (int *, beta, deleteInt, 2, newFoo, 6);
int main(void)
{
get_beta();
get_alpha();
return 0;
}