Replaced use of while(isRunning()) { YieldCurrentThread(); } style loops with use of join() to avoid false positives being reported by valgrind when using the helgrind tool for thread debugging.

git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14460 16af8721-9629-0410-8352-f15c8da7e697
This commit is contained in:
Robert Osfield
2014-11-04 10:46:59 +00:00
parent 997ee30039
commit 28a676e105
17 changed files with 195 additions and 233 deletions

View File

@@ -59,10 +59,10 @@ class ViewerFrameThread : public OpenThreads::Thread
~ViewerFrameThread()
{
cancel();
while(isRunning())
if (isRunning())
{
OpenThreads::Thread::YieldCurrentThread();
cancel();
join();
}
}

View File

@@ -37,33 +37,37 @@ public:
_done(false)
{
}
virtual ~ReadThread()
{
_done = true;
while(isRunning()) OpenThreads::Thread::YieldCurrentThread();
if (isRunning())
{
cancel();
join();
}
}
void addFileName(const std::string& filename)
{
_fileNames.push_back(filename);
}
void setStartBarrier(RefBarrier* barrier) { _startBarrier = barrier; }
void setEndBarrier(RefBarrier* barrier) { _endBarrier = barrier; }
virtual void run()
{
if (_startBarrier.valid())
if (_startBarrier.valid())
{
#if VERBOSE
#if VERBOSE
std::cout<<"Waiting on start block "<<this<<std::endl;
#endif
_startBarrier->block();
}
#if VERBOSE
#if VERBOSE
std::cout<<"Starting "<<this<<std::endl;
#endif
@@ -75,31 +79,31 @@ public:
std::string filename = _fileNames.front();
_fileNames.erase(_fileNames.begin());
#if VERBOSE
#if VERBOSE
std::cout<<"Reading "<<filename;
#endif
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(filename);
#if VERBOSE
#if VERBOSE
if (node.valid()) std::cout<<".. OK"<<std::endl;
else std::cout<<".. FAILED"<<std::endl;
#endif
}
} while (!testCancel() && !_fileNames.empty() && !_done);
if (_endBarrier.valid())
if (_endBarrier.valid())
{
#if VERBOSE
#if VERBOSE
std::cout<<"Waiting on end block "<<this<<std::endl;
#endif
_endBarrier->block();
}
#if VERBOSE
#if VERBOSE
std::cout<<"Completed"<<this<<std::endl;
#endif
}
typedef std::list<std::string> FileNames;
FileNames _fileNames;
bool _done;
@@ -151,7 +155,7 @@ public:
protected:
virtual ~SerializerReadFileCallback() {}
OpenThreads::Mutex _mutex;
};
@@ -159,13 +163,13 @@ protected:
void runMultiThreadReadTests(int numThreads, osg::ArgumentParser& arguments)
{
#if VERBOSE
#if VERBOSE
osg::notify(osg::NOTICE)<<"runMultiThreadReadTests() -- running"<<std::endl;
#endif
if (arguments.read("preload"))
{
{
osgDB::Registry::instance()->loadLibrary(osgDB::Registry::instance()->createLibraryNameForExtension("osg"));
osgDB::Registry::instance()->loadLibrary(osgDB::Registry::instance()->createLibraryNameForExtension("rgb"));
osgDB::Registry::instance()->loadLibrary(osgDB::Registry::instance()->createLibraryNameForExtension("jpeg"));
@@ -195,17 +199,17 @@ void runMultiThreadReadTests(int numThreads, osg::ArgumentParser& arguments)
readThread->addFileName("cessna.osgt");
readThread->addFileName("glider.osgt");
readThread->addFileName("town.ive");
readThreads.push_back(readThread.get());
readThread->start();
}
startBarrier->block();
endBarrier->block();
#if VERBOSE
#if VERBOSE
osg::notify(osg::NOTICE)<<"runMultiThreadReadTests() -- completed."<<std::endl;
#endif
}

View File

@@ -46,8 +46,8 @@ void testFrustum(double left,double right,double bottom,double top,double zNear,
double c_bottom=0;
double c_zNear=0;
double c_zFar=0;
std::cout << "testFrustum"<<f.getFrustum(c_left,c_right,c_bottom,c_top,c_zNear,c_zFar)<<std::endl;
std::cout << " left = "<<left<<" compute "<<c_left<<std::endl;
std::cout << " right = "<<right<<" compute "<<c_right<<std::endl;
@@ -57,7 +57,7 @@ void testFrustum(double left,double right,double bottom,double top,double zNear,
std::cout << " zNear = "<<zNear<<" compute "<<c_zNear<<std::endl;
std::cout << " zFar = "<<zFar<<" compute "<<c_zFar<<std::endl;
std::cout << std::endl;
}
@@ -82,7 +82,7 @@ void testOrtho(double left,double right,double bottom,double top,double zNear,do
std::cout << " zNear = "<<zNear<<" compute "<<c_zNear<<std::endl;
std::cout << " zFar = "<<zFar<<" compute "<<c_zFar<<std::endl;
std::cout << std::endl;
}
@@ -102,7 +102,7 @@ void testPerspective(double fovy,double aspect,double zNear,double zFar)
std::cout << " zNear = "<<zNear<<" compute "<<c_zNear<<std::endl;
std::cout << " zFar = "<<zFar<<" compute "<<c_zFar<<std::endl;
std::cout << std::endl;
}
@@ -110,17 +110,17 @@ void testLookAt(const osg::Vec3& eye,const osg::Vec3& center,const osg::Vec3& up
{
osg::Matrix mv;
mv.makeLookAt(eye,center,up);
osg::Vec3 c_eye,c_center,c_up;
mv.getLookAt(c_eye,c_center,c_up);
std::cout << "testLookAt"<<std::endl;
std::cout << " eye "<<eye<< " compute "<<c_eye<<std::endl;
std::cout << " center "<<center<< " compute "<<c_center<<std::endl;
std::cout << " up "<<up<< " compute "<<c_up<<std::endl;
std::cout << std::endl;
}
@@ -170,15 +170,15 @@ void sizeOfTest()
/// Exercise the Matrix.getRotate function.
/// Compare the output of:
/// q1 * q2
/// q1 * q2
/// versus
/// (mat(q1)*mat(q2)*scale).getRotate()
/// for a range of rotations
void testGetQuatFromMatrix(const osg::Vec3d& scale)
void testGetQuatFromMatrix(const osg::Vec3d& scale)
{
// Options
// acceptable error range
double eps=1e-6;
@@ -187,7 +187,7 @@ void testGetQuatFromMatrix(const osg::Vec3d& scale)
// Not sure if 0's or negative values are acceptable
osg::Matrixd scalemat;
scalemat.makeScale(scale);
// range of rotations
#if 1
// wide range
@@ -290,7 +290,7 @@ void testGetQuatFromMatrix(const osg::Vec3d& scale)
if(out_quat1.w()<0) out_quat1 = out_quat1 * -1.0;
if(out_quat2.w()<0) out_quat2 = out_quat2 * -1.0;
// if the output quat length is not one
// if the output quat length is not one
// or if the components do not match,
// something is amiss
@@ -346,10 +346,10 @@ void testQuatRotate(const osg::Vec3d& from, const osg::Vec3d& to)
{
osg::Quat q_nicolas;
q_nicolas.makeRotate(from,to);
osg::Quat q_original;
q_original.makeRotate_original(from,to);
std::cout<<"osg::Quat::makeRotate("<<from<<", "<<to<<")"<<std::endl;
std::cout<<" q_nicolas = "<<q_nicolas<<std::endl;
std::cout<<" q_original = "<<q_original<<std::endl;
@@ -370,16 +370,16 @@ void testQuat(const osg::Vec3d& quat_scale)
osg::Matrix m1 = osg::Matrix::rotate(q1);
osg::Matrix m2 = osg::Matrix::rotate(q2);
osg::Matrix m1_2 = m1*m2;
osg::Matrix m2_1 = m2*m1;
osg::Quat qm1_2;
qm1_2.set(m1_2);
osg::Quat qm2_1;
qm2_1.set(m2_1);
std::cout<<"q1*q2 = "<<q1_2<<std::endl;
std::cout<<"q2*q1 = "<<q2_1<<std::endl;
std::cout<<"m1*m2 = "<<qm1_2<<std::endl;
@@ -406,10 +406,10 @@ void testQuat(const osg::Vec3d& quat_scale)
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
1.0, 1.0, 1.0, 1.0);
osg::Quat quat;
matrix.get(quat);
osg::notify(osg::NOTICE)<<"Matrix = "<<matrix<<"rotation = "<<quat<<", expected quat = (0,0,0,1)"<<std::endl;
}
@@ -475,9 +475,10 @@ public:
~NotifyThread()
{
_done = true;
while(isRunning())
if (isRunning())
{
OpenThreads::Thread::YieldCurrentThread();
cancel();
join();
}
}
@@ -487,7 +488,7 @@ public:
unsigned int count=0;
while(!_done)
while(!_done)
{
++count;
#if 1
@@ -503,7 +504,7 @@ public:
bool _done;
osg::NotifySeverity _level;
std::string _message;
};
void testThreadInitAndExit()
@@ -514,10 +515,10 @@ void testThreadInitAndExit()
MyThread thread;
thread.startThread();
}
// add a sleep to allow the thread start to fall over it its going to.
OpenThreads::Thread::microSleep(500000);
std::cout<<"pass thread start and delete test"<<std::endl<<std::endl;
@@ -572,7 +573,7 @@ int main( int argc, char** argv )
arguments.getApplicationUsage()->addCommandLineOption("matrix","Display qualified tests.");
arguments.getApplicationUsage()->addCommandLineOption("performance","Display qualified tests.");
arguments.getApplicationUsage()->addCommandLineOption("read-threads <numthreads>","Run multi-thread reading test.");
if (arguments.argc()<=1)
{
@@ -580,35 +581,35 @@ int main( int argc, char** argv )
return 1;
}
bool printQualifiedTest = false;
while (arguments.read("qt")) printQualifiedTest = true;
bool printQualifiedTest = false;
while (arguments.read("qt")) printQualifiedTest = true;
bool printMatrixTest = false;
while (arguments.read("matrix")) printMatrixTest = true;
bool printMatrixTest = false;
while (arguments.read("matrix")) printMatrixTest = true;
bool printSizeOfTest = false;
bool printSizeOfTest = false;
while (arguments.read("sizeof")) printSizeOfTest = true;
bool printFileNameUtilsTests = false;
while (arguments.read("filenames")) printFileNameUtilsTests = true;
bool printQuatTest = false;
bool printQuatTest = false;
while (arguments.read("quat")) printQuatTest = true;
int numReadThreads = 0;
int numReadThreads = 0;
while (arguments.read("read-threads", numReadThreads)) {}
bool printPolytopeTest = false;
bool printPolytopeTest = false;
while (arguments.read("polytope")) printPolytopeTest = true;
bool doTestThreadInitAndExit = false;
while (arguments.read("thread")) doTestThreadInitAndExit = true;
osg::Vec3d quat_scale(1.0,1.0,1.0);
while (arguments.read("quat_scaled", quat_scale.x(), quat_scale.y(), quat_scale.z() )) printQuatTest = true;
osg::Vec3d quat_scale(1.0,1.0,1.0);
while (arguments.read("quat_scaled", quat_scale.x(), quat_scale.y(), quat_scale.z() )) printQuatTest = true;
bool performanceTest = false;
while (arguments.read("p") || arguments.read("performance")) performanceTest = true;
bool performanceTest = false;
while (arguments.read("p") || arguments.read("performance")) performanceTest = true;
// if user request help write it out to cout.
if (arguments.read("-h") || arguments.read("--help"))
@@ -627,7 +628,7 @@ int main( int argc, char** argv )
arguments.writeErrorMessages(std::cout);
return 1;
}
if (printQuatTest)
{
testQuat(quat_scale);
@@ -648,7 +649,7 @@ int main( int argc, char** argv )
testLookAt(osg::Vec3(10.0,4.0,2.0),osg::Vec3(10.0,4.0,2.0)+osg::Vec3(0.0,1.0,0.0),osg::Vec3(0.0,0.0,1.0));
testLookAt(osg::Vec3(10.0,4.0,2.0),osg::Vec3(10.0,4.0,2.0)+osg::Vec3(1.0,1.0,0.0),osg::Vec3(0.0,0.0,1.0));
testMatrixInvert(osg::Matrix(0.999848, -0.002700, 0.017242, -0.1715,
0, 0.987960, 0.154710, 0.207295,
-0.017452, -0.154687, 0.987809, -0.98239,
@@ -662,11 +663,11 @@ int main( int argc, char** argv )
testDecompose();
}
if (printSizeOfTest)
{
std::cout<<"**** sizeof() tests ******"<<std::endl;
sizeOfTest();
std::cout<<std::endl;
@@ -676,7 +677,7 @@ int main( int argc, char** argv )
if (performanceTest)
{
std::cout<<"**** performance tests ******"<<std::endl;
runPerformanceTests();
}
@@ -693,12 +694,12 @@ int main( int argc, char** argv )
}
if (printQualifiedTest)
if (printQualifiedTest)
{
std::cout<<"***** Qualified Tests ******"<<std::endl;
osgUtx::QualifiedTestPrinter printer;
osgUtx::TestGraph::instance().root()->accept( printer );
osgUtx::TestGraph::instance().root()->accept( printer );
std::cout<<std::endl;
}

View File

@@ -21,21 +21,21 @@
#include <iostream>
// The idea of user stats is that you record times or values in the viewer's
// stats, and you also tell the stats handler to watch those values each
// The idea of user stats is that you record times or values in the viewer's
// stats, and you also tell the stats handler to watch those values each
// frame. The stats handler can display the stats in three ways:
// - A numeric time beside the stat name
// Requires that an elapsed time be recorded in the viewer's stats for the
// Requires that an elapsed time be recorded in the viewer's stats for the
// "timeTakenName".
// - A bar in the top bar graph
// Requires that two times (relative to the viewer's start tick) be
// Requires that two times (relative to the viewer's start tick) be
// recorded in the viewer's stats for the "beginTimeName" and "endTimeName".
// - A line in the bottom graph
// Requires that an elapsed time be recorded in the viewer's stats for the
// Requires that an elapsed time be recorded in the viewer's stats for the
// "timeTakenName".
// Anything you want to time has to use a consistent name in both the stats
// Anything you want to time has to use a consistent name in both the stats
// handler and the viewer stats, so it's a good idea to use constants to make
// sure the names are the same everywhere.
const std::string frameNumberName = "Custom Frame Number";
@@ -49,54 +49,54 @@ const std::string otherThreadTimeName = "Thread";
void initUserStats(osgViewer::StatsHandler* statsHandler)
{
// This line displays the frame number. It's not averaged, just displayed as is.
statsHandler->addUserStatsLine("Frame", osg::Vec4(0.7,0.7,0.7,1), osg::Vec4(0.7,0.7,0.7,0.5),
statsHandler->addUserStatsLine("Frame", osg::Vec4(0.7,0.7,0.7,1), osg::Vec4(0.7,0.7,0.7,0.5),
frameNumberName, 1.0, false, false, "", "", 0.0);
// This line displays the frame time (from beginning of event to end of draw). No bars.
statsHandler->addUserStatsLine("MS/frame", osg::Vec4(1,0,1,1), osg::Vec4(1,0,1,0.5),
statsHandler->addUserStatsLine("MS/frame", osg::Vec4(1,0,1,1), osg::Vec4(1,0,1,0.5),
frameTimeName, 1000.0, true, false, "", "", 0.02);
// This line displays the sum of update and main camera cull times.
statsHandler->addUserStatsLine("Custom", osg::Vec4(1,1,1,1), osg::Vec4(1,1,1,0.5),
statsHandler->addUserStatsLine("Custom", osg::Vec4(1,1,1,1), osg::Vec4(1,1,1,0.5),
customTimeName + " time taken", 1000.0, true, false, customTimeName + " begin", customTimeName + " end", 0.016);
// This line displays the time taken by a function below ( doSomethingAndTimeIt() )
statsHandler->addUserStatsLine("Sleep1", osg::Vec4(1,0,0,1), osg::Vec4(1,0,0,0.5),
statsHandler->addUserStatsLine("Sleep1", osg::Vec4(1,0,0,1), osg::Vec4(1,0,0,0.5),
operation1TimeName + " time taken", 1000.0, true, false, operation1TimeName + " begin", operation1TimeName + " end", 0.016);
// This line displays the time taken by a function below ( doSomethingAndTimeIt() )
statsHandler->addUserStatsLine("Sleep2", osg::Vec4(1,0.5,0.5,1), osg::Vec4(1,0.5,0.5,0.5),
statsHandler->addUserStatsLine("Sleep2", osg::Vec4(1,0.5,0.5,1), osg::Vec4(1,0.5,0.5,0.5),
operation2TimeName + " time taken", 1000.0, true, false, operation2TimeName + " begin", operation2TimeName + " end", 0.016);
// This line displays the time taken by a function below ( doSomethingAndTimeIt() )
statsHandler->addUserStatsLine("Thread", osg::Vec4(0,0.5,0,1), osg::Vec4(0,0.5,0,0.5),
statsHandler->addUserStatsLine("Thread", osg::Vec4(0,0.5,0,1), osg::Vec4(0,0.5,0,0.5),
otherThreadTimeName + " time taken", 1000.0, true, false, otherThreadTimeName + " begin", otherThreadTimeName + " end", 0.016);
}
void updateUserStats(osgViewer::Viewer& viewer)
{
// Test the custom stats line by just adding up the update and cull
// Test the custom stats line by just adding up the update and cull
// times for the viewer main camera for the previous frame.
if (viewer.getViewerStats()->collectStats("update") && viewer.getCamera()->getStats()->collectStats("rendering"))
{
// First get the frame number. The code below assumes that
// First get the frame number. The code below assumes that
// updateUserStats() is called after advance(), so the frame number
// that will be returned is for the frame that has just started and is
// not rendered yet. The previous frame is framenumber-1, but we can't
// use that frame's timings because it's probably not finished
// use that frame's timings because it's probably not finished
// rendering yet (in multithreaded viewer modes). So we'll use the
// timings for framenumber-2 for this demo.
unsigned int framenumber = viewer.getFrameStamp()->getFrameNumber();
// Get the update time and the viewer main camera's cull time. We use
// getAveragedAttribute() in order to get the actual time elapsed as
// Get the update time and the viewer main camera's cull time. We use
// getAveragedAttribute() in order to get the actual time elapsed as
// calculated by the stats.
double update = 0.0, cull = 0.0;
viewer.getViewerStats()->getAveragedAttribute("Update traversal time taken", update);
viewer.getCamera()->getStats()->getAveragedAttribute("Cull traversal time taken", cull);
// Get various begin and end times, note these are not elapsed times
// Get various begin and end times, note these are not elapsed times
// in a frame but rather the simulation time at those moments.
double eventBegin = 0.0, updateBegin = 0.0, cullEnd = 0.0, drawEnd = 0.0;
viewer.getViewerStats()->getAttribute(framenumber-2, "Event traversal begin time", eventBegin);
@@ -112,11 +112,11 @@ void updateUserStats(osgViewer::Viewer& viewer)
// This line displays the sum of update and main camera cull times.
viewer.getViewerStats()->setAttribute(framenumber-1, customTimeName + " time taken", update+cull);
// Since we give begin and end times that correspond to the begin of
// the update phase and the end of the cull phase, the bar in the
// graph will not correspond to the summed times above if something
// happened between update and cull (as in this demo). Also, we need
// to translate the updateBegin and cullEnd times by one frame since
// Since we give begin and end times that correspond to the begin of
// the update phase and the end of the cull phase, the bar in the
// graph will not correspond to the summed times above if something
// happened between update and cull (as in this demo). Also, we need
// to translate the updateBegin and cullEnd times by one frame since
// we're taking the times for framenumber-2 but using them to display
// in the framenumber-1 graph.
viewer.getViewerStats()->setAttribute(framenumber-1, customTimeName + " begin", updateBegin + (1.0/60.0));
@@ -125,7 +125,7 @@ void updateUserStats(osgViewer::Viewer& viewer)
}
/// Utility function you call before something you want to time, so that the
/// Utility function you call before something you want to time, so that the
/// recorded times will all be consistent using the viewer's time.
void startTiming(osgViewer::Viewer& viewer, const std::string& name)
{
@@ -136,7 +136,7 @@ void startTiming(osgViewer::Viewer& viewer, const std::string& name)
viewer.getViewerStats()->setAttribute(framenumber, name + " begin", currentTime);
}
/// Utility function you call after something you want to time, so that the
/// Utility function you call after something you want to time, so that the
/// recorded times will all be consistent using the viewer's time.
void endTiming(osgViewer::Viewer& viewer, const std::string& name)
{
@@ -157,7 +157,7 @@ void endTiming(osgViewer::Viewer& viewer, const std::string& name)
}
/// Will just sleep for the given number of milliseconds in the same thread
/// Will just sleep for the given number of milliseconds in the same thread
/// as the caller, recording the time taken in the viewer's stats.
void doSomethingAndTimeIt(osgViewer::Viewer& viewer, const std::string& name, double milliseconds)
{
@@ -166,7 +166,7 @@ void doSomethingAndTimeIt(osgViewer::Viewer& viewer, const std::string& name, do
//------------------------------------------------------------
// Your processing goes here.
// Do nothing for the specified number of milliseconds, just so we can
// Do nothing for the specified number of milliseconds, just so we can
// see it in the stats.
osg::Timer_t startTick = osg::Timer::instance()->tick();
while (osg::Timer::instance()->delta_m(startTick, osg::Timer::instance()->tick()) < milliseconds)
@@ -179,8 +179,8 @@ void doSomethingAndTimeIt(osgViewer::Viewer& viewer, const std::string& name, do
}
/// Thread that will sleep for the given number of milliseconds, recording
/// the time taken in the viewer's stats, whenever its process() method is
/// Thread that will sleep for the given number of milliseconds, recording
/// the time taken in the viewer's stats, whenever its process() method is
/// called.
class UselessThread : public OpenThreads::Thread
{
@@ -204,7 +204,7 @@ public:
//------------------------------------------------------------
// Your processing goes here.
// Do nothing for the specified number of milliseconds, just so we can
// Do nothing for the specified number of milliseconds, just so we can
// see it in the stats.
osg::Timer_t startTick = osg::Timer::instance()->tick();
while (osg::Timer::instance()->delta_m(startTick, osg::Timer::instance()->tick()) < _timeToRun)
@@ -337,7 +337,7 @@ int main(int argc, char** argv)
viewer.realize();
// Start up a thread that will just run for a fixed time each frame, in
// Start up a thread that will just run for a fixed time each frame, in
// parallel to the frame loop.
UselessThread thread(viewer, 6.0);
thread.start();
@@ -357,7 +357,7 @@ int main(int argc, char** argv)
viewer.eventTraversal();
viewer.updateTraversal();
// Eat up some time on the viewer thread between the update and cull
// Eat up some time on the viewer thread between the update and cull
// phases.
doSomethingAndTimeIt(viewer, operation2TimeName, 3.0);
@@ -365,9 +365,6 @@ int main(int argc, char** argv)
}
thread.cancel();
while (thread.isRunning())
{
OpenThreads::Thread::YieldCurrentThread();
}
thread.join();
}

View File

@@ -5,7 +5,7 @@
cOSG::cOSG(HWND hWnd) :
m_hWnd(hWnd)
m_hWnd(hWnd)
{
}
@@ -73,7 +73,7 @@ void cOSG::InitCameraConfig(void)
// Add a Stats Handler to the viewer
mViewer->addEventHandler(new osgViewer::StatsHandler);
// Get the current window size
::GetWindowRect(m_hWnd, &rect);
@@ -161,8 +161,8 @@ void cOSG::PostFrameUpdate()
//Sleep(10); // Use this command if you need to allow other processes to have cpu time
}
// For some reason this has to be here to avoid issue:
// if you have multiple OSG windows up
// For some reason this has to be here to avoid issue:
// if you have multiple OSG windows up
// and you exit one then all stop rendering
AfxMessageBox("Exit Rendering Thread");
@@ -177,8 +177,11 @@ CRenderingThread::CRenderingThread( cOSG* ptr )
CRenderingThread::~CRenderingThread()
{
_done = true;
while( isRunning() )
OpenThreads::Thread::YieldCurrentThread();
if (isRunning())
{
cancel();
join();
}
}
void CRenderingThread::run()