core/vgui/vgui_tag.h
Go to the documentation of this file.
00001 // This is core/vgui/vgui_tag.h
00002 #ifndef vgui_tag_h_
00003 #define vgui_tag_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief  Allow clients to register 'tag functions' which are called later.
00010 // \author fsm
00011 //
00012 // Real Purpose:
00013 //
00014 // An impl library "blah" should register a tag function at library
00015 // initialization time. The old method, where a library had a line
00016 // something like
00017 // \code
00018 //   static vgui_blah *init_dummy = new vgui_blah;
00019 // \endcode
00020 // caused problems (segv) if a vgui_blah uses run-time libraries which
00021 // have not yet been initialized. No particular order of library
00022 // initialization may be assumed, so static objects in libA might not
00023 // yet have been constructed when libB is initialized.
00024 //
00025 // The workaround provided by vgui_tag is to make impl libraries register
00026 // tag functions instead. Class vgui then promises to call all the
00027 // registered tag functions near the beginning of vgui::init(); There
00028 // is no problem with registering function pointers, as these are POD
00029 // (Plain Old Data). Thus, vgui_blah_tag.cxx now looks like this :
00030 // \code
00031 //   static int vgui_blah_function() { new vgui_blah; return 0; }
00032 //   int vgui_blah_tag = vgui_tag_add(vgui_blah_function, "blah");
00033 // \endcode
00034 // Thus, when 'vgui_blah_tag' is initialized, the tag function called
00035 // 'vgui_blah_tag_function' is registered. There is no instance of
00036 // vgui_blah created until that tag function is called by vgui::init().
00037 //
00038 // \verbatim
00039 //  Modifications
00040 //   07-AUG-2002 K.Y.McGaul - Changed to Doxygen style comments.
00041 // \endverbatim
00042 
00043 //: The type of a tag function.
00044 typedef int (*vgui_tag_function)(void);
00045 
00046 //: Registers a tag function - returns 0.
00047 int vgui_tag_add(vgui_tag_function, char const *);
00048 
00049 //: Returns null-terminated list of tag functions.
00050 vgui_tag_function const *vgui_tag_list();
00051 
00052 //: Call all registered tag functions and remove them from the list.
00053 void                     vgui_tag_call();
00054 
00055 // Easy macro. It will provide two external symbols
00056 //  int vgui_${tk}_tag;
00057 //  int vgui_${tk}_tag_function();
00058 // which may be pulled from the link line. The
00059 // function is idempotent in the sense that calling
00060 // it multiple times will not have any further side
00061 // effects and will given the same return value.
00062 #define vgui_tag(tk) \
00063 int vgui_##tk##_tag_function(); \
00064 int vgui_##tk##_tag = vgui_tag_add(vgui_##tk##_tag_function, #tk); \
00065 static int vgui_##tk##_tag_function_(); \
00066 int vgui_##tk##_tag_function() { \
00067   static bool once = false; \
00068   static int  value = 0; \
00069   if (!once) \
00070     value = vgui_##tk##_tag_function_(); \
00071   once = true; \
00072   return value; \
00073 } \
00074 int vgui_##tk##_tag_function_()
00075 
00076 #endif // vgui_tag_h_