diff --git a/newton-4.00/sdk/dCollision/ndScene.cpp b/newton-4.00/sdk/dCollision/ndScene.cpp index 3ed4450bb..12a97e8b4 100644 --- a/newton-4.00/sdk/dCollision/ndScene.cpp +++ b/newton-4.00/sdk/dCollision/ndScene.cpp @@ -46,7 +46,8 @@ ndVector ndScene::m_angularContactError2(D_CONTACT_ANGULAR_ERROR * D_CONTACT_ANG ndVector ndScene::m_linearContactError2(D_CONTACT_TRANSLATION_ERROR * D_CONTACT_TRANSLATION_ERROR); ndScene::ndScene() - :ndThreadPool("newtonWorker") + :ndClassAlloc() + ,ndThreadPool("newtonWorker") ,m_bodyList() ,m_particleSetList() ,m_contactArray() @@ -77,7 +78,8 @@ ndScene::ndScene() } ndScene::ndScene(const ndScene& src) - :ndThreadPool("newtonWorker") + :ndClassAlloc() + ,ndThreadPool("newtonWorker") ,m_bodyList(src.m_bodyList) ,m_particleSetList() ,m_contactArray(src.m_contactArray) diff --git a/newton-4.00/sdk/dCollision/ndScene.h b/newton-4.00/sdk/dCollision/ndScene.h index c2f6b2429..0c5e437b8 100644 --- a/newton-4.00/sdk/dCollision/ndScene.h +++ b/newton-4.00/sdk/dCollision/ndScene.h @@ -55,7 +55,7 @@ class ndSceneTreeNotiFy : public ndClassAlloc } D_GCC_NEWTON_ALIGN_32; D_MSV_NEWTON_ALIGN_32 -class ndScene : public ndThreadPool +class ndScene : public ndClassAlloc, public ndThreadPool { protected: class ndContactPairs diff --git a/newton-4.00/sdk/dCollision/ndShapeCompound.cpp b/newton-4.00/sdk/dCollision/ndShapeCompound.cpp index de34d631d..1dab21edf 100644 --- a/newton-4.00/sdk/dCollision/ndShapeCompound.cpp +++ b/newton-4.00/sdk/dCollision/ndShapeCompound.cpp @@ -249,7 +249,6 @@ void ndShapeCompound::ndTreeArray::AddNode(ndNodeBase* const node, ndInt32 index { ndTreeArray::ndNode* const myNode = Insert(node, index); node->m_myNode = myNode; - //node->m_shapeInstance->m_parent____ = parent; node->m_shapeInstance->m_subCollisionHandle = myNode; } @@ -260,7 +259,6 @@ ndShapeCompound::ndShapeCompound() ,m_boxMinRadius(ndFloat32(0.0f)) ,m_boxMaxRadius(ndFloat32(0.0f)) ,m_root(nullptr) - //,m_ownerInstance(nullptr) ,m_idIndex(0) { } @@ -272,7 +270,6 @@ ndShapeCompound::ndShapeCompound(const ndShapeCompound& source) ,m_boxMinRadius(ndFloat32(0.0f)) ,m_boxMaxRadius(ndFloat32(0.0f)) ,m_root(nullptr) - //,m_ownerInstance(m_ownerInstance) ,m_idIndex(0) { ndTreeArray::Iterator iter(source.m_array); diff --git a/newton-4.00/sdk/dCore/ndThread.cpp b/newton-4.00/sdk/dCore/ndThread.cpp index 90ed728d0..403a6e8b6 100644 --- a/newton-4.00/sdk/dCore/ndThread.cpp +++ b/newton-4.00/sdk/dCore/ndThread.cpp @@ -31,17 +31,26 @@ #pragma warning( disable : 4355) #endif -ndThread::ndThread() +ndThreadInterface::ndThreadInterface() :ndClassAlloc() - ,ndThreadName() ,ndSemaphore() +{ +} + +ndThreadInterface::~ndThreadInterface() +{ +} + + +ndThread::ndThread() + :ndThreadInterface() #ifndef D_USE_THREAD_EMULATION ,ndAtomic(true) ,std::condition_variable() ,std::thread(&ndThread::ThreadFunctionCallback, this) #endif { - strcpy (m_name, "newtonWorker"); + strcpy (m_name.m_name, "newtonWorker"); #ifndef D_USE_THREAD_EMULATION store(false); #endif @@ -57,7 +66,7 @@ ndThread::~ndThread() void ndThread::SetName(const char* const name) { - strncpy(m_name, name, sizeof(m_name) - 1); + strncpy(m_name.m_name, name, sizeof(m_name) - 1); #if defined(_MSC_VER) && !defined (D_USE_THREAD_EMULATION) // a hideous way to set the thread name, bu this is how Microsoft does it const DWORD MS_VC_EXCEPTION = 0x406D1388; @@ -103,6 +112,10 @@ void ndThread::Signal() #endif } +void ndThread::Release() +{ +} + void ndThread::ThreadFunctionCallback() { #ifndef D_USE_THREAD_EMULATION diff --git a/newton-4.00/sdk/dCore/ndThread.h b/newton-4.00/sdk/dCore/ndThread.h index 61c1fc463..0e9b0b0ee 100644 --- a/newton-4.00/sdk/dCore/ndThread.h +++ b/newton-4.00/sdk/dCore/ndThread.h @@ -36,11 +36,25 @@ class ndThreadName char m_name[32]; }; +class ndThreadInterface: public ndClassAlloc, public ndSemaphore +{ + public: + D_CORE_API ndThreadInterface(); + D_CORE_API virtual ~ndThreadInterface(); + + virtual void Signal() = 0; + virtual void Finish() = 0; + virtual void Release() = 0; + virtual void ThreadFunction() = 0; + virtual void ThreadFunctionCallback() = 0; + virtual void SetName(const char* const name) = 0; + + ndThreadName m_name; +}; + /// Base class for for all multi thread functionality. class ndThread - :public ndClassAlloc - ,public ndThreadName - ,public ndSemaphore + :public ndThreadInterface #ifndef D_USE_THREAD_EMULATION ,public ndAtomic ,public std::condition_variable @@ -58,27 +72,25 @@ class ndThread /// Set thread name. /// Useful for when debugging or profiler and application. - D_CORE_API void SetName(const char* const name); + D_CORE_API virtual void SetName(const char* const name) override; /// Set the thread, to execute one call to and go back to a wait state - D_CORE_API void Signal(); + D_CORE_API virtual void Signal() override; /// Force the thread loop to terminate. /// This function must be call explicitly when the application /// wants to terminate the thread because the destructor does not do it. - D_CORE_API void Finish(); + D_CORE_API virtual void Finish() override; /// Thread function to execute in a perpetual loop until the thread is terminated. /// Each time the thread owner calls function Signal, the loop execute one call to /// this function and upon return, the thread goes back to wait for another signal /// or to exit the loop. - virtual void ThreadFunction() = 0; + //virtual virtual void ThreadFunction() = 0; protected: - virtual void Release(){} - - private: - void ThreadFunctionCallback(); + D_CORE_API virtual void Release() override; + D_CORE_API virtual void ThreadFunctionCallback() override; }; #endif diff --git a/newton-4.00/sdk/dCore/ndThreadPool.cpp b/newton-4.00/sdk/dCore/ndThreadPool.cpp index 0473e38c0..86db9499b 100644 --- a/newton-4.00/sdk/dCore/ndThreadPool.cpp +++ b/newton-4.00/sdk/dCore/ndThreadPool.cpp @@ -26,6 +26,28 @@ #include "ndThreadPool.h" #include "ndThreadSyncUtils.h" +class ndThreadPool::ndMainThread: public ndThread +{ + public: + ndMainThread(ndThreadPool* const owner) + :ndThread() + ,m_owner(owner) + { + } + + void ThreadFunction() override + { + m_owner->ThreadFunction(); + } + + virtual void Release() + { + m_owner->Release(); + } + + ndThreadPool* const m_owner; +}; + ndThreadPool::ndWorker::ndWorker() :ndThread() ,m_owner(nullptr) @@ -112,19 +134,21 @@ void ndThreadPool::ndWorker::ThreadFunction() ndThreadPool::ndThreadPool(const char* const baseName) :ndSyncMutex() - ,ndThread() + ,m_main(nullptr) ,m_workers(nullptr) ,m_count(0) { char name[256]; + m_main = new ndMainThread(this); strncpy(m_baseName, baseName, sizeof (m_baseName)); snprintf(name, sizeof (name), "%s_%d", m_baseName, 0); - SetName(name); + m_main->SetName(name); } ndThreadPool::~ndThreadPool() { SetThreadCount(0); + delete m_main; } ndInt32 ndThreadPool::GetMaxThreads() @@ -147,21 +171,29 @@ void ndThreadPool::SetThreadCount(ndInt32 count) { if (m_workers) { + //m_count = 0; + //delete[] m_workers; + //m_workers = nullptr; + for (ndInt32 i = m_count - 1; i >= 0; --i) + { + m_workers[i] = ndSharedPtr(nullptr); + } m_count = 0; delete[] m_workers; - m_workers = nullptr; } if (count) { m_count = count; - m_workers = new ndWorker[size_t(count)]; + //m_workers = new ndWorker[size_t(count)]; + m_workers = new ndSharedPtr[size_t(count)]; for (ndInt32 i = 0; i < count; ++i) { char name[256]; - m_workers[i].m_owner = this; - m_workers[i].m_threadIndex = i; + m_workers[i] = ndSharedPtr(new ndWorker); + m_workers[i]->m_owner = this; + m_workers[i]->m_threadIndex = i; snprintf(name, sizeof(name), "%s_%d", m_baseName, i + 1); - m_workers[i].SetName(name); + m_workers[i]->SetName(name); } } } @@ -173,7 +205,7 @@ void ndThreadPool::Begin() D_TRACKTIME(); for (ndInt32 i = 0; i < m_count; ++i) { - m_workers[i].Signal(); + m_workers[i]->Signal(); } auto BeginJobs = ndMakeObject::ndFunction([this](ndInt32, ndInt32) @@ -188,9 +220,9 @@ void ndThreadPool::End() #ifndef D_USE_THREAD_EMULATION for (ndInt32 i = 0; i < m_count; ++i) { - m_workers[i].ExecuteTask(nullptr); + m_workers[i]->ExecuteTask(nullptr); #if !defined(D_USE_SYNC_SEMAPHORE) - m_workers[i].m_begin = 0; + m_workers[i]->m_begin = 0; #endif } @@ -200,7 +232,7 @@ void ndThreadPool::End() ndUnsigned8 looping = 0; for (ndInt32 i = 0; i < m_count; ++i) { - looping = ndUnsigned8(looping | m_workers[i].m_stillLooping); + looping = ndUnsigned8(looping | m_workers[i]->m_stillLooping); } stillLooping = ndUnsigned8(stillLooping & looping); if (m_count) @@ -216,10 +248,20 @@ void ndThreadPool::Release() ndSyncMutex::Release(); } +void ndThreadPool::Finish() +{ + m_main->Finish(); +} + +void ndThreadPool::Signal() +{ + m_main->Signal(); +} + void ndThreadPool::TickOne() { ndSyncMutex::Tick(); - ndSemaphore::Signal(); + m_main->ndSemaphore::Signal(); #ifdef D_USE_THREAD_EMULATION ThreadFunction(); #endif @@ -234,7 +276,7 @@ void ndThreadPool::WaitForWorkers() ndUnsigned8 inProgess = 0; for (ndInt32 i = 0; i < m_count; ++i) { - inProgess = ndUnsigned8(inProgess | (m_workers[i].IsTaskInProgress())); + inProgess = ndUnsigned8(inProgess | (m_workers[i]->IsTaskInProgress())); } jobsInProgress = ndUnsigned8 (jobsInProgress & inProgess); if (jobsInProgress) diff --git a/newton-4.00/sdk/dCore/ndThreadPool.h b/newton-4.00/sdk/dCore/ndThreadPool.h index 1578e765e..3aa3e15f7 100644 --- a/newton-4.00/sdk/dCore/ndThreadPool.h +++ b/newton-4.00/sdk/dCore/ndThreadPool.h @@ -29,6 +29,9 @@ #include "ndSyncMutex.h" #include "ndSemaphore.h" #include "ndClassAlloc.h" +#include "ndThreadSyncUtils.h" +#include "ndContainersAlloc.h" +#include "ndSharedPtr.h" //#define D_USE_SYNC_SEMAPHORE @@ -63,16 +66,20 @@ class ndTask virtual void Execute() const = 0; }; -class ndThreadPool: public ndSyncMutex, public ndThread +D_MSV_NEWTON_ALIGN_32 +//class ndThreadPool: public ndSyncMutex, public ndThread +class ndThreadPool: public ndSyncMutex { + class ndMainThread; + class ndWorker: public ndThread { public: D_CORE_API ndWorker(); D_CORE_API virtual ~ndWorker(); - D_CORE_API ndUnsigned8 IsTaskInProgress() const; - D_CORE_API void ExecuteTask(ndTask* const task); + D_CORE_API virtual ndUnsigned8 IsTaskInProgress() const; + D_CORE_API virtual void ExecuteTask(ndTask* const task); private: virtual void ThreadFunction(); @@ -102,6 +109,10 @@ class ndThreadPool: public ndSyncMutex, public ndThread D_CORE_API void TickOne(); D_CORE_API void Begin(); D_CORE_API void End(); + D_CORE_API void Signal(); + D_CORE_API void Finish(); + + virtual void ThreadFunction() = 0; template void ParallelExecute(const Function& ndFunction); @@ -110,10 +121,11 @@ class ndThreadPool: public ndSyncMutex, public ndThread D_CORE_API virtual void Release(); D_CORE_API virtual void WaitForWorkers(); - ndWorker* m_workers; + ndThreadInterface* m_main; + ndSharedPtr* m_workers; ndInt32 m_count; char m_baseName[32]; -}; +}D_GCC_NEWTON_ALIGN_32; inline ndInt32 ndThreadPool::GetThreadCount() const { @@ -206,7 +218,8 @@ void ndThreadPool::ParallelExecute(const Function& callback) for (ndInt32 i = 0; i < m_count; ++i) { ndTaskImplement* const job = &jobsArray[i + 1]; - m_workers[i].ExecuteTask(job); + //m_workers[i].ExecuteTask(job); + m_workers[i]->ExecuteTask(job); } ndTaskImplement* const job = &jobsArray[0];