SVN:(VZ)[71571] Fix bug with unloading wxPluginLibrary objects in "wrong" order.

3 views
Skip to first unread message

nor...@wxsite.net

unread,
May 26, 2012, 8:29:54 AM5/26/12
to wx-commi...@googlegroups.com
Revision
71571
Author
VZ
Date
2012-05-26 05:29:54 -0700 (Sat, 26 May 2012)

Log Message

Fix bug with unloading wxPluginLibrary objects in "wrong" order.

wxPluginLibrary objects had to be unloaded in exactly the reverse order to which they were loaded in. This was not documented and was a serious limitation for any realistic use of plugins anyhow, so fix it and allow unloading them in any order now.

Instead of keeping a pointer to the last wxClassInfo not created by this plugin, now keep a pointer to the first wxClassInfo that was created by it. This makes the code slightly more complex but this pointer, unlike the old one, remains valid even if another plugin was unloaded.

Closes 14261.

Modified Paths

Diff

Modified: wxWidgets/trunk/docs/changes.txt (71570 => 71571)


--- wxWidgets/trunk/docs/changes.txt	2012-05-26 12:29:50 UTC (rev 71570)
+++ wxWidgets/trunk/docs/changes.txt	2012-05-26 12:29:54 UTC (rev 71571)
@@ -522,6 +522,7 @@
 - Implement wxThread::SetConcurrency() for POSIX systems (Igor Korot).
 - Fix deadlock due to too many events in Unix console apps (Lukasz Michalski).
 - Added wxDir::GetNameWithSep().
+- Allow unloading wxPluginLibrary objects in any order (manyleaves).
 
 All (GUI):
 

Modified: wxWidgets/trunk/include/wx/dynload.h (71570 => 71571)


--- wxWidgets/trunk/include/wx/dynload.h	2012-05-26 12:29:50 UTC (rev 71570)
+++ wxWidgets/trunk/include/wx/dynload.h	2012-05-26 12:29:54 UTC (rev 71571)
@@ -82,8 +82,11 @@
 
 private:
 
-    const wxClassInfo    *m_before; // sm_first before loading this lib
-    const wxClassInfo    *m_after;  // ..and after.
+    // These pointers may be NULL but if they are not, then m_ourLast follows
+    // m_ourFirst in the linked list, i.e. can be found by calling GetNext() a
+    // sufficient number of times.
+    const wxClassInfo    *m_ourFirst; // first class info in this plugin
+    const wxClassInfo    *m_ourLast;  // ..and the last one
 
     size_t          m_linkcount;    // Ref count of library link calls
     size_t          m_objcount;     // ..and (pluggable) object instantiations.

Modified: wxWidgets/trunk/src/common/dynload.cpp (71570 => 71571)


--- wxWidgets/trunk/src/common/dynload.cpp	2012-05-26 12:29:50 UTC (rev 71570)
+++ wxWidgets/trunk/src/common/dynload.cpp	2012-05-26 12:29:54 UTC (rev 71571)
@@ -76,10 +76,33 @@
         : m_linkcount(1)
         , m_objcount(0)
 {
-    m_before = wxClassInfo::GetFirst();
+    const wxClassInfo* const oldFirst = wxClassInfo::GetFirst();
     Load( libname, flags );
-    m_after = wxClassInfo::GetFirst();
 
+    // It is simple to know what is the last object we registered, it's just
+    // the new head of the wxClassInfo list:
+    m_ourLast = wxClassInfo::GetFirst();
+
+    // But to find the first wxClassInfo created by this library we need to
+    // iterate until we get to the previous head as we don't have the links in
+    // the backwards direction:
+    if ( m_ourLast != oldFirst )
+    {
+        for ( const wxClassInfo* info = m_ourLast; ; info = info->GetNext() )
+        {
+            if ( info->GetNext() == oldFirst )
+            {
+                m_ourFirst = info;
+                break;
+            }
+        }
+    }
+    else // We didn't register any classes at all.
+    {
+        m_ourFirst =
+        m_ourLast = NULL;
+    }
+
     if( m_handle != 0 )
     {
         UpdateClasses();
@@ -130,7 +153,10 @@
 
 void wxPluginLibrary::UpdateClasses()
 {
-    for (const wxClassInfo *info = m_after; info != m_before; info = info->GetNext())
+    if ( !m_ourFirst )
+        return;
+
+    for ( const wxClassInfo *info = m_ourFirst; ; info = info->GetNext() )
     {
         if( info->GetClassName() )
         {
@@ -138,6 +164,9 @@
             // we can quickly find the entry they correspond to.
             (*ms_classes)[info->GetClassName()] = this;
         }
+
+        if ( info == m_ourLast )
+            break;
     }
 }
 
@@ -147,9 +176,15 @@
     if (!ms_classes)
         return;
 
-    for(const wxClassInfo *info = m_after; info != m_before; info = info->GetNext())
+    if ( !m_ourFirst )
+        return;
+
+    for ( const wxClassInfo *info = m_ourFirst; ; info = info->GetNext() )
     {
         ms_classes->erase(ms_classes->find(info->GetClassName()));
+
+        if ( info == m_ourLast )
+            break;
     }
 }
 
@@ -166,16 +201,22 @@
     wxASSERT_MSG( m_linkcount == 1,
                   wxT("RegisterModules should only be called for the first load") );
 
-    for ( const wxClassInfo *info = m_after; info != m_before; info = info->GetNext())
+    if ( m_ourFirst )
     {
-        if( info->IsKindOf(CLASSINFO(wxModule)) )
+        for ( const wxClassInfo *info = m_ourFirst; ; info = info->GetNext() )
         {
-            wxModule *m = wxDynamicCast(info->CreateObject(), wxModule);
+            if( info->IsKindOf(CLASSINFO(wxModule)) )
+            {
+                wxModule *m = wxDynamicCast(info->CreateObject(), wxModule);
 
-            wxASSERT_MSG( m, wxT("wxDynamicCast of wxModule failed") );
+                wxASSERT_MSG( m, wxT("wxDynamicCast of wxModule failed") );
 
-            m_wxmodules.push_back(m);
-            wxModule::RegisterModule(m);
+                m_wxmodules.push_back(m);
+                wxModule::RegisterModule(m);
+            }
+
+            if ( info == m_ourLast )
+                break;
         }
     }
 
Reply all
Reply to author
Forward
0 new messages