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; }