diff --git a/ethread/Mutex.hpp b/ethread/Mutex.hpp index c973d78..bf8d506 100644 --- a/ethread/Mutex.hpp +++ b/ethread/Mutex.hpp @@ -21,7 +21,7 @@ namespace ethread { #ifdef __TARGET_OS__Windows CRITICAL_SECTION m_mutex; #else - pthread_mutex_t m_mutex; + pthread_mutex_t m_mutex; #endif public: /** @@ -54,20 +54,40 @@ namespace ethread { private: // Keep a reference on the mutex ethread::Mutex &m_protect; + bool m_lock; public: /** * @brief constructor that automaticly lock the mutex. * @param[in] _protect Mutex to Lock. + * @param[in] _notLock Must be lock after by a tryLock. */ - UniqueLock(ethread::Mutex& _protect) : - m_protect(_protect) { - m_protect.lock(); + UniqueLock(ethread::Mutex& _protect, bool _notLock = false) : + m_protect(_protect), + m_lock(false) { + if (_notLock == false) { + m_protect.lock(); + m_lock = true; + } + } + /** + * @brief Try to lock the mutex (exit if mutex is already locked) + * @return true The mutex is locked + * @return false The mutex is already locked. + */ + bool tryLock() { + if (m_protect.tryLock() == true) { + m_lock = true; + } + return m_lock; } /** * @brief Destructor that Auto Unlock mutex when remove. */ virtual ~UniqueLock(){ - m_protect.unLock(); + if (m_lock == true) { + m_protect.unLock(); + m_lock = false; + } } }; } diff --git a/ethread/Pool.cpp b/ethread/Pool.cpp index c2d27ed..cae31cd 100644 --- a/ethread/Pool.cpp +++ b/ethread/Pool.cpp @@ -10,7 +10,7 @@ ethread::Pool::Pool(uint16_t _numberOfThread): m_lastTrandId(1) { - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); for (uint32_t iii=0; iii<_numberOfThread; ++iii) { ememory::SharedPtr tmp = ememory::makeShared(*this); if (tmp != nullptr) { @@ -26,12 +26,12 @@ ethread::Pool::~Pool() { } uint32_t ethread::Pool::createGroupId() { - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); return m_lastTrandId++; } ethread::Future ethread::Pool::async(etk::Function _call, uint64_t _executionInGroupId) { - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); if (_call == nullptr) { ETHREAD_ERROR("Can not add an action with no function to call..."); return ethread::Future(); @@ -55,7 +55,7 @@ void ethread::Pool::releaseId(uint64_t _id) { if (_id == 0) { return; } - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); auto it = m_listIdPool.begin(); while (it != m_listIdPool.end()) { if (*it == _id) { @@ -68,7 +68,7 @@ void ethread::Pool::releaseId(uint64_t _id) { // get an action to execute ... ememory::SharedPtr ethread::Pool::getAction() { - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); auto it = m_listActions.begin(); while (it != m_listActions.end()) { if (*it == nullptr) { @@ -101,7 +101,7 @@ ememory::SharedPtr ethread::Pool::getAction() { void ethread::Pool::stop() { - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); auto it = m_listThread.begin(); while (it != m_listThread.end()) { if (*it == nullptr) { @@ -114,7 +114,7 @@ void ethread::Pool::stop() { } void ethread::Pool::join() { - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); ETHREAD_DEBUG("start join all the threads in pool " << m_listThread.size()); for (size_t iii=0; iii lock(m_mutex); + ethread::UniqueLock lock(m_mutex); // If no action availlable and not requested to check, just sleep ... if (m_needProcess == false) { m_isWaiting = true; @@ -55,7 +55,7 @@ void ethread::PoolExecutor::start() { ETHREAD_DEBUG("START: thread in Pool [START]"); m_running = true; { - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); m_condition.notify_all(); } m_thread = ememory::makeShared([&](void *){ this->threadCallback();}, nullptr); @@ -71,7 +71,7 @@ void ethread::PoolExecutor::start() { void ethread::PoolExecutor::stop() { ETHREAD_DEBUG("STOP: thread in Pool [START]"); { - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); m_condition.notify_all(); } m_running = false; @@ -81,7 +81,7 @@ void ethread::PoolExecutor::stop() { void ethread::PoolExecutor::join() { ETHREAD_DEBUG("JOIN: thread in Pool [START]"); { - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); m_condition.notify_all(); } if (m_thread != nullptr) { @@ -93,7 +93,7 @@ void ethread::PoolExecutor::join() { } bool ethread::PoolExecutor::touch() { - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); bool ret = false; if ( m_needProcess == false && m_isWaiting == true) { diff --git a/ethread/PoolExecutor.hpp b/ethread/PoolExecutor.hpp index f2ecfe6..fdaa6cf 100644 --- a/ethread/PoolExecutor.hpp +++ b/ethread/PoolExecutor.hpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include namespace ethread { /** diff --git a/ethread/Promise.cpp b/ethread/Promise.cpp index 059dca9..389279d 100644 --- a/ethread/Promise.cpp +++ b/ethread/Promise.cpp @@ -21,7 +21,7 @@ bool ethread::Promise::isFinished() { void ethread::Promise::finish() { etk::Function callback; { - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); if (m_isFinished == true) { ETHREAD_ERROR("Request 2 time finishing a Promise ..."); return; @@ -41,7 +41,7 @@ bool ethread::Promise::wait(echrono::Duration _delay) { echrono::Steady time = echrono::Steady::now(); while (_delay >= 0) { { - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); if (m_isFinished == true) { return true; } @@ -51,14 +51,14 @@ bool ethread::Promise::wait(echrono::Duration _delay) { time = time2; if (_delay >= 0) { // TODO : This is really bad ==> fast to code and debug but not optimum at all ... use condition instead ... - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + ethread::sleepMilliSeconds((10)); } } return false; } void ethread::Promise::andThen(etk::Function _action) { - std::unique_lock lock(m_mutex); + ethread::UniqueLock lock(m_mutex); m_callback = etk::move(_action); if (m_isFinished == true) { m_callback(); diff --git a/ethread/Promise.hpp b/ethread/Promise.hpp index 9554b1a..067807a 100644 --- a/ethread/Promise.hpp +++ b/ethread/Promise.hpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include namespace ethread { diff --git a/ethread/Thread.hpp b/ethread/Thread.hpp index 4467986..b6b6484 100644 --- a/ethread/Thread.hpp +++ b/ethread/Thread.hpp @@ -11,7 +11,9 @@ #ifdef __TARGET_OS__Windows #error TODO ... #else - #include + extern "C" { + #include + } #endif namespace ethread { @@ -23,9 +25,10 @@ namespace ethread { #ifdef __TARGET_OS__Windows #else - pthread_mutex_t m_thread; + pthread_t m_thread; + static void* threadCallback(void* _userData); #endif - uint32_t m_uid; //!< unique id of the thread + uint64_t m_uid; //!< unique id of the thread etk::String m_name; //!< Name of the thread (do not get it on the system ==> more portable) etk::Function m_function; //!< Function to call every cycle of the thead running public: @@ -33,9 +36,10 @@ namespace ethread { ~Thread(); void join(); bool detach(); + void threadCall(); void setName(const etk::String& _name); const etk::String& setName() const; - uint32_t getIdentifier() const; + uint64_t getId() const; }; } diff --git a/ethread/Thread.pthread.cpp b/ethread/Thread.pthread.cpp index e69de29..8e0e89a 100644 --- a/ethread/Thread.pthread.cpp +++ b/ethread/Thread.pthread.cpp @@ -0,0 +1,63 @@ +/** + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ +#include + + +void* ethread::Thread::threadCallback(void* _userData) { + ethread::Thread* threadHandle = static_cast(_userData); + if (threadHandle != nullptr) { + threadHandle->threadCall(); + } + return nullptr; +} + + +ethread::Thread::Thread(etk::Function&& _call, const etk::String& _name): + m_thread(0), + m_uid(-1), + m_name(_name), + m_function(etk::move(_call)) { + pthread_create(&m_thread, nullptr, ðread::Thread::threadCallback, this); + /* + pthread_id_np_t tid; + pthread_getunique_np(&m_thread, &tid); + m_uid = uint64_t(tid); + */ + m_uid = *(uint64_t*)(m_thread); +} + +ethread::Thread::~Thread() { + +} + +void ethread::Thread::join() { + void* ret = nullptr; + int val = pthread_join(m_thread, &ret); +} + +bool ethread::Thread::detach() { + +} + +void ethread::Thread::setName(const etk::String& _name) { + m_name = _name; +} + +const etk::String& ethread::Thread::setName() const { + return m_name; +} + +void ethread::Thread::threadCall() { + if (m_function != nullptr) { + m_function(); + } +} + +uint64_t ethread::Thread::getId() const { + return m_uid; +} + + diff --git a/ethread/tools.cpp b/ethread/tools.cpp index eabeee4..4d2b8f2 100644 --- a/ethread/tools.cpp +++ b/ethread/tools.cpp @@ -9,8 +9,16 @@ //#include // TODO: set mutex back ... #include -#include - +extern "C" { + #include +} +#ifdef __TARGET_OS__Windows + #error TODO ... +#else + extern "C" { + #include + } +#endif //static ethread::Mutex g_lock; static etk::Map& getThreadList() { static etk::Map g_val; @@ -79,15 +87,18 @@ static void setThreadName(ethread::Thread* _thread, const etk::String& _name) { } */ uint32_t ethread::getId() { + pthread_t self; + self = pthread_self(); /* - return getThreadHumanId(std::this_thread::get_id()); + pthread_id_np_t tid; + pthread_getunique_np(&self, &tid); + return uint64_t(tid); */ - return 0; + return *(uint64_t*)(self); } uint32_t ethread::getId(ethread::Thread& _thread) { - //return getThreadHumanId(_thread.get_id()); - return 0; + return _thread.getId(); } void ethread::setName(const etk::String& _name) { @@ -210,7 +221,7 @@ static etk::Map> g_listMetaData; void ethread::metadataSet(const etk::String& _key, uint64_t _value) { /* uint32_t currentThreadId = ethread::getId(); - // TODO: std::unique_lock lock(g_localMutex); + // TODO: ethread::UniqueLock lock(g_localMutex); auto it = g_listMetaData.find(currentThreadId); if (it != g_listMetaData.end()) { it.getValue().set(_key, _value); @@ -225,7 +236,7 @@ void ethread::metadataSet(const etk::String& _key, uint64_t _value) { void ethread::metadataRemove(const etk::String& _key) { /* uint32_t currentThreadId = ethread::getId(); - // TODO: std::unique_lock lock(g_localMutex); + // TODO: ethread::UniqueLock lock(g_localMutex); etk::Map>::Iterator it = g_listMetaData.find(currentThreadId); if (it != g_listMetaData.end()) { auto it2 = it.getValue().find(_key); @@ -240,7 +251,7 @@ void ethread::metadataRemove(const etk::String& _key) { uint64_t ethread::metadataGetU64(const etk::String& _key) { /* uint32_t currentThreadId = ethread::getId(); - // TODO: std::unique_lock lock(g_localMutex); + // TODO: ethread::UniqueLock lock(g_localMutex); auto it = g_listMetaData.find(currentThreadId); if (it != g_listMetaData.end()) { auto it2 = it.getValue().find(_key); diff --git a/lutin_ethread-tools.py b/lutin_ethread-tools.py index 842b156..77f3639 100644 --- a/lutin_ethread-tools.py +++ b/lutin_ethread-tools.py @@ -35,17 +35,20 @@ def configure(target, my_module): 'ethread/tools.hpp', 'ethread/Thread.hpp', 'ethread/Mutex.hpp', + 'ethread/MutexRecursive.hpp', 'ethread/Semaphore.hpp', ]) if "Windows" in target.get_type(): my_module.add_src_file([ 'ethread/Mutex.Windows.cpp', + 'ethread/MutexRecursive.Windows.cpp', 'ethread/Thread.Windows.cpp', ]) else: my_module.add_src_file([ 'ethread/Mutex.pthread.cpp', + 'ethread/MutexRecursive.pthread.cpp', 'ethread/Thread.pthread.cpp', ]) my_module.add_depend([