Commit c8e2cec3 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[CHANGE] - switched to WFlag in WThreadedRunner

[CHANGE] - now using ONE composite viewer for all WGEViewer
parent c9181c42
......@@ -24,9 +24,12 @@
#include <iostream>
#include "WConditionOneShot.h"
#include "WThreadedRunner.h"
WThreadedRunner::WThreadedRunner()
WThreadedRunner::WThreadedRunner():
m_shutdownFlag( new WConditionOneShot, false )
{
// initialize members
m_FinishRequested = false;
......@@ -53,15 +56,15 @@ void WThreadedRunner::wait( bool requestFinish )
notifyStop();
// then signal it
m_FinishRequested = requestFinish;
m_stopCondition.notify_all();
m_FinishRequested = true;
m_shutdownFlag( true );
}
m_Thread->join();
}
void WThreadedRunner::waitForStop()
{
m_stopCondition.wait( m_stopConditionMutex );
m_shutdownFlag.wait();
}
void WThreadedRunner::threadMain()
......
......@@ -28,6 +28,8 @@
#include <boost/thread.hpp>
#include <boost/thread/thread.hpp>
#include "WFlag.hpp"
/**
* Base class for all classes needing to be executed in a separate thread.
*/
......@@ -76,7 +78,7 @@ protected:
boost::thread* m_Thread;
/**
* True if thread should end execution.
* True if thread should end execution. NOTE: do not use this. Use m_shutdownFlag instead.
*/
bool m_FinishRequested;
......@@ -97,15 +99,10 @@ protected:
*/
void waitForStop();
/**
* Condition mutex used by m_stopCondition.
*/
boost::mutex m_stopConditionMutex;
/**
* Condition getting fired whenever the thread should quit. This is useful for waiting for stop requests.
*/
boost::condition_variable_any m_stopCondition;
WBoolFlag m_shutdownFlag;
private:
};
......
......@@ -39,12 +39,24 @@ class Callable
{
public:
/**
* Flag set true when the thread starts.
*/
bool flag;
/**
* The condition to use.
*/
WConditionOneShot* c;
/**
* The thread.
*/
void threadMain()
{
flag = true;
// let the test's thread reach its "wait" call first
boost::this_thread::sleep( boost::posix_time::seconds( 1 ) );
c->notify();
};
......@@ -62,7 +74,7 @@ public:
*/
void testInstantiation( void )
{
WConditionOneShot* c;
WConditionOneShot* c = 0;
TS_ASSERT_THROWS_NOTHING( c = new WConditionOneShot() );
TS_ASSERT_THROWS_NOTHING( delete c );
......
......@@ -39,12 +39,24 @@ class Callable
{
public:
/**
* Flag set to true when thread starts
*/
bool flag;
/**
* The condition to be used for signalling.
*/
WCondition* c;
/**
* Thread main method.
*/
void threadMain()
{
flag = true;
// let the test's thread reach its "wait" call first
boost::this_thread::sleep( boost::posix_time::seconds( 1 ) );
c->notify();
};
......@@ -62,7 +74,7 @@ public:
*/
void testInstantiation( void )
{
WCondition* c;
WCondition* c = 0;
TS_ASSERT_THROWS_NOTHING( c = new WCondition() );
TS_ASSERT_THROWS_NOTHING( delete c );
......
......@@ -39,17 +39,32 @@
class Callable
{
public:
/**
* The flag to be tested
*/
WFlag<bool>* flag;
/**
* True if the thread finishes.
*/
bool finished;
/**
* Constructor. To init the Flag.
*/
Callable()
{
finished = false;
flag = new WFlag< bool >( new WConditionOneShot(), false );
}
/**
* Thread function.
*/
void threadMain()
{
// just wait
flag->wait();
finished = true;
};
......@@ -67,7 +82,7 @@ public:
*/
void testInstantiation( void )
{
WFlag< bool >* flag;
WFlag< bool >* flag = 0;
TS_ASSERT_THROWS_NOTHING( flag = new WFlag< bool >( new WConditionOneShot(), false ) );
TS_ASSERT_THROWS_NOTHING( delete flag );
......
......@@ -39,30 +39,17 @@
#include <osgDB/ReadFile>
#include "exceptions/WGEInitFailed.h"
#include "WPickHandler.h"
#include "../kernel/WKernel.h"
#include "WGEViewer.h"
WGEViewer::WGEViewer( osg::ref_ptr<WindowData> wdata, int x, int y, int width, int height, WGECamera::ProjectionMode projectionMode ):
WGEGraphicsWindow( wdata, x, y, width, height )
WGEGraphicsWindow( wdata, x, y, width, height ),
boost::enable_shared_from_this< WGEViewer >()
{
try
{
// initialize OSG render window
m_Viewer = osg::ref_ptr<osgViewer::CompositeViewer>( new osgViewer::CompositeViewer() );
// ThreadingModel: enum with the following possibilities
//
// SingleThreadet
// CullDrawThreadPerContext
// ThreadPerContext
// DrawThreadPerContext
// CullThreadPerCameraDrawThreadPerContext
// ThreadPerCamera
// AutomaticSelection
m_Viewer->setThreadingModel( osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext );
m_View = osg::ref_ptr<osgViewer::Viewer>( new osgViewer::Viewer() );
m_View->getCamera()->setGraphicsContext( m_GraphicsContext );
......@@ -95,11 +82,6 @@ WGEViewer::WGEViewer( osg::ref_ptr<WindowData> wdata, int x, int y, int width, i
osg::ref_ptr<osgText::Text> updateText = new osgText::Text;
m_View->addEventHandler( new WPickHandler( updateText.get() ) );
// finally add view
// there is the possibility to use ONE single composite viewer instance for every view, but
// currently this possibility is not used.
m_Viewer->addView( m_View.get() );
}
catch( ... )
{
......@@ -113,9 +95,9 @@ WGEViewer::~WGEViewer()
close();
}
osg::ref_ptr<osgViewer::CompositeViewer> WGEViewer::getViewer()
osg::ref_ptr<osgViewer::Viewer> WGEViewer::getViewer()
{
return m_Viewer;
return m_View;
}
void WGEViewer::setCameraManipulator( osg::ref_ptr<osgGA::MatrixManipulator> manipulator )
......@@ -150,11 +132,6 @@ osg::ref_ptr<osg::Node> WGEViewer::getNode()
return m_View->getSceneData();
}
void WGEViewer::paint()
{
m_Viewer->frame();
}
void WGEViewer::resize( int width, int height )
{
WGEGraphicsWindow::resize( width, height );
......@@ -165,15 +142,7 @@ void WGEViewer::resize( int width, int height )
void WGEViewer::close()
{
m_Viewer->setDone( true );
m_Viewer->stopThreading();
// forward close event
WGEGraphicsWindow::close();
}
void WGEViewer::threadMain()
{
m_Viewer->startThreading();
m_Viewer->run();
}
......@@ -50,7 +50,7 @@
* \ingroup ge
*/
class WGEViewer: public WGEGraphicsWindow,
public WThreadedRunner
public boost::enable_shared_from_this< WGEViewer >
{
public:
/**
......@@ -72,11 +72,6 @@ public:
*/
virtual ~WGEViewer();
/**
* Paints this view to the window specified in constructor.
*/
void paint();
/**
* Updates size information. Also updates camera.
*
......@@ -95,7 +90,7 @@ public:
*
* \return the OSG Viewer instance.
*/
osg::ref_ptr<osgViewer::CompositeViewer> getViewer();
osg::ref_ptr<osgViewer::Viewer> getViewer();
/**
* Sets the camera manipulator to use.
......@@ -140,20 +135,11 @@ public:
osg::ref_ptr<osg::Node> getNode();
protected:
/**
* Handler for repainting and event handling. Gets executed in separate thread.
*/
virtual void threadMain();
/**
* OpenSceneGraph viewer.
*/
osg::ref_ptr<osgViewer::CompositeViewer> m_Viewer;
/**
* The OpenSceneGraph view used in this (Composite)Viewer.
*/
osg::ref_ptr<osgViewer::View> m_View;
osg::ref_ptr< osgViewer::Viewer > m_View;
private:
};
......
......@@ -30,13 +30,18 @@
#include <boost/shared_ptr.hpp>
#include <boost/thread/locks.hpp>
#include <osgViewer/Viewer>
#include <osgViewer/CompositeViewer>
#include <osgViewer/View>
#include "exceptions/WGEInitFailed.h"
#include "../common/WLogger.h"
#include "WGraphicsEngine.h"
#include "WGEViewer.h"
WGraphicsEngine::WGraphicsEngine()
WGraphicsEngine::WGraphicsEngine():
WThreadedRunner()
{
WLogger::getLogger()->addLogMessage( "Initializing Graphics Engine", "GE", LL_DEBUG );
......@@ -44,6 +49,20 @@ WGraphicsEngine::WGraphicsEngine()
m_rootNode = new WGEScene();
m_shaderPath = "";
// initialize OSG render window
m_Viewer = osg::ref_ptr<osgViewer::CompositeViewer>( new osgViewer::CompositeViewer() );
// ThreadingModel: enum with the following possibilities
//
// SingleThreadet
// CullDrawThreadPerContext
// ThreadPerContext
// DrawThreadPerContext
// CullThreadPerCameraDrawThreadPerContext
// ThreadPerCamera
// AutomaticSelection
m_Viewer->setThreadingModel( osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext );
}
WGraphicsEngine::~WGraphicsEngine()
......@@ -70,18 +89,38 @@ void WGraphicsEngine::setShaderPath( std::string path )
boost::shared_ptr<WGEViewer> WGraphicsEngine::createViewer(
osg::ref_ptr<WindowData> wdata, int x, int y, int width, int height, WGECamera::ProjectionMode projectionMode )
{
// init the composite viewer if not already done
if ( m_Viewer == osg::ref_ptr< osgViewer::CompositeViewer >() )
{
}
boost::shared_ptr<WGEViewer> viewer = boost::shared_ptr<WGEViewer>( new WGEViewer( wdata, x, y, width, height, projectionMode ) );
viewer->setScene( getScene() );
// start rendering
viewer->run();
// finally add view
m_Viewer->addView( viewer->getViewer().get() );
// store it in viewer list
// XXX is this list needed? If yes someone has to care about a deregisterViewer function
// XXX is this list needed? If yes, someone has to care about a deregisterViewer function
// boost::mutex::scoped_lock lock(m_ViewerLock);
// m_Viewer.push_back( viewer );
//m_Viewers.push_back( viewer );
return viewer;
}
void WGraphicsEngine::threadMain()
{
WLogger::getLogger()->addLogMessage( "Starting Graphics Engine", "GE", LL_DEBUG );
m_Viewer->startThreading();
m_Viewer->run();
m_Viewer->stopThreading();
}
void WGraphicsEngine::notifyStop()
{
WLogger::getLogger()->addLogMessage( "Stopping Graphics Engine", "GE", LL_DEBUG );
m_Viewer->setDone( true );
}
......@@ -34,8 +34,10 @@
#include <boost/thread/mutex.hpp>
#include <osg/Camera>
#include <osgViewer/Viewer>
#include <osg/Texture3D>
#include <osgViewer/Viewer>
#include <osgViewer/CompositeViewer>
#include <osgViewer/View>
#include "WGEScene.h"
#include "WGEGraphicsWindow.h"
......@@ -48,7 +50,7 @@
* engine.
* \ingroup ge
*/
class WGraphicsEngine
class WGraphicsEngine: public WThreadedRunner
{
public:
......@@ -100,6 +102,16 @@ public:
protected:
/**
* Handler for repainting and event handling. Gets executed in separate thread.
*/
virtual void threadMain();
/**
* Gets called when the thread should be stopped.
*/
virtual void notifyStop();
/**
* OpenSceneGraph root node.
*/
......@@ -108,7 +120,7 @@ protected:
/**
* All registered viewer.
*/
std::list<boost::shared_ptr<WGEViewer> > m_Viewer;
std::list<boost::shared_ptr<WGEViewer> > m_Viewers;
/**
* Mutex used to lock the list of viewers.
......@@ -120,6 +132,11 @@ protected:
*/
std::string m_shaderPath;
/**
* OpenSceneGraph composite viewer. Contains all created osg::Viewer.
*/
osg::ref_ptr<osgViewer::CompositeViewer> m_Viewer;
private:
};
......
......@@ -26,6 +26,8 @@
#include <string>
#include <vector>
#include <boost/thread.hpp>
#include <QtGui/QApplication>
#include <QtGui/QMainWindow>
#include <QtGui/QDockWidget>
......@@ -75,21 +77,21 @@ void WMainWindow::setupGUI()
setCentralWidget( m_mainGLWidget.get() );
// initially 3 views
//m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "axial", 160, "axialPos" ) );
//m_navAxial->getGLWidget()->initialize();
//addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get() );
m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "axial", 160, "axialPos" ) );
m_navAxial->getGLWidget()->initialize();
addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get() );
//m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "coronal", 200, "coronalPos" ) );
//m_navCoronal->getGLWidget()->initialize();
//addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get() );
m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "coronal", 200, "coronalPos" ) );
m_navCoronal->getGLWidget()->initialize();
addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get() );
//m_navSagittal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "sagittal", 160, "sagittalPos" ) );
//m_navSagittal->getGLWidget()->initialize();
//addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get() );
m_navSagittal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "sagittal", 160, "sagittalPos" ) );
m_navSagittal->getGLWidget()->initialize();
addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get() );
//connect( m_navAxial.get(), SIGNAL( navSliderValueChanged( QString, int ) ), &m_propertyManager, SLOT( slotIntChanged( QString, int ) ) );
//connect( m_navCoronal.get(), SIGNAL( navSliderValueChanged( QString, int ) ), &m_propertyManager, SLOT( slotIntChanged( QString, int ) ) );
//connect( m_navSagittal.get(), SIGNAL( navSliderValueChanged( QString, int ) ), &m_propertyManager, SLOT( slotIntChanged( QString, int ) ) );
connect( m_navAxial.get(), SIGNAL( navSliderValueChanged( QString, int ) ), &m_propertyManager, SLOT( slotIntChanged( QString, int ) ) );
connect( m_navCoronal.get(), SIGNAL( navSliderValueChanged( QString, int ) ), &m_propertyManager, SLOT( slotIntChanged( QString, int ) ) );
connect( m_navSagittal.get(), SIGNAL( navSliderValueChanged( QString, int ) ), &m_propertyManager, SLOT( slotIntChanged( QString, int ) ) );
m_datasetBrowser = new WQtDatasetBrowser();
addDockWidget( Qt::RightDockWidgetArea, m_datasetBrowser );
......@@ -216,22 +218,15 @@ void WMainWindow::closeEvent( QCloseEvent* e )
// handle close event
if ( reallyClose )
{
// signal everybuddy to shut down properly.
WKernel::getRunningKernel()->stop();
// signal everybody to shut down properly.
WKernel::getRunningKernel()->finalize();
// now nobody acesses the osg anymore
// clean up gl widgets
m_mainGLWidget->close();
m_mainGLWidget.reset();
// m_navAxial->close();
//m_navAxial.reset();
//m_navCoronal->close();
//m_navCoronal.reset();
//m_navSagittal->close();
//m_navSagittal.reset();
m_navAxial->close();
m_navCoronal->close();
m_navSagittal->close();
// finally close
e->accept();
......
......@@ -72,8 +72,13 @@ int WQt4Gui::run()
m_isInitialized( true );
// run
// NOTE: kernel shutdown is implemented in WMainWindow
return appl.exec();
int qtRetCode = appl.exec();
// signal everybody to shut down properly.
WKernel::getRunningKernel()->wait( true );
WKernel::getRunningKernel()->getGraphicsEngine()->wait( true );
return qtRetCode;
}
void WQt4Gui::addDatasetToBrowser( boost::shared_ptr< WModule > module, int subjectId )
......
......@@ -143,16 +143,16 @@ void WQtGLWidget::paintEvent( QPaintEvent* /*event*/ )
void WQtGLWidget::destroyEvent( bool /*destroyWindow*/, bool /*destroySubWindows*/ )
{
// forward events
m_Viewer->close();
//m_Viewer->close();
}
void WQtGLWidget::closeEvent( QCloseEvent* event )
{
event->accept();
// forward events
m_Viewer->close();
event->accept();
}
......
......@@ -28,6 +28,7 @@
#include <QtGui/QDockWidget>
#include <QtGui/QSlider>
#include <QtGui/QVBoxLayout>
#include <QtGui/QKeyEvent>
#include "WQtNavGLWidget.h"
......@@ -62,6 +63,14 @@ WQtNavGLWidget::~WQtNavGLWidget()
{
}
void WQtNavGLWidget::closeEvent( QCloseEvent* event )
{
// forward events
m_glWidget->close();
event->accept();
}
void WQtNavGLWidget::setSliderTitle( std::string title )
{
m_sliderTitle = QString( title.c_str() );
......
......@@ -59,6 +59,14 @@ public:
void setSliderTitle( std::string title );
protected:
/**
* Event handler for close events.
*
* \param event the event description.
*/
virtual void closeEvent( QCloseEvent* event );
private:
QString m_sliderTitle;
......
......@@ -50,8 +50,7 @@
WKernel* kernel = NULL;
WKernel::WKernel( boost::shared_ptr< WGraphicsEngine > ge, boost::shared_ptr< WGUI > gui ):
WThreadedRunner(),
m_FinishRequested( new WConditionOneShot, false )
WThreadedRunner()
{
WLogger::getLogger()->addLogMessage( "Initializing Kernel", "Kernel", LL_DEBUG );
......@@ -114,13 +113,10 @@ boost::shared_ptr< WGUI > WKernel::getGui() const
return m_gui;
}
void WKernel::stop()
void WKernel::finalize()
{
WLogger::getLogger()->addLogMessage( "Stopping Kernel", "Kernel", LL_DEBUG );
// stop everybody
m_FinishRequested( true );
// NOTE: stopping a container erases all modules inside.
getRootContainer()->stop();
}
......@@ -132,12 +128,16 @@ void WKernel::threadMain()
// wait for GUI to be initialized properly