Commit daae40db authored by Jussi Lindgren's avatar Jussi Lindgren

Kernel: Introducing multicore scheduler prototype

Prototype only, tests do not pass + has problems. Do not merge/use yet.
parent 63d5741a
......@@ -12,7 +12,12 @@ SET(PROJECT_VERSION_PATCH ${OV_GLOBAL_VERSION_PATCH})
SET(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
FILE(GLOB_RECURSE source_files src/*.cpp src/*.h src/*.inl)
ADD_EXECUTABLE(${PROJECT_NAME} ${source_files})
IF(WIN32)
# ADD_EXECUTABLE(${PROJECT_NAME} WIN32 ${source_files})
ADD_EXECUTABLE(${PROJECT_NAME} ${source_files})
ELSE(WIN32)
ADD_EXECUTABLE(${PROJECT_NAME} ${source_files})
ENDIF(WIN32)
INCLUDE("FindOpenViBE")
INCLUDE("FindOpenViBECommon")
......@@ -22,6 +27,9 @@ INCLUDE("FindOpenViBEModuleXML")
INCLUDE("FindOpenViBEModuleEBML")
INCLUDE("FindOpenViBEModuleFS")
INCLUDE("FindThirdPartyGTK")
INCLUDE("FindThirdPartyBoost")
INCLUDE("FindThirdPartyBoost_Thread")
INCLUDE("FindThirdPartyEigen")
# ---------------------------------
# Target macros
......
......@@ -5,6 +5,8 @@
#include <openvibe/ovITimeArithmetics.h>
#include <boost/thread.hpp>
#define OVD_GUI_File OpenViBE::Directories::getDataDir() + "/applications/designer/interface.ui"
using namespace OpenViBE;
......
......@@ -16,6 +16,14 @@
#include "ovdCInterfacedScenario.h"
#include "ovdCApplication.h"
#if defined(TARGET_OS_Windows) && defined(TEST_NO_CONSOLE)
// #include <Windows.h>
// msvcrt
// extern int __cdecl __getmainargs( int *argc, char ***argv, char ***envp,
// int expand_wildcards, int *new_mode );
#endif
using namespace OpenViBE;
using namespace OpenViBE::Kernel;
using namespace OpenViBE::Plugins;
......@@ -24,6 +32,10 @@ using namespace std;
map<uint32, ::GdkColor> g_vColors;
#if TARGET_HAS_ThirdPartyEIGEN
#include <Eigen/Core>
#endif
class CPluginObjectDescEnum
{
public:
......@@ -37,7 +49,7 @@ public:
{
}
virtual boolean enumeratePluginObjectDesc(void)
virtual OpenViBE::boolean enumeratePluginObjectDesc(void)
{
CIdentifier l_oIdentifier;
while((l_oIdentifier=m_rKernelContext.getPluginManager().getNextPluginObjectDescIdentifier(l_oIdentifier))!=OV_UndefinedIdentifier)
......@@ -47,7 +59,7 @@ public:
return true;
}
virtual boolean enumeratePluginObjectDesc(
virtual OpenViBE::boolean enumeratePluginObjectDesc(
const CIdentifier& rParentClassIdentifier)
{
CIdentifier l_oIdentifier;
......@@ -58,7 +70,7 @@ public:
return true;
}
virtual boolean callback(
virtual OpenViBE::boolean callback(
const IPluginObjectDesc& rPluginObjectDesc)=0;
protected:
......@@ -79,7 +91,7 @@ public:
{
}
virtual boolean callback(
virtual OpenViBE::boolean callback(
const IPluginObjectDesc& rPluginObjectDesc)
{
string l_sFullName=string(rPluginObjectDesc.getCategory())+"/"+string(rPluginObjectDesc.getName());
......@@ -115,7 +127,7 @@ public:
{
}
virtual boolean callback(
virtual OpenViBE::boolean callback(
const IPluginObjectDesc& rPluginObjectDesc)
{
// Outputs plugin info to console
......@@ -150,7 +162,7 @@ static void insertPluginObjectDesc_to_GtkTreeStore(const IKernelContext& rKernel
l_sStockItemName=l_pBoxAlgorithmDesc->getStockItemName();
}
boolean l_bShouldShow=true;
OpenViBE::boolean l_bShouldShow=true;
if (rKernelContext.getPluginManager().isPluginObjectFlaggedAsDeprecated(l_pPluginObjectDesc->getCreatedClass())
&& !rKernelContext.getConfigurationManager().expandAsBoolean("${Designer_ShowDeprecated}", false))
......@@ -160,7 +172,7 @@ static void insertPluginObjectDesc_to_GtkTreeStore(const IKernelContext& rKernel
/*
if (rKernelContext.getPluginManager().isPluginObjectFlaggedAsUnstable(l_pPluginObjectDesc->getCreatedClass())
&& !rKernelContext.getConfigurationManager().expandAsBoolean("${Designer_ShowUnstable}", false))
&& !rKernelContext.getConfigurationManager().expandAsOpenViBE::boolean("${Designer_ShowUnstable}", false))
{
l_bShouldShow=false;
}
......@@ -200,8 +212,8 @@ static void insertPluginObjectDesc_to_GtkTreeStore(const IKernelContext& rKernel
::GtkTreeIter* l_pGtkIterChild=&l_oGtkIter1;
for(it=l_vCategory.begin(); it!=l_vCategory.end(); it++)
{
boolean l_bFound=false;
boolean l_bValid=gtk_tree_model_iter_children(
OpenViBE::boolean l_bFound=false;
OpenViBE::boolean l_bValid=gtk_tree_model_iter_children(
GTK_TREE_MODEL(pTreeStore),
l_pGtkIterChild,
l_pGtkIterParent)?true:false;
......@@ -299,7 +311,7 @@ typedef struct _SConfiguration
} SConfiguration;
boolean parse_arguments(int argc, char** argv, SConfiguration& rConfiguration)
OpenViBE::boolean parse_arguments(int argc, char** argv, SConfiguration& rConfiguration)
{
SConfiguration l_oConfiguration;
......@@ -408,7 +420,7 @@ boolean parse_arguments(int argc, char** argv, SConfiguration& rConfiguration)
int go(int argc, char ** argv)
{
boolean errorWhileLoadingScenario = false;
OpenViBE::boolean errorWhileLoadingScenario = false;
/*
{ 0, 0, 0, 0 },
{ 0, 16383, 16383, 16383 },
......@@ -543,7 +555,16 @@ int go(int argc, char ** argv)
setlocale( LC_ALL, l_sLocale.toASCIIString() );
//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();
gdk_threads_enter();
gtk_init(&argc, &argv);
// gtk_rc_parse(OpenViBE::Directories::getDataDir() + "/applications/designer/interface.gtkrc");
#ifdef TARGET_OS_Linux
......@@ -572,7 +593,7 @@ int go(int argc, char ** argv)
::CApplication app(*l_pKernelContext);
app.initialize(l_oConfiguration.getFlags());
// FIXME is it necessary to keep next line uncomment ?
//boolean l_bIsScreenValid=true;
//OpenViBE::boolean l_bIsScreenValid=true;
if(!l_oConfiguration.m_eNoCheckColorDepth)
{
if(GDK_IS_DRAWABLE(GTK_WIDGET(app.m_pMainWindow)->window))
......@@ -657,6 +678,8 @@ int go(int argc, char ** argv)
}
}
gdk_threads_leave();
l_rLogManager << LogLevel_Info << "Application terminated, releasing allocated objects\n";
OpenViBEToolkit::uninitialize(*l_pKernelContext);
......@@ -675,8 +698,61 @@ int go(int argc, char ** argv)
return 0;
}
#if defined(TARGET_OS_Windows) && defined(TEST_NO_CONSOLE)
int __stdcall WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int cmdShow)
{
int argc = -1;
char **argv = NULL;
char **env = NULL;
int start_info = 0;
__getmainargs(&argc, &argv, &env, 0, &start_info);
int l_iRet=-1;
try
{
l_iRet=go(argc, argv);
}
catch (...)
{
std::cout << "Caught an exception at the very top...\nLeaving application!\n";
}
return l_iRet;
}
#else
int main(int argc, char ** argv)
{
#if defined(TARGET_OS_Windows) && defined(TEST_NO_CONSOLE)
// FreeConsole();
#endif
#if defined(TARGET_HAS_ThirdPartyEIGEN)
#if (EIGEN_WORLD_VERSION >= 3) && (EIGEN_MAJOR_VERSION >= 2)
Eigen::initParallel();
// Eigen::setNbThreads(4);
// std::cout << "Eigen: I'm using " << Eigen::nbThreads() << " threads\n";
#endif
#if DEBUG
#ifdef EIGEN_VECTORIZE
std::cout << "Eigen: Vectorization is compiled\n";
#else
std::cout << "Eigen: Vectorization is NOT compiled\n";
#ifdef EIGEN_DONT_VECTORIZE
std::cout << "Eigen: (DONT_VECTORIZE is on)\n";
#endif
#endif
#endif
#endif
int l_iRet=-1;
try
{
......@@ -688,3 +764,5 @@ int main(int argc, char ** argv)
}
return l_iRet;
}
#endif
\ No newline at end of file
# Add all the subdirs as projects of the named branch
OV_ADD_PROJECTS("PLUGINS")
OV_ADD_PROJECTS("CONTRIB")
......@@ -6,6 +6,8 @@
#include <vector>
#include <map>
#include <boost/thread.hpp>
namespace OpenViBE
{
namespace Kernel
......@@ -50,10 +52,15 @@ namespace OpenViBE
_IsDerivedFromClass_Final_(OpenViBE::Kernel::TKernelObject<OpenViBE::Kernel::ILogManager>, OVK_ClassId_Kernel_Log_LogManager);
boost::mutex m_oMutex;
protected:
template <class T> void logForEach(T tValue)
{
// @fixme we need to create a buffer per thread (caller) and then on EOL, lock();flush buffer();unlock()
boost::mutex::scoped_lock lock(m_oMutex);
if(m_eCurrentLogLevel!=LogLevel_None && this->isActive(m_eCurrentLogLevel))
{
std::vector<OpenViBE::Kernel::ILogListener*>::iterator i;
......
......@@ -38,9 +38,7 @@ public:
OpenViBE::boolean m_bIsParsingSettingOverride;
OpenViBE::Kernel::IConfigurationManager* m_pConfigurationManager;
#undef boolean
_IsDerivedFromClass_Final_(OpenViBE::IObjectVisitor, OV_UndefinedIdentifier);
#define boolean OpenViBE::boolean
};
#endif
\ No newline at end of file
......@@ -3,6 +3,7 @@
#include "../ovkTKernelObject.h"
#include "ovkCScheduler.h"
#include "ovkCSchedulerMulticore.h"
#include "../ovkCKernelContext.h"
......@@ -48,7 +49,9 @@ namespace OpenViBE
OpenViBE::Kernel::CKernelContextBridge m_oKernelContextBridge;
OpenViBE::Kernel::IConfigurationManager* m_pLocalConfigurationManager;
OpenViBE::Kernel::CScheduler m_oScheduler;
// For now, switch between these to change the schedulers
// OpenViBE::Kernel::CScheduler m_oScheduler;
OpenViBE::Kernel::CSchedulerMulticore m_oScheduler;
OpenViBE::uint64 m_ui64CurrentTimeToReach;
OpenViBE::uint64 m_ui64Lateness;
......
......@@ -44,7 +44,7 @@ namespace OpenViBE
virtual OpenViBE::uint64 getFrequency(void) const;
virtual OpenViBE::float64 getCPUUsage(void) const;
bool sendMessage(const IMessageWithData &msg, CIdentifier targetBox, uint32 inputIndex);
virtual OpenViBE::boolean sendMessage(const IMessageWithData &msg, CIdentifier targetBox, uint32 inputIndex);
_IsDerivedFromClass_Final_(OpenViBE::Kernel::TKernelObject < OpenViBE::Kernel::IKernelObject >, OVK_ClassId_Kernel_Player_Scheduler);
......
......@@ -5,6 +5,11 @@
#include <map>
#include <list>
#include <deque>
#include <boost/thread.hpp>
#include <boost/thread/condition.hpp>
#include <boost/version.hpp>
namespace OpenViBE
{
......@@ -14,6 +19,110 @@ namespace OpenViBE
class CChunk;
class CPlayer;
// typedef std::pair<boolean (*)(void*), void*> jobInfo;
typedef boost::function<void()> jobCall;
class JobContext {
public:
JobContext() : m_ui32JobsPending(0), m_bQuit(false) { };
boost::mutex m_oJobMutex;
// boost::mutex m_oJobsPendingMutex;
std::deque<jobCall> m_vJobList;
// std::deque<jobInfo> m_vJobList;
OpenViBE::uint32 m_ui32JobsPending;
boost::condition_variable m_oHaveWork;
boost::condition_variable m_oJobDone;
OpenViBE::boolean m_bQuit;
};
class CWorkerThread {
public:
CWorkerThread(JobContext& ctx) : m_ctx(ctx) { };
JobContext& m_ctx;
// void operator()(void)
void run(void)
{
while(true)
{
jobCall job;
// jobInfo job((boolean (*)(void*))NULL,(void*)NULL);
// Wait until we get a job or are told to quit
{ // scope for lock
boost::unique_lock<boost::mutex> lock(m_ctx.m_oJobMutex);
while(!m_ctx.m_bQuit && m_ctx.m_vJobList.size()==0)
{
m_ctx.m_oHaveWork.wait(lock);
}
if(m_ctx.m_bQuit) {
return;
}
// Ok, we have a job
job = m_ctx.m_vJobList.front();
m_ctx.m_vJobList.pop_front();
}
// do job
// std::cout << "Hello " << job << " ( " << boost::this_thread::get_id() << ")\n";
// std::cout << "Thread " << boost::this_thread::get_id() << " enter job\n";
// @todo pass job failed to caller
job();
// (*job.first)(job.second);
// std::cout << "Thread " << boost::this_thread::get_id() << " exit job\n";
// job done, mark as done
{ // scope for lock
boost::unique_lock<boost::mutex> lock(m_ctx.m_oJobMutex);
m_ctx.m_ui32JobsPending--;
}
m_ctx.m_oJobDone.notify_one();
}
}
static void startWorkerThread(CWorkerThread* pThread)
{
pThread->run();
// (*pThread)();
}
};
class parallelExecutor
{
public:
parallelExecutor() { };
boolean initialize(const uint32 nThreads);
boolean push(const jobCall& someJob); // add job, pass to threads
boolean pushList(const std::deque<jobCall>& vJobList); // add jobs
boolean waitForAll(void); // wait until all pushed jobs are done
boolean uninitialize();
private:
JobContext m_oJobContext;
std::vector<CWorkerThread*> m_vWorkerThread;
std::vector<boost::thread*> m_vThread;
};
class CSchedulerMulticore : public OpenViBE::Kernel::CScheduler
{
public:
......@@ -36,7 +145,10 @@ namespace OpenViBE
virtual OpenViBE::uint64 getFrequency(void) const;
virtual OpenViBE::float64 getCPUUsage(void) const;
bool sendMessage(const IMessageWithData &msg, CIdentifier targetBox, uint32 inputIndex);
virtual OpenViBE::boolean sendMessage(const IMessageWithData &msg, CIdentifier targetBox, uint32 inputIndex);
static OpenViBE::boolean job(CSchedulerMulticore *context, CIdentifier id, CSimulatedBox* box);
OpenViBE::boolean runBox(CIdentifier id, CSimulatedBox* box);
_IsDerivedFromClass_Final_(OpenViBE::Kernel::TKernelObject < OpenViBE::Kernel::IKernelObject >, OVK_ClassId_Kernel_Player_Scheduler);
......@@ -54,10 +166,12 @@ namespace OpenViBE
OpenViBE::uint64 m_ui64Frequency;
OpenViBE::uint64 m_ui64CurrentTime;
OpenViBE::boolean m_bIsInitialized;
OpenViBE::Kernel::parallelExecutor m_oExecutor;
std::map < std::pair < OpenViBE::int32, OpenViBE::CIdentifier>, OpenViBE::Kernel::CSimulatedBox* > m_vSimulatedBox;
std::map < OpenViBE::CIdentifier, System::CChrono > m_vSimulatedBoxChrono;
std::map < OpenViBE::CIdentifier, std::map < OpenViBE::uint32, std::list < OpenViBE::Kernel::CChunk > > > m_vSimulatedBoxInput;
std::map < OpenViBE::CIdentifier, boost::mutex* > m_vSimulatedBoxInputMutex;
private:
......
......@@ -898,6 +898,16 @@ boolean CSimulatedBox::getBoxIdentifier(CIdentifier& rBoxIdentifier)
return true;
}
boolean CSimulatedBox::getBoxAlgorithmClassIdentifier(CIdentifier& rIdentifier)
{
if(m_pBox == NULL)
{
return false;
}
rIdentifier = m_pBox->getAlgorithmClassIdentifier();
return true;
}
boolean CSimulatedBox::setBoxIdentifier(const CIdentifier& rBoxIdentifier)
{
if(!m_pScenario)
......
......@@ -121,6 +121,9 @@ namespace OpenViBE
virtual OpenViBE::boolean setBoxIdentifier(
const OpenViBE::CIdentifier& rBoxIdentifier);
virtual OpenViBE::boolean getBoxAlgorithmClassIdentifier(
OpenViBE::CIdentifier& rIdentifier);
virtual OpenViBE::boolean initialize(void);
virtual OpenViBE::boolean uninitialize(void);
......@@ -332,7 +335,7 @@ namespace OpenViBE
std::vector< OpenViBE::Kernel::CMessageWithData* > m_vPreparedMessages;
OpenViBE::boolean m_bIsReceivingMessage;
public:
private:
std::vector < std::deque < OpenViBE::Kernel::CChunk > > m_vInput;
std::vector < std::deque < OpenViBE::Kernel::CChunk > > m_vOutput;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment