+ if ( sm_classTable )
+ {
+ return (wxClassInfo *)wxClassInfo::sm_classTable->Get(className);
+ }
+ else
+ {
+ for ( wxClassInfo *info = sm_first; info ; info = info->m_next )
+ {
+ if ( className == info->GetClassName() )
+ return info;
+ }
+
+ return NULL;
+ }
+}
+
+// Reentrance can occur on some platforms (Solaris for one), as the use of hash
+// and string objects can cause other modules to load and register classes
+// before the original call returns. This is handled by keeping the hash table
+// local when it is first created and only assigning it to the global variable
+// when the function is ready to return.
+//
+// That does make the assumption that after the function has completed the
+// first time the problem will no longer happen; all the modules it depends on
+// will have been loaded. The assumption is checked using the 'entry' variable
+// as a reentrance guard, it checks that once the hash table is global it is
+// not accessed multiple times simulateously.
+
+void wxClassInfo::Register()
+{
+#if wxDEBUG_LEVEL
+ // reentrance guard - see note above
+ static int entry = 0;
+#endif // wxDEBUG_LEVEL
+
+ wxHashTable *classTable;
+
+ if ( !sm_classTable )
+ {
+ // keep the hash local initially, reentrance is possible
+ classTable = new wxHashTable(wxKEY_STRING);
+ }
+ else
+ {
+ // guard againt reentrance once the global has been created
+ wxASSERT_MSG(++entry == 1, wxT("wxClassInfo::Register() reentrance"));
+ classTable = sm_classTable;
+ }
+
+ // Using IMPLEMENT_DYNAMIC_CLASS() macro twice (which may happen if you
+ // link any object module twice mistakenly, or link twice against wx shared
+ // library) will break this function because it will enter an infinite loop
+ // and eventually die with "out of memory" - as this is quite hard to
+ // detect if you're unaware of this, try to do some checks here.
+ wxASSERT_MSG( classTable->Get(m_className) == NULL,
+ wxString::Format
+ (
+ wxT("Class \"%s\" already in RTTI table - have you used IMPLEMENT_DYNAMIC_CLASS() multiple times or linked some object file twice)?"),
+ m_className
+ )
+ );
+
+ classTable->Put(m_className, (wxObject *)this);
+
+ // if we're using a local hash we need to try to make it global
+ if ( sm_classTable != classTable )
+ {
+ if ( !sm_classTable )
+ {
+ // make the hash global
+ sm_classTable = classTable;
+ }
+ else
+ {
+ // the gobal hash has already been created by a reentrant call,
+ // so delete the local hash and try again
+ delete classTable;
+ Register();
+ }
+ }
+
+#if wxDEBUG_LEVEL
+ entry = 0;
+#endif // wxDEBUG_LEVEL