1 #ifndef STATIC_MEMORY_GREMLIN_CLASS
2 #define STATIC_MEMORY_GREMLIN_CLASS
4 /*****************************************************************************\
6 * Name : static_memory_gremlin *
7 * Author : Chris Koeritz *
9 *******************************************************************************
10 * Copyright (c) 1992-$now By Author. This program is free software; you can *
11 * redistribute it and/or modify it under the terms of the GNU General Public *
12 * License as published by the Free Software Foundation; either version 2 of *
13 * the License or (at your option) any later version. This is online at: *
14 * http://www.fsf.org/copyleft/gpl.html *
15 * Please send any updates to: fred@gruntose.com *
16 \*****************************************************************************/
18 #include <basis/contracts.h>
19 #include <basis/enhance_cpp.h>
20 #include <basis/mutex.h>
22 namespace structures {
24 // forward declarations.
25 class gremlin_object_record;
27 //! Holds onto memory chunks that are allocated globally within the program.
29 The objects managed by the gremlin do not get destroyed until after the
30 program begins shutting down. This file also provides the SAFE_STATIC macros
31 that can be used for allocating static objects safely in a multi-threaded
35 class static_memory_gremlin : public virtual basis::nameable
38 static_memory_gremlin();
40 ~static_memory_gremlin();
41 /*!< when destroyed, it is assumed that the program's lifetime is over and
42 all objects stored here are now unnecessary. this implements a
43 regenerative scheme for when static shutdowns occur out of order; if an
44 object has already been destroyed, it is recreated for the purposes of
45 other statics being shutdown. eventually this should stabilize since
46 it's completely unacceptable for static objects to depend on each other
49 DEFINE_CLASS_NAME("static_memory_gremlin");
51 static bool __program_is_dying();
52 //!< Reports whether the program is shutting down currently.
53 /*!< If this flag is true, then code should generally just return without
54 doing anything where possible. It's especially important for long
55 running loops or active threads to stop if they see this, although
56 the normal program exit processes usually make it unnecessary. */
58 static static_memory_gremlin &__hoople_globals();
59 //!< Holds onto objects that have been allocated in a program-wide scope.
60 /*!< These objects will have a lifetime up to the point of normal static
61 object destruction and then they will be cleaned up. */
63 static basis::mutex &__memory_gremlin_synchronizer();
64 //!< private object for static_memory_gremlin's use only.
66 void enable_debugging(bool verbose) { c_show_debugging = verbose; }
67 //!< if "verbose" is true, then the object will produce a noisy log.
69 bool put(const char *unique_name, basis::root_object *ptr);
70 //!< adds a "ptr" to the set of static objects under the "unique_name".
71 /*!< the name must really be unique or objects will collide. we recommend
72 using an identifier based on a line number and filename where the static
73 is going to be placed (see the safe static implementation below). */
75 basis::root_object *get(const char *unique_name);
76 //!< locates the pointer held for the "unique_name", if any.
77 /*!< if no pointer exists, then NULL_POINTER is returned. NOTE: the returned
78 pointer must not be destroyed, since the object could be used at any time
79 during the program's lifetime. */
81 const char *find(const basis::root_object *ptr);
82 //!< locates the name for "ptr" in our objects.
83 /*!< if it does not exist, then NULL_POINTER is returned. */
85 void ensure_space_exists();
86 /*!< makes sure that the list of objects is large enough to contain all of
87 the identifiers that have been issued. */
90 basis::mutex c_lock; //!< protects object's state.
91 int c_top_index; //!< top place that's occupied in the list.
92 int c_actual_size; //!< the real number of indices in list.
93 gremlin_object_record **c_pointers; //!< storage for the static pointers.
94 bool c_show_debugging; //!< if true, then the object will log noisily.
96 int locate(const char *unique_name);
97 //!< returns the index number of the "unique_name".
102 //! Statically defines a singleton object whose scope is the program's lifetime.
104 SAFE_STATIC is a macro that dynamically creates a function returning a particular
105 data type. the object is allocated statically, so that the same object will be
106 returned ever after until the program is shut down. the allocation is guarded so
107 that multiple threads cannot create conflicting static objects.
109 note: in ms-win32, if you use this macro in a static library (rather than
110 a DLL), then the heap context is different. thus you could actually have
111 multiple copies of the underlying object. if the object is supposed to
112 be global and unique, then that's a problem. relocating the definitions
113 to a dll while keeping declarations in the static lib works (see the
114 program wide logger approach in <application/program_wide_logger.h>).
115 "type" is the object class to return.
116 "func_name" is the function to be created.
117 "parms" must be a list of parameters in parentheses or nothing.
120 SAFE_STATIC(connection_table, conntab, (parm1, parm2)) @endcode
121 will define a function: connection_table &conntab()
122 that returns a connection table object which has been created safely,
123 given that the main synchronizer was called from the main thread at least
125 SAFE_STATIC(astring, static_string_doodle, ) @endcode
126 will define a static astring object named "static_string_doodle" that uses
127 the default constructor for astrings.
129 #define SAFE_STATIC(type, func_name, parms) \
130 type &func_name() { SAFE_STATIC_IMPLEMENTATION(type, parms, __LINE__); }
132 //! this version returns a constant object instead.
133 #define SAFE_STATIC_CONST(type, func_name, parms) \
134 const type &func_name() \
135 { SAFE_STATIC_IMPLEMENTATION(type, parms, __LINE__); }
137 //! Statically defines a string for the rest of the program's life.
138 /*! This macro can be used to make functions returning a string a little
139 simpler. This can only be used when the string is constant. The usual way
140 to use this macro is in a function that returns a constant reference to a
141 string. The macro allocates the string to be returned statically so that all
142 future calls will refer to the stored string rather than recreating it again. */
143 #define STATIC_STRING(str) \
144 SAFE_STATIC_IMPLEMENTATION(astring, (str), __LINE__)
148 //! this macro creates a unique const char pointer based on file location.
149 #define UNIQUE_NAME_BASED_ON_SOURCE(name, linenum) \
150 static const char *name = "file:" __FILE__ ":line:" #linenum
152 //! this blob is just a chunk of macro implementation for SAFE_STATIC...
153 /*! if the static object isn't initialized yet, we'll create it and store it
154 in the static_memory_gremlin. we make sure that the program isn't shutting
155 down, because that imposes a new requirement--previously created statics might
156 have already been destroyed. thus, during the program shutdown, we carefully
157 recreate any objects that were already toast. */
158 #define SAFE_STATIC_IMPLEMENTATION(type, parms, linenum) \
159 /*hmmm: bring all this back.*/ \
160 /* const char *func = "allocation"; */ \
161 /* frame_tracking_instance __trail_of_function("safe_static", func, \
162 __FILE__, __LINE__, true); */ \
163 UNIQUE_NAME_BASED_ON_SOURCE(__uid_name, linenum); \
164 /* program_wide_memories(); */ \
165 static basis::root_object *_hidden = NULL_POINTER; \
166 /* if haven't initialized yet, then definitely need to lock carefully. */ \
167 if (structures::static_memory_gremlin::__program_is_dying() || !_hidden) { \
168 basis::auto_synchronizer l(structures::static_memory_gremlin::__memory_gremlin_synchronizer()); \
169 if (structures::static_memory_gremlin::__program_is_dying()) { \
170 /* we can't rely on the pointer since we're shutting down currently. */ \
171 _hidden = structures::static_memory_gremlin::__hoople_globals().get(__uid_name); \
173 if (!_hidden) { /* make sure no one scooped us. */ \
174 /* try to retrieve an existing one first and use it if there. */ \
175 _hidden = structures::static_memory_gremlin::__hoople_globals().get(__uid_name); \
177 _hidden = new type parms ; /* create the object finally. */ \
178 /* store our object using the unique name for it. */ \
179 if (!structures::static_memory_gremlin::__hoople_globals().put(__uid_name, _hidden)) { \
180 /* we failed to allocate space. this is serious. */ \
187 /* grab the pointer that was stored, in case we're late getting here. */ \
188 /* another thread might have scooped the object creation. */ \
189 _hidden = structures::static_memory_gremlin::__hoople_globals().get(__uid_name); \
191 return *dynamic_cast<type *>(_hidden)
193 // historical note: the SAFE_STATIC approach has existed since about 1998.
194 // however, the static_memory_gremlin's role in this started much later.