static_memory_gremlin.h

Go to the documentation of this file.
00001 #ifndef STATIC_MEMORY_GREMLIN_CLASS
00002 #define STATIC_MEMORY_GREMLIN_CLASS
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : static_memory_gremlin                                             *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *******************************************************************************
00010 * Copyright (c) 1992-$now By Author.  This program is free software; you can  *
00011 * redistribute it and/or modify it under the terms of the GNU General Public  *
00012 * License as published by the Free Software Foundation; either version 2 of   *
00013 * the License or (at your option) any later version.  This is online at:      *
00014 *     http://www.fsf.org/copyleft/gpl.html                                    *
00015 * Please send any updates to: fred@gruntose.com                               *
00016 \*****************************************************************************/
00017 
00018 #include "data_structure_dll.h"
00019 
00020 #include <basis/callstack_tracker.h>
00021 #include <basis/memory_checker.h>
00022 #include <basis/mutex.h>
00023 #include <basis/portable.h>
00024 
00025 // forward:
00026 class object_base;
00027 class object_base_record;
00028 
00030 
00037 class DATA_STRUCTURE_CLASS_STYLE static_memory_gremlin
00038 {
00039 public:
00040   static_memory_gremlin();
00041 
00042   ~static_memory_gremlin();
00051   void enable_debugging(bool verbose) { _show_debugging = verbose; }
00053 
00054   bool put(const char *unique_name, object_base *ptr);
00056 
00060   object_base *get(const char *unique_name);
00062 
00066   const char *find(const object_base *ptr);
00068 
00070   void ensure_space_exists();
00074 private:
00075   mutex *_lock;  
00076   int _top_index;  
00077   int _actual_size;  
00078   object_base_record **_pointers_held;  
00079   bool _show_debugging;  
00080 
00081   int locate(const char *unique_name);
00083 };
00084 
00086 
00087 bool DATA_STRUCTURE_FUNCTION_STYLE program_is_dying();
00089 
00094 static_memory_gremlin DATA_STRUCTURE_FUNCTION_STYLE &HOOPLE_GLOBALS();
00096 
00099 
00100 
00101 mutex DATA_STRUCTURE_FUNCTION_STYLE &__memory_gremlin_synchronizer();
00103 
00113 
00114 
00115 // the following functions are for internal use only.  do not mess around
00116 // with these unless you enjoy program deadlocks or other bizarre crashes.
00117 
00118 bool DATA_STRUCTURE_FUNCTION_STYLE program_is_dying();
00120 
00121 const char DATA_STRUCTURE_FUNCTION_STYLE *EXCEPTION_INFO_FOR_SHUTTING_DOWN();
00123 
00126 
00127 
00128 // historical note: the SAFE_STATIC approach has existed since about 1998.
00129 // however, the static_memory_gremlin's role in this started much later.
00130 // so the following portions should be considered GPL with copyright 1998
00131 // and onwards.
00132 
00134 
00159 #define SAFE_STATIC(type, func_name, parms) \
00160   type &func_name() { SAFE_STATIC_IMPLEMENTATION(type, parms, __LINE__); }
00161 
00163 #define SAFE_STATIC_CONST(type, func_name, parms) \
00164   const type &func_name() \
00165   { SAFE_STATIC_IMPLEMENTATION(type, parms, __LINE__); }
00166 
00168 
00173 #define STATIC_STRING(str) \
00174   SAFE_STATIC_IMPLEMENTATION(istring_object, (str), __LINE__)
00175 
00177 #define UNIQUE_NAME_BASED_ON_SOURCE(name, linenum) \
00178   static const char *name = "file:" __FILE__ ":line:" #linenum
00179 
00181 
00186 #define SAFE_STATIC_IMPLEMENTATION(type, parms, linenum) \
00187   const char *func = "allocation"; \
00188   frame_tracking_instance __trail_of_function("safe_static", func, \
00189       __FILE__, __LINE__, true); \
00190   UNIQUE_NAME_BASED_ON_SOURCE(__uid_name, linenum); \
00191   program_wide_memories(); \
00192   static object_base *_hidden = NIL; \
00193   /* if haven't initialized yet, then definitely need to lock carefully. */ \
00194   if (program_is_dying() || !_hidden) { \
00195     auto_synchronizer l(__memory_gremlin_synchronizer()); \
00196     if (program_is_dying()) { \
00197       /* we can't rely on the pointer since we're shutting down currently. */ \
00198       _hidden = HOOPLE_GLOBALS().get(__uid_name); \
00199     } \
00200     if (!_hidden) {  /* make sure no one scooped us. */ \
00201       /* try to retrieve an existing one first and use it if there. */ \
00202       _hidden = HOOPLE_GLOBALS().get(__uid_name); \
00203       if (!_hidden) { \
00204         _hidden = new type parms ; /* create the object finally. */ \
00205         /* store our object using the unique name for it. */ \
00206         if (!HOOPLE_GLOBALS().put(__uid_name, _hidden)) { \
00207           /* we failed to allocate space.  this is serious. */ \
00208           throw __uid_name; \
00209         } \
00210       } \
00211     } \
00212   } \
00213   if (!_hidden) { \
00214     /* grab the pointer that was stored, in case we're late getting here. */ \
00215     /* another thread might have scooped the object creation. */ \
00216     _hidden = HOOPLE_GLOBALS().get(__uid_name); \
00217   } \
00218   return *dynamic_cast<type *>(_hidden)
00219 
00221 
00223 
00224 class DATA_STRUCTURE_CLASS_STYLE library_wide_cleanup
00225 {
00226 public:
00227   library_wide_cleanup();
00229 
00230   ~library_wide_cleanup();
00231 
00232 private:
00233   static_memory_gremlin *_shared_chunks;  
00234 };
00235 
00237 
00239 
00240 class DATA_STRUCTURE_CLASS_STYLE program_wide_cleanup
00241 {
00242 public:
00243   program_wide_cleanup();
00244   ~program_wide_cleanup();
00245 };
00246 
00248 
00249 /*
00250   The HOOPLE_STARTUP_CODE macro must be deployed once and only once in
00251   each program that uses the HOOPLE libraries.  If it isn't provided, then
00252   link errors may result.  The macro ensures that some of the critical internal
00253   objects are defined and created properly for the program's use.
00254 */
00255 
00257 
00259 #define HOOPLE_STARTUP_CODE_DLL \
00260   DEFINE_ARGC_AND_ARGV;  /* any OS specific code. */ \
00261   DEFINE_INSTANCE_HANDLE;  /* set up the instance handle. */ \
00262   static library_wide_cleanup _jean_reno
00263 
00265 
00268 #define HOOPLE_STARTUP_CODE \
00269   HOOPLE_STARTUP_CODE_DLL; \
00270   /* the creation of this static cleanup object also establishes the \
00271    * static objects that are provided as global hoople services. */ \
00272   static program_wide_cleanup _harvey_keitel
00273 
00275 #define BASIS_STARTUP_CODE_DLL HOOPLE_STARTUP_CODE_DLL
00276 #define BASIS_STARTUP_CODE HOOPLE_STARTUP_CODE
00277 
00278 #endif
00279 

Generated on Sat Aug 30 04:31:45 2008 for HOOPLE Libraries by  doxygen 1.5.1