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_