Commit e0a732ce authored by Jussi Lindgren's avatar Jussi Lindgren

Merge branch 'wip-jlindgre-std-threads' of gitlab.inria.fr:openvibe/extras...

Merge branch 'wip-jlindgre-std-threads' of gitlab.inria.fr:openvibe/extras into wip-all-openvibe20-base
parents 8585b9f5 40b64bdd
......@@ -69,8 +69,8 @@ INCLUDE("FindThirdPartyLiveAmpAPI")
INCLUDE("FindThirdPartyOpenAL")
INCLUDE("FindThirdPartyBoost")
INCLUDE("FindThirdPartyBoost_Thread")
INCLUDE("FindThirdPartyPThread") # for Windows Fieldtrip
INCLUDE("FindThirdPartyRT") # external stims shared memory needs this
INCLUDE("FindThirdPartyLSL")
......
......@@ -93,14 +93,53 @@ const char* CDriverBioSemiActiveTwo::getName(void)
return "BioSemi Active Two (MkI and MkII)";
}
void CDriverBioSemiActiveTwo::setupInformationWindow(void)
{
if (!m_pInformationWindow)
{
m_rDriverContext.getLogManager() << LogLevel_Error << "Information window not allocated\n";
return;
}
std::lock_guard<std::mutex> l_lock(m_pInformationWindow->m_oMutex);
m_pInformationWindow->m_pBuilderConfigureInterface=gtk_builder_new();
if(!gtk_builder_add_from_file(m_pInformationWindow->m_pBuilderConfigureInterface, OpenViBE::Directories::getDataDir() + "/applications/acquisition-server/interface-BioSemi-ActiveTwo.ui", NULL))
  • Don't you have access to the OV_ERROR_UNLESS_K ?

  • No, afaik *this has neither logmanager or errormanager getters as members. And before you suggest to use another macro, note that ErrorManager is likely not available at all in this context. Wontfix in current commit scope, feel free to add a task to make AS and its components ErrorManager-compatible.

Please register or sign in to reply
{
m_rDriverContext.getLogManager() << LogLevel_Error << "File not found: "<< OpenViBE::Directories::getDataDir() << "/applications/acquisition-server/interface-BioSemi-ActiveTwo.ui\n";
return;
}
gtk_label_set_markup(GTK_LABEL(gtk_builder_get_object(m_pInformationWindow->m_pBuilderConfigureInterface, "label-device-type")), (m_oBridge.isDeviceMarkII() ? "- <i>ActiveTwo Mark II</i> -" : "- <i>ActiveTwo Mark I</i> -"));
m_pInformationWindow->m_bIsCMSInRange = m_oBridge.isCMSInRange();
m_pInformationWindow->m_bIsBatteryLow = m_oBridge.isBatteryLow();
m_pInformationWindow->m_bIsChanged = true;
gtk_widget_show_all(GTK_WIDGET(gtk_builder_get_object(m_pInformationWindow->m_pBuilderConfigureInterface, "device-information")));
return;
}
//___________________________________________________________________//
// //
gint setup_information_window_callback(void* pUserData)
{
CDriverBioSemiActiveTwo* pTmp = static_cast<CDriverBioSemiActiveTwo*>(pUserData);
pTmp->setupInformationWindow();
return FALSE; // Don't run again
}
gint information_window_callback(void* pInformationWindow)
{
if (!pInformationWindow)
{
// Not initialized yet?
return TRUE;
}
SInformationWindow* l_pInformationWindow = reinterpret_cast<SInformationWindow*>(pInformationWindow);
boost::mutex::scoped_lock l_lock(reinterpret_cast<SInformationWindow*>(pInformationWindow)->m_oMutex);
std::lock_guard<std::mutex> l_lock(reinterpret_cast<SInformationWindow*>(pInformationWindow)->m_oMutex);
// If nothing changed, directly return from the callback
if(!l_pInformationWindow->m_bIsChanged)
{
......@@ -111,6 +150,10 @@ gint information_window_callback(void* pInformationWindow)
// If the acquisition is ended, delete the window
gtk_widget_destroy(GTK_WIDGET(gtk_builder_get_object(l_pInformationWindow->m_pBuilderConfigureInterface, "device-information")));
g_object_unref(l_pInformationWindow->m_pBuilderConfigureInterface);
// If we get here, we know that the other thread has passed uninitialize() and will no longer access
// l_pInformationMindow.
delete l_pInformationWindow;
// The loop should now be stopped
return FALSE;
}
......@@ -230,23 +273,15 @@ boolean CDriverBioSemiActiveTwo::initialize(
}
}
// Initialize information window
gdk_threads_enter();
m_pInformationWindow = new SInformationWindow();
m_pInformationWindow->m_pBuilderConfigureInterface=gtk_builder_new();
if(!gtk_builder_add_from_file(m_pInformationWindow->m_pBuilderConfigureInterface, OpenViBE::Directories::getDataDir() + "/applications/acquisition-server/interface-BioSemi-ActiveTwo.ui", NULL))
{
m_rDriverContext.getLogManager() << LogLevel_Error << "File not found: "<< OpenViBE::Directories::getDataDir() << "/applications/acquisition-server/interface-BioSemi-ActiveTwo.ui\n";
}
gtk_label_set_markup(GTK_LABEL(gtk_builder_get_object(m_pInformationWindow->m_pBuilderConfigureInterface, "label-device-type")), (m_oBridge.isDeviceMarkII() ? "- <i>ActiveTwo Mark II</i> -" : "- <i>ActiveTwo Mark I</i> -"));
m_pInformationWindow->m_bIsCMSInRange = m_oBridge.isCMSInRange();
m_pInformationWindow->m_bIsBatteryLow = m_oBridge.isBatteryLow();
m_pInformationWindow->m_bIsChanged = true;
gtk_widget_show_all(GTK_WIDGET(gtk_builder_get_object(m_pInformationWindow->m_pBuilderConfigureInterface, "device-information")));
// Initialize information window
// n.b. do all gtk stuff from callbacks to avoid threading issues.
gdk_threads_add_idle(setup_information_window_callback, this);
//Launch idle loop: update the information window in a separate glib thread
g_idle_add(information_window_callback, m_pInformationWindow);
gdk_threads_leave();
gdk_threads_add_idle(information_window_callback, m_pInformationWindow);
return true;
}
......@@ -284,7 +319,7 @@ boolean CDriverBioSemiActiveTwo::loop(void)
// we consume one sample per channel, values are given in uV
if(!m_oBridge.consumeOneSamplePerChannel(&m_vSample[0], l_ui32Max))
{
boost::mutex::scoped_lock l_lock(m_pInformationWindow->m_oMutex);
std::lock_guard<std::mutex> l_lock(m_pInformationWindow->m_oMutex);
m_rDriverContext.getLogManager() << LogLevel_Error << "Something bad happened while consuming samples from device.\n";
m_pInformationWindow->m_bIsChanged = true;
m_pInformationWindow->m_sErrorMessage = "<span color=\"darkred\">Something bad happened while consuming samples from device.</span>\n";
......@@ -348,7 +383,7 @@ boolean CDriverBioSemiActiveTwo::loop(void)
m_rDriverContext.getLogManager() << "\t The corresponding sample range has been tagged with OVTK_StimulationId_SegmentStart and OVTK_StimulationId_SegmentStop.\n";
m_rDriverContext.getLogManager() << "\t Possible causes include broken wires, damaged cable isolation, bad connector contacts, defect IC inside the electrode.\n";
{
boost::mutex::scoped_lock l_lock(m_pInformationWindow->m_oMutex);
std::lock_guard<std::mutex> l_lock(m_pInformationWindow->m_oMutex);
m_pInformationWindow->m_bIsCMSInRange = false;
m_pInformationWindow->m_bIsChanged = true;
}
......@@ -382,7 +417,7 @@ boolean CDriverBioSemiActiveTwo::loop(void)
m_bCMSBackInRange = true;
m_rDriverContext.getLogManager() << LogLevel_Info << "Back in range \n";
{
boost::mutex::scoped_lock l_lock(m_pInformationWindow->m_oMutex);
std::lock_guard<std::mutex> l_lock(m_pInformationWindow->m_oMutex);
m_pInformationWindow->m_bIsCMSInRange = true;
m_pInformationWindow->m_bIsChanged = true;
}
......@@ -397,7 +432,7 @@ boolean CDriverBioSemiActiveTwo::loop(void)
l_bWarningDisplayed = true;
m_rDriverContext.getLogManager() << LogLevel_Warning << "("<<((System::Time::getTime() - m_ui32StartTime)/1000)<<"') Device battery is low !\n";
{
boost::mutex::scoped_lock l_lock(m_pInformationWindow->m_oMutex);
std::lock_guard<std::mutex> l_lock(m_pInformationWindow->m_oMutex);
m_pInformationWindow->m_bIsBatteryLow = true;
m_pInformationWindow->m_bIsChanged = true;
}
......@@ -420,7 +455,7 @@ boolean CDriverBioSemiActiveTwo::loop(void)
m_bBatteryBackOk = true;
m_rDriverContext.getLogManager() << LogLevel_Info << "Back in range \n";
{
boost::mutex::scoped_lock l_lock(m_pInformationWindow->m_oMutex);
std::lock_guard<std::mutex> l_lock(m_pInformationWindow->m_oMutex);
m_pInformationWindow->m_bIsBatteryLow = false;
m_pInformationWindow->m_bIsChanged = true;
}
......@@ -442,7 +477,7 @@ boolean CDriverBioSemiActiveTwo::loop(void)
m_rDriverContext.getLogManager() << LogLevel_Error << "An error occured while reading data from device !\n";
m_bAcquisitionStopped = true;
{
boost::mutex::scoped_lock l_lock(m_pInformationWindow->m_oMutex);
std::lock_guard<std::mutex> l_lock(m_pInformationWindow->m_oMutex);
m_pInformationWindow->m_sErrorMessage = "<span color=\"darkred\">An error occured while reading data from device !</span>";
m_pInformationWindow->m_bIsChanged = true;
}
......@@ -462,7 +497,7 @@ boolean CDriverBioSemiActiveTwo::loop(void)
m_rDriverContext.getLogManager() << LogLevel_Error << "An error occured while dropping samples.\n";
m_bAcquisitionStopped = true;
{
boost::mutex::scoped_lock l_lock(m_pInformationWindow->m_oMutex);
std::lock_guard<std::mutex> l_lock(m_pInformationWindow->m_oMutex);
m_pInformationWindow->m_sErrorMessage = "<span color=\"darkred\">An error occured while dropping samples.</span>";
m_pInformationWindow->m_bIsChanged = true;
}
......@@ -475,7 +510,7 @@ boolean CDriverBioSemiActiveTwo::loop(void)
m_rDriverContext.getLogManager() << LogLevel_Error << "An error occured while reading data from device (drop)!\n";
m_bAcquisitionStopped = true;
{
boost::mutex::scoped_lock l_lock(m_pInformationWindow->m_oMutex);
std::lock_guard<std::mutex> l_lock(m_pInformationWindow->m_oMutex);
m_pInformationWindow->m_sErrorMessage = "<span color=\"darkred\">An error occured while reading data from device (drop)!</span>";
m_pInformationWindow->m_bIsChanged = true;
}
......@@ -499,10 +534,13 @@ boolean CDriverBioSemiActiveTwo::stop(void)
boolean CDriverBioSemiActiveTwo::uninitialize(void)
{
{
boost::mutex::scoped_lock l_lock(m_pInformationWindow->m_oMutex);
std::lock_guard<std::mutex> l_lock(m_pInformationWindow->m_oMutex);
m_pInformationWindow->m_bIsChanged = true;
m_pInformationWindow->m_bIsAcquisitionEnded = true;
m_pInformationWindow = NULL; // The callback will free the memory
}
// Rename EX channels as "" so that the names are not saved as settings
if(m_oBridge.isUseEXChannels())
{
......@@ -520,7 +558,7 @@ boolean CDriverBioSemiActiveTwo::uninitialize(void)
m_rDriverContext.getLogManager() << LogLevel_Warning << "Could not close the device.\n";
return false;
}
m_rDriverContext.getLogManager() << LogLevel_Error << "Driver uninitialized...\n";
m_rDriverContext.getLogManager() << LogLevel_Info << "Driver uninitialized...\n";
return true;
}
......
......@@ -33,8 +33,10 @@
#include "mCBridgeBioSemiActiveTwo.h"
#include "gtk/gtk.h"
#include "boost/thread.hpp"
#include <vector>
#include <thread>
#include <mutex>
namespace OpenViBEAcquisitionServer
{
......@@ -65,7 +67,7 @@ namespace OpenViBEAcquisitionServer
// The window is changed in a idle loop in function of m_bIsCMSInRange,
// m_bIsBatteryLow and m_sErrorMessage that change in the driver loop
// A mutex is necessary to secure the access to the data
boost::mutex m_oMutex;
std::mutex m_oMutex;
} SInformationWindow;
/**
......@@ -94,7 +96,11 @@ namespace OpenViBEAcquisitionServer
virtual const OpenViBEAcquisitionServer::IHeader* getHeader(void) { return &m_oHeader; }
//OpenViBE::uint32 getChannelCount();
// Called from gtk callback
void setupInformationWindow(void);
protected:
SettingsHelper m_oSettings;
OpenViBEAcquisitionServer::IDriverCallback* m_pCallback;
......
......@@ -153,7 +153,7 @@ boolean CDriverEnobio3G::loop(void) {
// query new data flag state
OpenViBE::boolean l_bNewData;
{
boost::mutex::scoped_lock lock(m_oMutex);
std::lock_guard<std::mutex> lock(m_oMutex);
l_bNewData = m_bNewData;
}
......@@ -166,7 +166,7 @@ boolean CDriverEnobio3G::loop(void) {
m_pCallback->setSamples(m_pSample[m_ui32lastBufferFilled]);
// lower new data flag
{
boost::mutex::scoped_lock lock(m_oMutex);
std::lock_guard<std::mutex> lock(m_oMutex);
m_bNewData = false;
}
// When your sample buffer is fully loaded,
......@@ -270,7 +270,7 @@ void CDriverEnobio3G::receiveData(const PData &data){
// mutex for writing header and new data flag
{
boost::mutex::scoped_lock lock(m_oMutex);
std::lock_guard<std::mutex> lock(m_oMutex);
m_ui32bufHead++;
// if we already filled the current buffer we need to raise the new data flag
......
......@@ -15,8 +15,7 @@
#include "enobio3g.h"
#include "StatusData.h"
#include <boost/thread.hpp>
#include <boost/thread/condition.hpp>
#include <mutex>
#ifndef _ENOBIO_SAMPLE_RATE_
#ifdef FREQ_SAMP
......@@ -99,7 +98,7 @@ namespace OpenViBEAcquisitionServer
OpenViBE::uint32 m_ui32lastBufferFilled; // last buffer filled with data ready to be submitted
OpenViBE::boolean m_bNewData; // if there is a new buffer with data ready to be submitted
boost::mutex m_oMutex;
std::mutex m_oMutex;
};
};
......
......@@ -20,28 +20,9 @@
#include <cassert>
#include <iostream>
#include <mutex>
// @FIXME CERT
#pragma message("WARNING: Hard-coding some CIdentifiers that should be obtainable from OpenViBE SDK in the future")
#define OVP_GD_ClassId_Algorithm_MasterAcquisitionStreamEncoder OpenViBE::CIdentifier(0x2D15E00B, 0x51414EB6)
#define OVP_GD_ClassId_Algorithm_MasterAcquisitionStreamEncoderDesc OpenViBE::CIdentifier(0xE6EC841D, 0x9E75A8FB)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_InputParameterId_SubjectIdentifier OpenViBE::CIdentifier(0xD5BB5231, 0x59389B72)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_InputParameterId_SubjectAge OpenViBE::CIdentifier(0x9EF355E4, 0xC8531112)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_InputParameterId_SubjectGender OpenViBE::CIdentifier(0xA9056AE3, 0x57FE6AF0)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_InputParameterId_SignalMatrix OpenViBE::CIdentifier(0xE9AC8077, 0xE369A51D)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_InputParameterId_SignalSamplingRate OpenViBE::CIdentifier(0xB84AD0CA, 0x4F316DD3)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_InputParameterId_StimulationSet OpenViBE::CIdentifier(0x5B728D37, 0xFD088887)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_InputParameterId_BufferDuration OpenViBE::CIdentifier(0xE1FC7385, 0x586A4F3F)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_InputParameterId_ChannelLocalisation OpenViBE::CIdentifier(0x227E13F0, 0x206B44F9)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_InputParameterId_ChannelUnits OpenViBE::CIdentifier(0x740060C2, 0x7D2B4F57)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_InputParameterId_EncodeChannelLocalisationData OpenViBE::CIdentifier(0x26EE1F81, 0x3DB00D5D)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_InputParameterId_EncodeChannelUnitData OpenViBE::CIdentifier(0x19DC533C, 0x56301D0B)
#define OVP_GD_Algorithm_AcquisitionStreamEncoder_OutputParameterId_EncodedMemoryBuffer OpenViBE::CIdentifier(0xa3d8b171, 0xf8734734)
#define OVP_GD_Algorithm_AcquisitionStreamEncoder_InputTriggerId_EncodeBuffer OpenViBE::CIdentifier(0x1b7076fd, 0x449bc70a)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_OutputParameterId_EncodedMemoryBuffer OpenViBE::CIdentifier(0xa3d8b171, 0xf8734734)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_InputTriggerId_EncodeHeader OpenViBE::CIdentifier(0x878eaf60, 0xf9d5303f)
#define OVP_GD_Algorithm_MasterAcquisitionStreamEncoder_InputTriggerId_EncodeBuffer OpenViBE::CIdentifier(0x1b7076fd, 0x449bc70a)
#include <iostream>
#define boolean OpenViBE::boolean
......@@ -189,9 +170,8 @@ namespace OpenViBEAcquisitionServer
CMemoryBuffer* l_pMemoryBuffer=NULL;
{
boost::mutex::scoped_lock l_oProtectionLock(m_oPendingBufferProtectionMutex);
boost::mutex::scoped_lock l_oExecutionLock(m_oPendingBufferExectutionMutex);
l_oProtectionLock.unlock();
DoubleLock lock(&m_oPendingBufferProtectionMutex, &m_oPendingBufferExecutionMutex);
if(m_vPendingBuffer.size())
{
l_pMemoryBuffer=m_vPendingBuffer.front();
......@@ -223,9 +203,9 @@ namespace OpenViBEAcquisitionServer
void scheduleBuffer(const IMemoryBuffer& rMemoryBuffer)
{
CMemoryBuffer* l_pMemoryBuffer=new CMemoryBuffer(rMemoryBuffer);
boost::mutex::scoped_lock l_oProtectionLock(m_oPendingBufferProtectionMutex);
boost::mutex::scoped_lock l_oExecutionLock(m_oPendingBufferExectutionMutex);
l_oProtectionLock.unlock();
DoubleLock lock(&m_oPendingBufferProtectionMutex, &m_oPendingBufferExecutionMutex);
m_vPendingBuffer.push_back(l_pMemoryBuffer);
}
......@@ -233,8 +213,10 @@ namespace OpenViBEAcquisitionServer
Socket::IConnection& m_rConnection;
std::deque < CMemoryBuffer* > m_vPendingBuffer;
boost::mutex m_oPendingBufferExectutionMutex;
boost::mutex m_oPendingBufferProtectionMutex;
// See class DoubleLock
std::mutex m_oPendingBufferProtectionMutex;
std::mutex m_oPendingBufferExecutionMutex;
};
static void start_connection_client_handler_thread(CConnectionClientHandlerThread* pThread)
......@@ -247,7 +229,7 @@ namespace OpenViBEAcquisitionServer
// //
CAcquisitionServer::CAcquisitionServer(const IKernelContext& rKernelContext)
:m_pConnectionServerHandlerBoostThread(NULL)
:m_pConnectionServerHandlerStdThread(NULL)
,m_rKernelContext(rKernelContext)
,m_pDriverContext(NULL)
,m_pDriver(NULL)
......@@ -391,9 +373,7 @@ boolean CAcquisitionServer::loop(void)
// Searches for new connection(s)
if(m_pConnectionServer)
{
boost::mutex::scoped_lock m_oProtectionLock(m_oPendingConnectionProtectionMutex);
boost::mutex::scoped_lock m_oExecutionLock(m_oPendingConnectionExectutionMutex);
m_oProtectionLock.unlock();
DoubleLock lock(&m_oPendingConnectionProtectionMutex, &m_oPendingConnectionExecutionMutex);
for(itConnection=m_vPendingConnection.begin(); itConnection!=m_vPendingConnection.end(); itConnection++)
{
......@@ -425,10 +405,10 @@ boolean CAcquisitionServer::loop(void)
l_oInfo.m_ui64StimulationTimeOffset=ITimeArithmetics::sampleCountToTime(m_ui32SamplingFrequency, l_ui64TheoreticalSampleCountToSkip+m_ui64SampleCount-m_vPendingBuffer.size());
l_oInfo.m_ui64SignalSampleCountToSkip=l_ui64TheoreticalSampleCountToSkip;
l_oInfo.m_pConnectionClientHandlerThread=new CConnectionClientHandlerThread(*this, *l_pConnection);
l_oInfo.m_pConnectionClientHandlerBoostThread=new boost::thread(boost::bind(&start_connection_client_handler_thread, l_oInfo.m_pConnectionClientHandlerThread));
l_oInfo.m_pConnectionClientHandlerStdThread=new std::thread(std::bind(&start_connection_client_handler_thread, l_oInfo.m_pConnectionClientHandlerThread));
l_oInfo.m_bChannelLocalisationSent = false;
l_oInfo.m_bChannelUnitsSent = false;
//applyPriority(l_oInfo.m_pConnectionClientHandlerBoostThread,15);
//applyPriority(l_oInfo.m_pConnectionClientHandlerStdThread,15);
m_vConnection.push_back(pair < Socket::IConnection*, SConnectionInfo >(l_pConnection, l_oInfo));
......@@ -467,10 +447,10 @@ boolean CAcquisitionServer::loop(void)
if(!l_pConnection->isConnected())
{
l_pConnection->release();
if(itConnection->second.m_pConnectionClientHandlerBoostThread)
if(itConnection->second.m_pConnectionClientHandlerStdThread)
{
itConnection->second.m_pConnectionClientHandlerBoostThread->join();
delete itConnection->second.m_pConnectionClientHandlerBoostThread;
itConnection->second.m_pConnectionClientHandlerStdThread->join();
delete itConnection->second.m_pConnectionClientHandlerStdThread;
delete itConnection->second.m_pConnectionClientHandlerThread;
}
itConnection=m_vConnection.erase(itConnection);
......@@ -822,8 +802,8 @@ boolean CAcquisitionServer::connect(IDriver& rDriver, IHeader& rHeaderCopy, uint
return false;
}
m_pConnectionServerHandlerBoostThread=new boost::thread(CConnectionServerHandlerThread(*this, *m_pConnectionServer));
//applyPriority(m_pConnectionServerHandlerBoostThread,15);
m_pConnectionServerHandlerStdThread=new std::thread(CConnectionServerHandlerThread(*this, *m_pConnectionServer));
//applyPriority(m_pConnectionServerHandlerStdThread,15);
return true;
}
......@@ -884,10 +864,10 @@ boolean CAcquisitionServer::stop(void)
while(itConnection!=m_vConnection.end())
{
itConnection->first->close();
if(itConnection->second.m_pConnectionClientHandlerBoostThread)
if(itConnection->second.m_pConnectionClientHandlerStdThread)
{
itConnection->second.m_pConnectionClientHandlerBoostThread->join();
delete itConnection->second.m_pConnectionClientHandlerBoostThread;
itConnection->second.m_pConnectionClientHandlerStdThread->join();
delete itConnection->second.m_pConnectionClientHandlerStdThread;
delete itConnection->second.m_pConnectionClientHandlerThread;
}
itConnection->first->release();
......@@ -930,11 +910,11 @@ boolean CAcquisitionServer::disconnect(void)
// Thread joining must be done after
// switching m_bInitialized to false
if(m_pConnectionServerHandlerBoostThread)
if(m_pConnectionServerHandlerStdThread)
{
m_pConnectionServerHandlerBoostThread->join();
delete m_pConnectionServerHandlerBoostThread;
m_pConnectionServerHandlerBoostThread=NULL;
m_pConnectionServerHandlerStdThread->join();
delete m_pConnectionServerHandlerStdThread;
m_pConnectionServerHandlerStdThread=NULL;
}
return true;
......@@ -1149,16 +1129,14 @@ boolean CAcquisitionServer::acceptNewConnection(Socket::IConnection* pConnection
uint64 l_ui64Time=System::Time::zgetTime();
boost::mutex::scoped_lock m_oProtectionLock(m_oPendingConnectionProtectionMutex);
boost::mutex::scoped_lock m_oExecutionLock(m_oPendingConnectionExectutionMutex);
m_oProtectionLock.unlock();
DoubleLock lock(&m_oPendingConnectionProtectionMutex, &m_oPendingConnectionExecutionMutex);
SConnectionInfo l_oInfo;
l_oInfo.m_ui64ConnectionTime=l_ui64Time;
l_oInfo.m_ui64StimulationTimeOffset=0; // not used
l_oInfo.m_ui64SignalSampleCountToSkip=0; // not used
l_oInfo.m_pConnectionClientHandlerThread=NULL; // not used
l_oInfo.m_pConnectionClientHandlerBoostThread=NULL; // not used
l_oInfo.m_pConnectionClientHandlerStdThread=NULL; // not used
l_oInfo.m_bChannelLocalisationSent = false;
l_oInfo.m_bChannelUnitsSent = false;
......
......@@ -8,9 +8,8 @@
#include <socket/IConnectionServer.h>
#include <boost/thread.hpp>
#include <boost/thread/condition.hpp>
#include <boost/version.hpp>
#include <mutex>
#include <thread>
#include <string>
#include <vector>
......@@ -30,7 +29,7 @@ namespace OpenViBEAcquisitionServer
OpenViBE::uint64 m_ui64StimulationTimeOffset;
OpenViBE::uint64 m_ui64SignalSampleCountToSkip;
CConnectionClientHandlerThread* m_pConnectionClientHandlerThread;
boost::thread* m_pConnectionClientHandlerBoostThread;
std::thread* m_pConnectionClientHandlerStdThread;
bool m_bChannelUnitsSent;
bool m_bChannelLocalisationSent;
} SConnectionInfo;
......@@ -42,6 +41,28 @@ namespace OpenViBEAcquisitionServer
NaNReplacementPolicy_Disabled,
} ENaNReplacementPolicy;
// Concurrency handling
class DoubleLock {
// Implements
// lock(mutex1);
// lock(mutex2);
// unlock(mutex1);
// mutex2 lock is released when the object goes out of scope
//
// @details The two mutex 'pattern' is used to avoid thread starving which can happen e.g.
// on Linux if just a single mutex is used; apparently the main loop just takes the
// mutex repeatedly without the gui thread sitting on the mutex being unlocked.
// n.b. potentially calls for redesign
public:
DoubleLock(std::mutex* m1, std::mutex* m2) : lock2(*m2, std::defer_lock)
{
std::lock_guard<std::mutex> lock1(*m1);
lock2.lock();
}
private:
std::unique_lock<std::mutex> lock2;
};
class CDriverContext;
class CAcquisitionServer : public OpenViBEAcquisitionServer::IDriverCallback
{
......@@ -90,13 +111,14 @@ namespace OpenViBEAcquisitionServer
public:
boost::mutex m_oExecutionMutex;
boost::mutex m_oProtectionMutex;
// See class DoubleLock
std::mutex m_oProtectionMutex;
std::mutex m_oExecutionMutex;
boost::mutex m_oPendingConnectionExectutionMutex;
boost::mutex m_oPendingConnectionProtectionMutex;
std::mutex m_oPendingConnectionProtectionMutex;
std::mutex m_oPendingConnectionExecutionMutex;
boost::thread* m_pConnectionServerHandlerBoostThread;
std::thread* m_pConnectionServerHandlerStdThread;
public:
......
......@@ -279,7 +279,7 @@ CAcquisitionServerGUI::CAcquisitionServerGUI(const IKernelContext& rKernelContex
// Initialize GTK objects as the thread started below may refer to them quickly
this->initialize();
m_pThread=new boost::thread(CAcquisitionServerThreadHandle(*m_pAcquisitionServerThread));
m_pThread=new std::thread(CAcquisitionServerThreadHandle(*m_pAcquisitionServerThread));
}
CAcquisitionServerGUI::~CAcquisitionServerGUI(void)
......
......@@ -8,9 +8,8 @@
#include <socket/IConnectionServer.h>
#include <boost/thread.hpp>
#include <boost/thread/condition.hpp>
#include <boost/version.hpp>
#include <thread>
#include <boost/algorithm/string.hpp>
#include <gtk/gtk.h>
......@@ -85,7 +84,7 @@ namespace OpenViBEAcquisitionServer
::GtkWidget* m_pImpedanceWindow;
std::vector < ::GtkWidget* > m_vLevelMesure;
boost::thread* m_pThread;
std::thread* m_pThread;
};
};
......
......@@ -197,13 +197,6 @@ int main(int argc, char ** argv)
l_rConfigurationManager.addOrReplaceConfigurationToken((*itr).first.c_str(), (*itr).second.c_str());
}
//initialise Gtk before 3D context
#if !GLIB_CHECK_VERSION(2,32,0)
// although deprecated in newer GTKs (no more needed after (at least) 2.24.13, deprecated in 2.32), we need to use this on Windows with the older GTK (2.22.1), or acquisition server will crash on startup
g_thread_init(NULL);
#endif
gdk_threads_init();
if(!gtk_init_check(&argc, &argv))
{
l_pKernelContext->getLogManager() << LogLevel_Error << "Unable to initialize GTK. Possibly the display could not be opened. Exiting.\n";
......@@ -247,9 +240,7 @@ int main(int argc, char ** argv)
try
{
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
gtk_main();
}
catch(...)
{
......
# ---------------------------------
# Finds third party rt
# Adds library to target
# Adds include path
# ---------------------------------
GET_PROPERTY(OV_PRINTED GLOBAL PROPERTY OV_TRIED_ThirdPartyRT)
IF(UNIX)
# For Ubuntu 13.04 (interprocess/ipc/message_queue.hpp in ovasCPluginExternalStimulations.cpp caused dep)
FIND_LIBRARY(LIB_STANDARD_MODULE_RT rt)
IF(LIB_STANDARD_MODULE_RT)
OV_PRINT(OV_PRINTED " Found rt...")
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LIB_STANDARD_MODULE_RT})
ELSE(LIB_STANDARD_MODULE_RT)
OV_PRINT(OV_PRINTED " FAILED to find rt...")