r589: Added threaded rasterizer
[ctsim.git] / src / backgroundsupr.cpp
index 2b8c0491cd2f034111f014d8a77d95701c750aa5..3b2f36245f154f46802f3883da355b809ca4f378 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (C) 1983-2001 Kevin Rosenberg
 **
-**  $Id: backgroundsupr.cpp,v 1.2 2001/02/25 07:36:26 kevin Exp $
+**  $Id: backgroundsupr.cpp,v 1.9 2001/02/27 03:59:30 kevin Exp $
 **
 **  This program is free software; you can redistribute it and/or modify
 **  it under the terms of the GNU General Public License (version 2) as
@@ -67,14 +67,14 @@ BackgroundSupervisor::cancelSupervisor (BackgroundSupervisor* pSupervisor)
 }
 
 
-BackgroundSupervisor::BackgroundSupervisor (wxFrame* pParentFrame, wxDocument* pDocument, const char* const pszProcessTitle, int iTotalUnits)
-    : m_pParentFrame(pParentFrame), m_pDocument(pDocument), m_pDialogProgress(NULL), m_strProcessTitle(pszProcessTitle), 
+BackgroundSupervisor::BackgroundSupervisor (SupervisorThread* pMyThread, wxFrame* pParentFrame, wxDocument* pDocument, const char* const pszProcessTitle, int iTotalUnits)
+    : m_pMyThread(pMyThread), m_pParentFrame(pParentFrame), m_pDocument(pDocument), m_pDialogProgress(NULL), m_strProcessTitle(pszProcessTitle), 
     m_iTotalUnits(iTotalUnits), m_iNumThreads(0), m_bDone(false), m_bFail(false), m_bCancelled(false), 
-    m_pTimer(NULL), m_bBackgroundTaskAdded(false),
+    m_pTimer(NULL), m_bBackgroundTaskAdded(false), m_bWorkersDeleted(false),
     wxEvtHandler()
 {
   m_iNumThreads = theApp->getNumberCPU();
-  //  ++m_iNumThreads;
+    ++m_iNumThreads;
 
   m_vecpThreads.reserve (m_iNumThreads);
   for (int iThread = 0; iThread < m_iNumThreads; iThread++)
@@ -92,7 +92,7 @@ BackgroundSupervisor::~BackgroundSupervisor()
   }
 
   while (m_bBackgroundTaskAdded) {
-    Sleep(50);
+    m_pMyThread->Sleep(50);
     ProcessPendingEvents();
   }
 
@@ -101,29 +101,32 @@ BackgroundSupervisor::~BackgroundSupervisor()
 }
 
 void
-BackgroundSupervisor::deleteAnyWorkers()
+BackgroundSupervisor::deleteWorkers()
 {
-  m_critsectThreadContainer.Enter();  
+  wxCriticalSectionLocker lock (m_critsectThreads);
+  if (m_bWorkersDeleted)
+    return;
+
   for (int i = 0; i < m_iNumThreads; i++) 
     if (m_vecpThreads[i]) {
       m_vecpThreads[i]->Delete(); // sends Destroy message to workers
   }
-  m_critsectThreadContainer.Leave();
 
   while (m_iRunning > 0) {
-    Sleep(50);
+    m_pMyThread->Sleep(50);
     ProcessPendingEvents();
   }
+  m_iRunning = 0;
+  m_bWorkersDeleted = true;
 }
 
-
 bool
 BackgroundSupervisor::start()
 {
   int iBaseUnits = m_iTotalUnits / m_iNumThreads;
   int iExtraUnits = m_iTotalUnits % m_iNumThreads;
+  int iStartUnit = 0;
   for (int iThread = 0; iThread < m_iNumThreads; iThread++) {
-    int iStartUnit = iThread * iBaseUnits;
     int iNumUnits = iBaseUnits;
     if (iThread < iExtraUnits)
       ++iNumUnits;
@@ -138,7 +141,8 @@ BackgroundSupervisor::start()
       m_strFailMessage = "Thread creation failed [BackgroundSupervisor]";
       break;
     }
-    m_vecpThreads[iThread]->SetPriority (40);
+   m_vecpThreads[iThread]->SetPriority (40);
+   iStartUnit += iNumUnits;
   }
   if (m_bFail)
     return false;
@@ -174,8 +178,8 @@ void
 BackgroundSupervisor::OnCancel(wxCommandEvent& event)
 {
   m_bCancelled = true;
-  deleteAnyWorkers();
   m_bDone = true;
+  deleteWorkers();
 }
 
 void
@@ -212,9 +216,6 @@ BackgroundSupervisor::OnWorkerDone (wxCommandEvent& event)
 {
   m_iRunning--;
   wxASSERT (m_iRunning >= 0);
-  m_critsectThreadContainer.Enter();
-  m_vecpThreads[event.GetInt()] = NULL;
-  m_critsectThreadContainer.Leave();
 
 #ifdef DEBUG
   if (theApp->getVerboseLogging()) {
@@ -225,21 +226,21 @@ BackgroundSupervisor::OnWorkerDone (wxCommandEvent& event)
     wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
   }
 #endif
-  if (m_iRunning <= 0 && ! m_bCancelled)
+  if (m_iRunning <= 0 && ! m_bCancelled) {
+    deleteWorkers();
     onDone();
+  }
 }
 
 void
 BackgroundSupervisor::OnWorkerFail (wxCommandEvent& event)
 {
   m_iRunning--;
-  m_critsectThreadContainer.Enter();
-  m_vecpThreads[event.GetInt()] = NULL;
-  m_critsectThreadContainer.Leave();
   wxCommandEvent eventLog( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
   eventLog.SetString( event.GetString() );
   wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
 
-  onDone();
+  wxCommandEvent dummy;
+  OnCancel(dummy);
 }