From 74fda9ff851e32b8e6bb2de0f9668b10f06a0e60 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Fri, 21 Aug 2015 15:18:18 -0700 Subject: [PATCH] simple multi threading test --- examples/ExampleBrowser/CMakeLists.txt | 5 +- examples/ExampleBrowser/ExampleEntries.cpp | 5 +- examples/ExampleBrowser/premake4.lua | 4 + .../MultiThreading/MultiThreadingExample.cpp | 325 ++++++++++++++++++ .../MultiThreading/MultiThreadingExample.h | 11 + .../MultiThreading/b3PosixThreadSupport.cpp | 22 +- .../MultiThreading/b3PosixThreadSupport.h | 2 +- .../MultiThreading/b3ThreadSupportInterface.h | 2 +- .../MultiThreading/b3Win32ThreadSupport.cpp | 3 + examples/MultiThreading/main.cpp | 6 +- 10 files changed, 374 insertions(+), 11 deletions(-) create mode 100644 examples/MultiThreading/MultiThreadingExample.cpp create mode 100644 examples/MultiThreading/MultiThreadingExample.h diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index 2074ef722..dc0fb873b 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -45,7 +45,10 @@ SET(App_ExampleBrowser_SRCS ../FractureDemo/btFractureDynamicsWorld.h ../DynamicControlDemo/MotorDemo.cpp ../DynamicControlDemo/MotorDemo.h - + ../MultiThreading/MultiThreadingExample.cpp + ../MultiThreading/b3PosixThreadSupport.cpp + ../MultiThreading/b3Win32ThreadSupport.cpp + ../MultiThreading/b3ThreadSupportInterface.cpp ../RenderingExamples/TimeSeriesCanvas.cpp ../RenderingExamples/TimeSeriesCanvas.h ../RenderingExamples/TimeSeriesFontData.cpp diff --git a/examples/ExampleBrowser/ExampleEntries.cpp b/examples/ExampleBrowser/ExampleEntries.cpp index edef28e17..a3a550062 100644 --- a/examples/ExampleBrowser/ExampleEntries.cpp +++ b/examples/ExampleBrowser/ExampleEntries.cpp @@ -40,7 +40,7 @@ #include "../RenderingExamples/TimeSeriesExample.h" #include "../Tutorial/Tutorial.h" #include "../Tutorial/Dof6ConstraintTutorial.h" - +#include "../MultiThreading/MultiThreadingExample.h" #ifdef ENABLE_LUA #include "../LuaDemo/LuaPhysicsSetup.h" #endif @@ -216,6 +216,9 @@ static ExampleEntry gDefaultExamples[]= ExampleEntry(1,"Lua Script", "Create the dynamics world, collision shapes and rigid bodies using Lua scripting", LuaDemoCreateFunc), #endif + ExampleEntry(1,"MultiThreading (submitJob)", "Simple example of executing jobs across multiple threads.", + MultiThreadingExampleCreateFunc,SINGLE_SIM_THREAD), + ExampleEntry(1,"Voronoi Fracture", "Automatically create a compound rigid body using voronoi tesselation. Individual parts are modeled as rigid bodies using a btConvexHullShape.", VoronoiFractureCreateFunc), diff --git a/examples/ExampleBrowser/premake4.lua b/examples/ExampleBrowser/premake4.lua index f872babe7..fb650075c 100644 --- a/examples/ExampleBrowser/premake4.lua +++ b/examples/ExampleBrowser/premake4.lua @@ -61,6 +61,10 @@ "../SharedMemory/PhysicsClient.cpp", "../SharedMemory/PosixSharedMemory.cpp", "../SharedMemory/Win32SharedMemory.cpp", + "../MultiThreading/MultiThreadingExample.cpp", + "../MultiThreading/b3PosixThreadSupport.cpp", + "../MultiThreading/b3Win32ThreadSupport.cpp", + "../MultiThreading/b3ThreadSupportInterface.cpp", "../BasicDemo/BasicExample.*", "../Tutorial/*", "../Benchmarks/*", diff --git a/examples/MultiThreading/MultiThreadingExample.cpp b/examples/MultiThreading/MultiThreadingExample.cpp new file mode 100644 index 000000000..0cf47c529 --- /dev/null +++ b/examples/MultiThreading/MultiThreadingExample.cpp @@ -0,0 +1,325 @@ + +#include "MultiThreadingExample.h" +#include "../CommonInterfaces/CommonGraphicsAppInterface.h" +#include "../CommonInterfaces/CommonRenderInterface.h" + +#include "../CommonInterfaces/CommonExampleInterface.h" +#include "LinearMath/btTransform.h" + +#include "../CommonInterfaces/CommonGUIHelperInterface.h" +#include "../RenderingExamples/TimeSeriesCanvas.h" +#include "stb_image/stb_image.h" +#include "Bullet3Common/b3Quaternion.h" +#include "Bullet3Common/b3Matrix3x3.h" +#include "../CommonInterfaces/CommonParameterInterface.h" + +#include "LinearMath/btAlignedObjectArray.h" +#define stdvector btAlignedObjectArray + +#define MAGIC_RESET_NUMBER 64738 + +void SampleThreadFunc(void* userPtr,void* lsMemory); +void* SamplelsMemoryFunc(); + + +#include +//#include "BulletMultiThreaded/PlatformDefinitions.h" + +#ifndef _WIN32 +#include "b3PosixThreadSupport.h" + +b3ThreadSupportInterface* createThreadSupport(int numThreads) +{ + b3PosixThreadSupport::ThreadConstructionInfo constructionInfo("testThreads", + SampleThreadFunc, + SamplelsMemoryFunc, + numThreads); + b3ThreadSupportInterface* threadSupport = new b3PosixThreadSupport(constructionInfo); + + return threadSupport; + +} + + +#elif defined( _WIN32) +#include "b3Win32ThreadSupport.h" + +b3ThreadSupportInterface* createThreadSupport(int numThreads) +{ + b3Win32ThreadSupport::Win32ThreadConstructionInfo threadConstructionInfo("testThreads",SampleThreadFunc,SamplelsMemoryFunc,numThreads); + b3Win32ThreadSupport* threadSupport = new b3Win32ThreadSupport(threadConstructionInfo); + return threadSupport; + +} +#endif + +struct SampleJobInterface +{ + virtual void executeJob(int threadIndex)=0; +}; + +struct SampleJob1 : public SampleJobInterface +{ + float m_fakeWork; + int m_jobId; + + SampleJob1(int jobId) + :m_fakeWork(0), + m_jobId(jobId) + { + } + virtual void executeJob(int threadIndex) + { + printf("start SampleJob1 %d using threadIndex %d\n",m_jobId,threadIndex); + //do some fake work + for (int i=0;i<1000000;i++) + m_fakeWork = b3Scalar(1.21)*m_fakeWork; + printf("finished SampleJob1 %d using threadIndex %d\n",m_jobId,threadIndex); + } +}; + + +struct SampleArgs +{ + SampleArgs() + { + } + b3CriticalSection* m_cs; + + btAlignedObjectArray m_jobQueue; + + void submitJob(SampleJobInterface* job) + { + m_cs->lock(); + m_jobQueue.push_back(job); + m_cs->unlock(); + } + SampleJobInterface* consumeJob() + { + SampleJobInterface* job = 0; + m_cs->lock(); + int sz = m_jobQueue.size(); + if (sz) + { + job = m_jobQueue[sz-1]; + m_jobQueue.pop_back(); + } + m_cs->unlock(); + return job; + } +}; +SampleArgs args; +struct SampleThreadLocalStorage +{ + int threadId; +}; + + +void SampleThreadFunc(void* userPtr,void* lsMemory) +{ + printf("thread started\n"); + + SampleThreadLocalStorage* localStorage = (SampleThreadLocalStorage*) lsMemory; + + SampleArgs* args = (SampleArgs*) userPtr; + + bool requestExit = false; + while (!requestExit) + { + SampleJobInterface* job = args->consumeJob(); + if (job) + { + job->executeJob(localStorage->threadId); + } + + args->m_cs->lock(); + int exitMagicNumber = args->m_cs->getSharedParam(1); + requestExit = (exitMagicNumber==MAGIC_RESET_NUMBER); + args->m_cs->unlock(); + + } + + printf("finished\n"); + //do nothing +} + + +void* SamplelsMemoryFunc() +{ + //don't create local store memory, just return 0 + return new SampleThreadLocalStorage; +} + + + + + + +class MultiThreadingExample : public CommonExampleInterface +{ + CommonGraphicsApp* m_app; + GUIHelperInterface* m_guiHelper; + int m_exampleIndex; + b3ThreadSupportInterface* m_threadSupport; + btAlignedObjectArray m_jobs; + int m_numThreads; +public: + + MultiThreadingExample(GUIHelperInterface* guiHelper, int tutorialIndex) + :m_app(guiHelper->getAppInterface()), + m_guiHelper(guiHelper), + m_exampleIndex(tutorialIndex), + m_threadSupport(0), + m_numThreads(8) + { + int numBodies = 1; + + m_app->setUpAxis(1); + m_app->m_renderer->enableBlend(true); + + } + virtual ~MultiThreadingExample() + { + + + m_app->m_renderer->enableBlend(false); + } + + + virtual void renderScene() + { +} + virtual void initPhysics() + { + b3Printf("initPhysics"); + + + + m_threadSupport = createThreadSupport(m_numThreads); + + + + for (int i=0;igetNumTasks();i++) + { + SampleThreadLocalStorage* storage = (SampleThreadLocalStorage*)m_threadSupport->getThreadLocalMemory(i); + b3Assert(storage); + storage->threadId = i; + } + + + + args.m_cs = m_threadSupport->createCriticalSection(); + args.m_cs->setSharedParam(0,100); + + for (int i=0;i<100;i++) + { + SampleJob1* job = new SampleJob1(i); + args.submitJob(job); + } + + + int i; + for (i=0;irunTask(B3_THREAD_SCHEDULE_TASK, (void*) &args, i); + } + b3Printf("Threads started"); + + } + virtual void exitPhysics() + { + b3Printf("exitPhysics, stopping threads"); + bool blockingWait =false; + int arg0,arg1; + + args.m_cs->lock(); + //terminate all threads + args.m_cs->setSharedParam(1,MAGIC_RESET_NUMBER); + args.m_cs->unlock(); + + if (blockingWait) + { + for (int i=0;iwaitForResponse(&arg0,&arg1); + printf("finished waiting for response: %d %d\n", arg0,arg1); + } + } else + { + int numActiveThreads = m_numThreads; + while (numActiveThreads) + { + if (m_threadSupport->isTaskCompleted(&arg0,&arg1,0)) + { + numActiveThreads--; + printf("numActiveThreads = %d\n",numActiveThreads); + + } else + { + // printf("polling.."); + } + }; + } + + delete m_threadSupport; + + b3Printf("Threads stopped"); + for (int i=0;im_renderer && m_app->m_renderer->getActiveCamera()) + { + m_app->m_renderer->getActiveCamera()->setCameraDistance(dist); + m_app->m_renderer->getActiveCamera()->setCameraPitch(pitch); + m_app->m_renderer->getActiveCamera()->setCameraYaw(yaw); + m_app->m_renderer->getActiveCamera()->setCameraTargetPosition(targetPos[0],targetPos[1],targetPos[2]); + } + } +}; + + + +class CommonExampleInterface* MultiThreadingExampleCreateFunc(struct CommonExampleOptions& options) +{ + return new MultiThreadingExample(options.m_guiHelper, options.m_option); +} + diff --git a/examples/MultiThreading/MultiThreadingExample.h b/examples/MultiThreading/MultiThreadingExample.h new file mode 100644 index 000000000..c748fa3be --- /dev/null +++ b/examples/MultiThreading/MultiThreadingExample.h @@ -0,0 +1,11 @@ +#ifndef MULTI_THREADING_EXAMPLE_H +#define MULTI_THREADING_EXAMPLE_H + +enum EnumMultiThreadingExampleTypes +{ + SINGLE_SIM_THREAD=0, +}; + +class CommonExampleInterface* MultiThreadingExampleCreateFunc(struct CommonExampleOptions& options); + +#endif //MULTI_THREADING_EXAMPLE_H diff --git a/examples/MultiThreading/b3PosixThreadSupport.cpp b/examples/MultiThreading/b3PosixThreadSupport.cpp index 705e297ce..74cdfaba2 100644 --- a/examples/MultiThreading/b3PosixThreadSupport.cpp +++ b/examples/MultiThreading/b3PosixThreadSupport.cpp @@ -1,3 +1,4 @@ +#ifndef _WIN32 /* Bullet Continuous Collision Detection and Physics Library Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com @@ -117,7 +118,7 @@ static void *threadFunction(void *argument) } ///send messages to SPUs -void b3PosixThreadSupport::sendRequest(int uiCommand, void* uiArgument0, int taskId) +void b3PosixThreadSupport::runTask(int uiCommand, void* uiArgument0, int taskId) { /// gMidphaseSPU.sendRequest(CMD_GATHER_AND_PROCESS_PAIRLIST, (int) &taskDesc); @@ -302,11 +303,24 @@ public: virtual unsigned int getSharedParam(int i) { - return mCommonBuff[i]; + if (i<32) + { + return mCommonBuff[i]; + } else + { + b3Assert(0); + } + return 0; } virtual void setSharedParam(int i,unsigned int p) { - mCommonBuff[i] = p; + if (i<32) + { + mCommonBuff[i] = p; + } else + { + b3Assert(0); + } } virtual void lock() @@ -433,4 +447,4 @@ void b3PosixThreadSupport::deleteCriticalSection(b3CriticalSection* cs) { delete cs; } - +#endif //_WIN32 diff --git a/examples/MultiThreading/b3PosixThreadSupport.h b/examples/MultiThreading/b3PosixThreadSupport.h index 17dde8d60..ae23dd610 100644 --- a/examples/MultiThreading/b3PosixThreadSupport.h +++ b/examples/MultiThreading/b3PosixThreadSupport.h @@ -103,7 +103,7 @@ public: void startThreads(ThreadConstructionInfo& threadInfo); - virtual void sendRequest(int uiCommand, void* uiArgument0, int uiArgument1); + virtual void runTask(int uiCommand, void* uiArgument0, int uiArgument1); virtual void waitForResponse(int *puiArgument0, int *puiArgument1); diff --git a/examples/MultiThreading/b3ThreadSupportInterface.h b/examples/MultiThreading/b3ThreadSupportInterface.h index d53209abd..c24ae1b72 100644 --- a/examples/MultiThreading/b3ThreadSupportInterface.h +++ b/examples/MultiThreading/b3ThreadSupportInterface.h @@ -57,7 +57,7 @@ public: virtual ~b3ThreadSupportInterface(); - virtual void sendRequest(int uiCommand, void* uiArgument0, int uiArgument1) =0; + virtual void runTask(int uiCommand, void* uiArgument0, int uiArgument1) =0; virtual void waitForResponse(int *puiArgument0, int *puiArgument1) =0; diff --git a/examples/MultiThreading/b3Win32ThreadSupport.cpp b/examples/MultiThreading/b3Win32ThreadSupport.cpp index 7eae9b1a3..e80b616f4 100644 --- a/examples/MultiThreading/b3Win32ThreadSupport.cpp +++ b/examples/MultiThreading/b3Win32ThreadSupport.cpp @@ -1,3 +1,4 @@ +#ifdef _WIN32 /* Bullet Continuous Collision Detection and Physics Library Copyright (c) 2003-2007 Erwin Coumans http://bulletphysics.com @@ -452,3 +453,5 @@ void b3Win32ThreadSupport::deleteCriticalSection(b3CriticalSection* criticalSect +#endif //_WIN32 + diff --git a/examples/MultiThreading/main.cpp b/examples/MultiThreading/main.cpp index 7d39e5e54..7b520b9fc 100644 --- a/examples/MultiThreading/main.cpp +++ b/examples/MultiThreading/main.cpp @@ -140,7 +140,7 @@ int main(int argc,char** argv) int i; for (i=0;isendRequest(B3_THREAD_SCHEDULE_TASK, (void*) &args, i); + threadSupport->runTask(B3_THREAD_SCHEDULE_TASK, (void*) &args, i); } bool blockingWait =false; @@ -168,10 +168,10 @@ int main(int argc,char** argv) }; } -printf("stopping threads\n"); + printf("stopping threads\n"); delete threadSupport; printf("Press ENTER to quit\n"); - getchar(); + //getchar(); return 0; }