Skip to content

Commit

Permalink
[OmniDriverEmu] replace the use of phtread (on windows) or boost thre…
Browse files Browse the repository at this point in the history
…ad (on linux) by std::thread. Use an atomic bool to be able to stop the emulator thread from the main thread before closing it. This will fix possible seg fault or lock at exit.
  • Loading branch information
epernod committed Dec 15, 2020
1 parent 0eba7a7 commit 9db21c0
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 71 deletions.
79 changes: 16 additions & 63 deletions applications/plugins/SensableEmulation/OmniDriverEmu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,10 @@
#include <sofa/core/objectmodel/KeyreleasedEvent.h>

#include <chrono>
#include <thread>

#ifndef WIN32
# include <pthread.h>
#else
# include <boost/thread/thread.hpp>
#endif

#include <sofa/simulation/UpdateMappingVisitor.h>
#include <sofa/simulation/MechanicalVisitor.h>

#ifdef WIN32
# include <windows.h>
#endif

#include <sofa/helper/rmath.h>

namespace sofa
Expand Down Expand Up @@ -100,6 +89,7 @@ OmniDriverEmu::OmniDriverEmu()
moveOmniBase = false;
executeAsynchro = false;
omniSimThreadCreated = false;
m_terminate = true;
}


Expand All @@ -121,26 +111,12 @@ void OmniDriverEmu::setForceFeedbacks(vector<ForceFeedback*> ffs)

void OmniDriverEmu::cleanup()
{
msg_info() << "cleanup()" ;

// If the thread is still running stop it
if (omniSimThreadCreated)
if (m_terminate == false && omniSimThreadCreated)
{
#ifndef WIN32
int err = pthread_cancel(hapSimuThread);

// no error: thread cancel
if(err==0)
{
msg_info() << "Haptic thread has been cancelled in cleanup without error.";
}

// error
else
{
msg_error() << "Haptic thread cancel in cleanup failed with error code = " << err ;
}
#endif
m_terminate = true;
hapSimuThread.join();
omniSimThreadCreated = false;
msg_info() << "Haptic thread has been cancelled in cleanup without error.";
}
}

Expand All @@ -161,7 +137,7 @@ void OmniDriverEmu::init()
/**
function that is used to emulate a haptic device by interpolating the position of the tool between several points.
*/
void *hapticSimuExecute( void *ptr )
void hapticSimuExecute(std::atomic<bool>& terminate, void *ptr )
{
assert(ptr!=nullptr);

Expand All @@ -175,7 +151,7 @@ void *hapticSimuExecute( void *ptr )
if (pts.empty())
{
msg_error(omniDrv) << "Bad trajectory specification : there are no points for interpolation. ";
return nullptr;
return;
}

// Add a first point ( 0 0 0 0 0 0 1 ) if the first "key time" is not 0
Expand All @@ -192,7 +168,7 @@ void *hapticSimuExecute( void *ptr )
if (numSegs != numPts)
{
msg_error(omniDrv) << "Bad trajectory specification : the number of trajectory timing does not match the number of trajectory points. ";
return nullptr;
return;
}

helper::vector< unsigned int > stepNum;
Expand All @@ -219,7 +195,7 @@ void *hapticSimuExecute( void *ptr )

int oneTimeMessage = 0;
// loop that updates the position tool.
while (true)
while (!terminate)
{
if (omniDrv->executeAsynchro)
{
Expand Down Expand Up @@ -258,12 +234,7 @@ void *hapticSimuExecute( void *ptr )
else
{
msg_info(omniDrv) << "End of the movement!" ;
omniDrv->setOmniSimThreadCreated(false);
#ifndef WIN32
pthread_exit(0);
#else
return 0;
#endif
return;
}

// Update the position of the tool
Expand Down Expand Up @@ -348,35 +319,17 @@ void OmniDriverEmu::bwdInit()
if (omniSimThreadCreated)
{
msg_warning() << "Emulating thread already running" ;

#ifndef WIN32
int err = pthread_cancel(hapSimuThread);

// no error: thread cancel
if(err==0)
{
msg_info() << "OmniDriverEmu: Haptic thread has been cancelled without error.";
}
else
{
msg_warning() << "thread cancel failed with error code = " << err ;
}
#endif
m_terminate = false;
cleanup();
}

if (thTimer == nullptr)
thTimer = new(helper::system::thread::CTime);

#ifndef WIN32
if ( pthread_create( &hapSimuThread, nullptr, hapticSimuExecute, static_cast<void*>(this)) == 0 )
{
msg_info() << "OmniDriver : Thread created for Omni simulation." ;
omniSimThreadCreated=true;
}
#else
boost::thread hapSimuThread(hapticSimuExecute, this);
m_terminate = false;
hapSimuThread = std::thread(hapticSimuExecute, std::ref(this->m_terminate), this);
setOmniSimThreadCreated(true);
#endif
msg_info() << "OmniDriver : Thread created for Omni simulation.";
}


Expand Down
14 changes: 6 additions & 8 deletions applications/plugins/SensableEmulation/OmniDriverEmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,7 @@
#include <sofa/defaulttype/SolidTypes.h>

#include <sofa/helper/system/thread/CTime.h>

#ifndef WIN32
# include <pthread.h>
#endif

#include <thread>
#include <SensableEmulation/config.h>


Expand Down Expand Up @@ -139,9 +135,11 @@ class SOFA_SENSABLEEMUPLUGIN_API OmniDriverEmu : public Controller
//need for "omni simulation"
helper::system::thread::CTime *thTimer;

#ifndef WIN32
pthread_t hapSimuThread;
#endif
/// Thread object
std::thread hapSimuThread;

/// Bool to notify thread to stop work
std::atomic<bool> m_terminate;

double lastStep;
bool executeAsynchro;
Expand Down

0 comments on commit 9db21c0

Please sign in to comment.