r589: Added threaded rasterizer
[ctsim.git] / src / threadraster.cpp
diff --git a/src/threadraster.cpp b/src/threadraster.cpp
new file mode 100644 (file)
index 0000000..00f89dc
--- /dev/null
@@ -0,0 +1,232 @@
+/*****************************************************************************
+** FILE IDENTIFICATION
+**
+**   Name:          threadraster.cpp
+**   Purpose:       Threaded rasterizer class
+**   Programmer:    Kevin Rosenberg
+**   Date Started:  February 2001
+**
+**  This is part of the CTSim program
+**  Copyright (C) 1983-2001 Kevin Rosenberg
+**
+**  $Id: threadraster.cpp,v 1.1 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
+**  published by the Free Software Foundation.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+******************************************************************************/
+
+#include "wx/wxprec.h"
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include "ct.h"
+#include "ctsim.h"
+#include "docs.h"
+#include "views.h"
+#include "threadraster.h"
+#include "backgroundmgr.h"
+#include "backgroundsupr.h"
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+
+
+/////////////////////////////////////////////////////////////////////
+//
+// Class RasterizerSupervisorThread -- Thread for Background Supervisor
+//
+/////////////////////////////////////////////////////////////////////
+
+RasterizerSupervisorThread::RasterizerSupervisorThread (PhantomFileView* pProjView, int iNX, int iNY, 
+   int iNSample, double dViewRatio, const char* const pszLabel)
+: m_pPhantomView(pProjView), m_iNX(iNX), m_iNY(iNY), m_iNSample(iNSample), m_dViewRatio(dViewRatio), m_strLabel(pszLabel),
+  SupervisorThread()
+{
+}
+
+wxThread::ExitCode
+RasterizerSupervisorThread::Entry()
+{
+  RasterizerSupervisor rasterSupervisor (this, m_pPhantomView, m_iNX, m_iNY, m_iNSample, m_dViewRatio, m_strLabel.c_str());
+
+  rasterSupervisor.start();
+  while (! rasterSupervisor.isDone() && ! rasterSupervisor.fail()) {
+    Sleep(100);
+    Yield();
+  }
+  if (rasterSupervisor.fail())
+  {
+    wxString msg ("Error starting Rasterizer supervisor: ");
+    msg += rasterSupervisor.getFailMessage().c_str();
+    msg += "\n";
+    wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
+    eventLog.SetString( msg );
+    wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
+  }
+
+  while (! rasterSupervisor.workersDeleted()) {
+    Sleep(50);
+    rasterSupervisor.ProcessPendingEvents();
+  }
+
+  return reinterpret_cast<wxThread::ExitCode>(0);
+}
+
+void
+RasterizerSupervisorThread::OnExit()
+{
+}
+
+
+/////////////////////////////////////////////////////////////////////
+//
+// Class RasterizerSupervisor -- A Background Supervisor
+//
+/////////////////////////////////////////////////////////////////////
+
+RasterizerSupervisor::RasterizerSupervisor (SupervisorThread* pThread, PhantomFileView* pPhantomView, int iNX, int iNY, 
+   int iNSample, double dViewRatio, const char* const pszLabel)
+    : m_pPhantomView(pPhantomView), m_pPhantomDoc(pPhantomView->GetDocument()), 
+      m_iNX(iNX), m_iNY(iNY), m_iNSample(iNSample), m_dViewRatio(dViewRatio), m_pszLabel(pszLabel), 
+      BackgroundSupervisor (pThread, pPhantomView->GetFrame(), pPhantomView->GetDocument(), "Rasterizing", iNX)
+{
+  m_vecpChildImageFiles.reserve (getNumWorkers());
+  for (unsigned int iThread = 0; iThread < getNumWorkers(); iThread++) {
+    m_vecpChildImageFiles[iThread] = new ImageFile;
+  }
+
+
+
+}
+
+RasterizerSupervisor::~RasterizerSupervisor()
+{
+  for (int i = 0; i < getNumWorkers(); i++)
+    delete m_vecpChildImageFiles[i];
+}
+
+BackgroundWorkerThread*
+RasterizerSupervisor::createWorker (int iThread, int iStartUnit, int iNumUnits)
+{
+   RasterizerWorker* pThread = new RasterizerWorker (this, iThread, iStartUnit, iNumUnits);
+   m_vecpChildImageFiles[iThread]->setArraySize (iNumUnits, m_iNY);
+   pThread->SetParameters (m_pPhantomView, m_vecpChildImageFiles[iThread], m_iNX, m_iNY, m_iNSample, m_dViewRatio);
+
+   return pThread;
+}
+
+void
+RasterizerSupervisor::onDone()
+{
+  wxCriticalSection doneSection;
+  wxCriticalSectionLocker critsect (doneSection);
+
+  ImageFileDocument* pImageDoc = theApp->newImageDoc();
+  if (! pImageDoc) {
+    sys_error (ERR_SEVERE, "Unable to create image file");
+    return;
+  }
+    
+  ImageFile* pImageFile = getImageFile();
+  pImageDoc->setImageFile (pImageFile);
+  if (theApp->getAskDeleteNewDocs())
+    pImageDoc->Modify (true);
+  pImageDoc->UpdateAllViews (NULL);
+  if (ImageFileView* imageView = pImageDoc->getView()) {
+    imageView->OnUpdate (imageView, NULL);
+    imageView->getFrame()->SetFocus();
+    imageView->getFrame()->Show(true);
+  }
+  *theApp->getLog() << m_pszLabel << "\n";
+  pImageFile->labelAdd (m_pszLabel, getTimerEnd());
+
+  setDone();
+}
+
+
+ImageFile*
+RasterizerSupervisor::getImageFile()
+{
+  ImageFile* pImageFile = new ImageFile (m_iNX, m_iNY);
+
+  size_t iColSize = sizeof(ImageFileValue) * m_iNY;
+
+  ImageFileArray globalArray = pImageFile->getArray();
+  int iGlobalCol = 0;
+  for (int iw = 0; iw < getNumWorkers(); iw++) {
+    ImageFileArray childArray = m_vecpChildImageFiles[iw]->getArray();
+    for (int iCol = 0; iCol < m_vecpChildImageFiles[iw]->nx(); iCol++) {
+      memcpy (globalArray[iGlobalCol++], childArray[iCol], iColSize);
+    }
+  }
+  return (pImageFile);
+}
+
+
+/////////////////////////////////////////////////////////////////////
+//
+// Class RasterizerWorker -- A worker thread
+//
+/////////////////////////////////////////////////////////////////////
+
+void
+RasterizerWorker::SetParameters (PhantomFileView* pPhantomView, ImageFile* pImageFile, int iNX, int iNY, int iNSample, double dViewRatio)
+{
+  m_pImageFile = pImageFile;
+  m_iNX = iNX;
+  m_iNY = iNY;
+  m_pPhantomView = pPhantomView;
+  m_iNSample = iNSample;
+  m_dViewRatio = dViewRatio;
+}
+
+wxThread::ExitCode
+RasterizerWorker::Entry ()
+{
+  const Phantom& rPhantom = m_pPhantomView->GetDocument()->getPhantom();
+  wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_UNIT_TICK);
+  for (int iUnit = 0; iUnit < m_iNumUnits; iUnit++) {
+    if (TestDestroy()) {
+#ifdef DEBUG
+      if (theApp->getVerboseLogging()) {
+        wxString msg;
+        msg.Printf("Worker thread: Received destroy message at work unit #%d\n", iUnit);  
+        wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
+        event.SetString( msg );
+        wxPostEvent( theApp->getMainFrame(), event ); 
+      }
+#endif
+      break;
+    }
+    rPhantom.convertToImagefile (*m_pImageFile, m_iNX, m_dViewRatio, m_iNSample, Trace::TRACE_NONE, 
+      iUnit + m_iStartUnit, 1, iUnit);
+    wxPostEvent (m_pSupervisor, eventProgress);
+  }
+  wxCommandEvent eventDone (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_DONE);
+  eventDone.SetInt (m_iThread); // Send back thread# that has finished
+  wxPostEvent (m_pSupervisor, eventDone);
+
+  while (! TestDestroy())
+    Sleep(100);
+
+  return reinterpret_cast<wxThread::ExitCode>(0);
+}
+
+void
+RasterizerWorker::OnExit ()
+{
+}