[DEV] remove os dependency for mutex and contition

This commit is contained in:
Edouard DUPIN 2014-10-08 22:14:17 +02:00
parent 0b42adbec8
commit 327fdbf1a2
8 changed files with 13 additions and 403 deletions

View File

@ -11,9 +11,9 @@
#ifndef __ETK_MESSAGE_FIFO_H__ #ifndef __ETK_MESSAGE_FIFO_H__
#define __ETK_MESSAGE_FIFO_H__ #define __ETK_MESSAGE_FIFO_H__
#include <etk/os/Mutex.h> #include <mutex>
#include <etk/os/Semaphore.h>
#include <vector> #include <vector>
#include <condition_variable>
namespace etk { namespace etk {
/** /**
@ -23,8 +23,8 @@ namespace etk {
*/ */
template<class MY_TYPE=int32_t> class Fifo { template<class MY_TYPE=int32_t> class Fifo {
private : private :
etk::Mutex m_mutex; //!< protection of the internal data. std::mutex m_mutex; //!< protection of the internal data.
etk::Semaphore m_semaphore; //!< Message system to send event on an other thread. std::condition_variable m_condition; //!< Message system to send event on an other thread.
std::vector<MY_TYPE> m_data; //!< List of all message to send std::vector<MY_TYPE> m_data; //!< List of all message to send
public : public :
/** /**
@ -46,12 +46,10 @@ namespace etk {
* @return false No data found or closed fifo * @return false No data found or closed fifo
*/ */
bool wait(MY_TYPE &_data) { bool wait(MY_TYPE &_data) {
m_mutex.lock(); std::unique_lock<std::mutex> lock(m_mutex);
// Check if data is not previously here // Check if data is not previously here
while(0==m_data.size()) { while(0==m_data.size()) {
m_mutex.unLock(); m_condition.wait(lock);
m_semaphore.wait();
m_mutex.lock();
} }
// End Waiting message : // End Waiting message :
if (0<m_data.size()) { if (0<m_data.size()) {
@ -59,8 +57,6 @@ namespace etk {
_data = m_data[0]; _data = m_data[0];
// remove element : // remove element :
m_data.erase(m_data.begin()); m_data.erase(m_data.begin());
// remove lock
m_mutex.unLock();
return true; return true;
} }
return false; return false;
@ -73,14 +69,12 @@ namespace etk {
* @return false No message found while time-out appear. * @return false No message found while time-out appear.
*/ */
bool wait(MY_TYPE &_data, uint32_t _timeOutInUs) { bool wait(MY_TYPE &_data, uint32_t _timeOutInUs) {
m_mutex.lock(); std::unique_lock<std::mutex> lock(m_mutex);
// Check if data is not previously here // Check if data is not previously here
while(0==m_data.size()) { while(0==m_data.size()) {
m_mutex.unLock(); if (m_condition.wait_for(lock, std::chrono::microseconds(_timeOutInUs)) == std::cv_status::timeout) {
if (false == m_semaphore.wait(_timeOutInUs)) {
return false; return false;
} }
m_mutex.lock();
} }
// End Waiting message : // End Waiting message :
if (0<m_data.size()) { if (0<m_data.size()) {
@ -88,8 +82,6 @@ namespace etk {
_data = m_data[0]; _data = m_data[0];
// remove element : // remove element :
m_data.erase(0); m_data.erase(0);
// remove lock
m_mutex.unLock();
return true; return true;
} }
return false; return false;
@ -99,9 +91,8 @@ namespace etk {
* @return Number of message in the fifo. * @return Number of message in the fifo.
*/ */
int32_t count() { int32_t count() {
m_mutex.lock(); std::unique_lock<std::mutex> lock(m_mutex);
int32_t nbElement = m_data.size(); int32_t nbElement = m_data.size();
m_mutex.unLock();
return nbElement; return nbElement;
}; };
/** /**
@ -109,21 +100,18 @@ namespace etk {
* @param[in] _data New data to add at the fifo. * @param[in] _data New data to add at the fifo.
*/ */
void post(MY_TYPE &_data) { void post(MY_TYPE &_data) {
m_mutex.lock(); std::unique_lock<std::mutex> lock(m_mutex);
m_data.push_back(_data); m_data.push_back(_data);
m_semaphore.post(); m_condition.notify_all();
m_mutex.unLock();
}; };
/** /**
* @brief Remove all the message in the fifo. * @brief Remove all the message in the fifo.
*/ */
void clean() { void clean() {
m_mutex.lock(); std::unique_lock<std::mutex> lock(m_mutex);
// remove data // remove data
m_data.clear(); m_data.clear();
m_mutex.unLock(); m_condition.wait_for(lock, std::chrono::microseconds(0));
// remove semaphore
m_semaphore.wait(0);
}; };
}; };
}; };

View File

@ -1,45 +0,0 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#include <etk/types.h>
#include <etk/os/Mutex.h>
#include <etk/debug.h>
etk::Mutex::Mutex()
{
// create interface mutex :
int ret = pthread_mutex_init(&m_mutex, NULL);
TK_ASSERT(ret == 0, "Error creating Mutex ...");
}
etk::Mutex::~Mutex()
{
// Remove mutex
int ret = pthread_mutex_destroy(&m_mutex);
TK_ASSERT(ret == 0, "Error destroying Mutex ...");
}
void etk::Mutex::lock()
{
pthread_mutex_lock(&m_mutex);
}
bool etk::Mutex::tryLock()
{
return pthread_mutex_trylock(&m_mutex) != 0;
}
void etk::Mutex::unLock()
{
pthread_mutex_unlock(&m_mutex);
}

View File

@ -1,40 +0,0 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#include <etk/os/Mutex.h>
etk::Mutex::Mutex()
{
InitializeCriticalSection(&m_mutex);
}
etk::Mutex::~Mutex()
{
DeleteCriticalSection(&m_mutex);
}
void etk::Mutex::lock()
{
EnterCriticalSection(&m_mutex);
}
bool etk::Mutex::tryLock()
{
return TryEnterCriticalSection(&m_mutex) != 0;
}
void etk::Mutex::unLock()
{
LeaveCriticalSection(&m_mutex);
}

View File

@ -1,80 +0,0 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#include <etk/types.h>
#ifndef __ETK_MUTEX_H__
#define __ETK_MUTEX_H__
#ifdef __TARGET_OS__Windows
#include <windows.h>
#else
#include <pthread.h>
#endif
namespace etk {
/**
* @brief Generic mutex interface (OS independent)
*/
class Mutex {
private:
#ifdef __TARGET_OS__Windows
CRITICAL_SECTION m_mutex;
#else
pthread_mutex_t m_mutex;
#endif
public:
/**
* @brief Create a new mutex
*/
Mutex();
/**
* @brief Destroy the mutex.
*/
~Mutex();
/**
* @brief Lock the mutex (Wait while the mutex is not lock)
*/
void lock();
/**
* @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();
/**
* @brief Unloc the mutex
*/
void unLock();
};
/**
* @brief AutoLock and un-lock when exit fuction.
*/
class AutoLockMutex {
private:
// Keep a reference on the mutex
etk::Mutex &m_protect;
public:
/**
* @brief constructor that automaticly lock the mutex.
* @param[in] _protect Mutex to Lock.
*/
AutoLockMutex(etk::Mutex& _protect) :
m_protect(_protect) {
m_protect.lock();
}
/**
* @brief Destructor that Auto Unlock mutex when remove.
*/
virtual ~AutoLockMutex(){
m_protect.unLock();
}
};
};
#endif

View File

@ -1,89 +0,0 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#include <etk/types.h>
#include <etk/os/Semaphore.h>
#include <etk/debug.h>
#include <sys/time.h>
etk::Semaphore::Semaphore(uint32_t _nbBasicElement, uint32_t _nbMessageMax) {
// create interface mutex :
int ret = pthread_mutex_init(&m_mutex, NULL);
TK_ASSERT(ret == 0, "Error creating Mutex ...");
// create contition :
ret = pthread_cond_init(&m_condition, NULL);
TK_ASSERT(ret == 0, "Error creating Condition ...");
if (ret != 0) {
ret = pthread_mutex_destroy(&m_mutex);
TK_ASSERT(ret == 0, "Error destroying Mutex ...");
}
m_maximum = _nbMessageMax;
m_data = _nbBasicElement;
}
etk::Semaphore::~Semaphore() {
// Remove condition
int ret = pthread_cond_destroy(&m_condition);
TK_ASSERT(ret == 0, "Error destroying Condition ...");
// Remove Mutex
ret = pthread_mutex_destroy(&m_mutex);
TK_ASSERT(ret == 0, "Error destroying Mutex ...");
}
uint32_t etk::Semaphore::getCount() {
int32_t tmpData = 0;
pthread_mutex_lock(&m_mutex);
tmpData = m_data;
pthread_mutex_unlock(&m_mutex);
return tmpData;
}
void etk::Semaphore::post() {
pthread_mutex_lock(&m_mutex);
if (m_data>=m_maximum) {
m_data = m_maximum;
} else {
m_data++;
}
// send message
pthread_cond_broadcast(&m_condition);
pthread_mutex_unlock(&m_mutex);
}
void etk::Semaphore::wait() {
pthread_mutex_lock(&m_mutex);
while(m_data == 0) {
pthread_cond_wait(&m_condition, &m_mutex);
}
m_data--;
pthread_mutex_unlock(&m_mutex);
}
bool etk::Semaphore::wait(uint64_t _timeOutInUs) {
pthread_mutex_lock(&m_mutex);
if(m_data == 0) {
struct timeval tp;
struct timespec ts;
gettimeofday(&tp,NULL);
uint64_t totalTimeUS = tp.tv_sec * 1000000 + tp.tv_usec;
totalTimeUS += _timeOutInUs;
ts.tv_sec = totalTimeUS / 1000000;
ts.tv_nsec = (totalTimeUS%1000000) * 1000;
int ret = pthread_cond_timedwait(&m_condition, &m_mutex, &ts);
if (ret !=0) { //== ETIMEOUT) {
pthread_mutex_unlock(&m_mutex);
return false;
}
}
m_data--;
pthread_mutex_unlock(&m_mutex);
return true;
}

View File

@ -1,48 +0,0 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#include <etk/types.h>
#include <etk/os/Semaphore.h>
#include <etk/debug.h>
etk::Semaphore::Semaphore(uint32_t _nbBasicElement, uint32_t _nbMessageMax) {
// create interface mutex :
m_semaphore = CreateSemaphore(NULL, _nbBasicElement, _nbMessageMax, NULL);
TK_ASSERT(m_semaphore != 0, "Error creating SEMAPHORE ...");
}
etk::Semaphore::~Semaphore() {
CloseHandle(m_semaphore);
}
uint32_t etk::Semaphore::getCount() {
LONG tmpData = 0;
ReleaseSemaphore(m_semaphore, 0, &tmpData);
return tmpData;
}
void etk::Semaphore::post() {
ReleaseSemaphore(m_semaphore, 1, NULL);
}
void etk::Semaphore::wait() {
WaitForSingleObject(m_semaphore, INFINITE);
}
bool etk::Semaphore::wait(uint64_t _timeOutInUs) {
DWORD result = WaitForSingleObject(m_semaphore, _timeOutInUs);
if (result == WAIT_FAILED) {
TK_ERROR("Failed to wait for semaphore ");
return false;
} else {
return result == WAIT_OBJECT_0;
}
}

View File

@ -1,69 +0,0 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license APACHE v2.0 (see license file)
*/
#ifndef __ETK_SEMAPHORE_H__
#define __ETK_SEMAPHORE_H__
#include <etk/types.h>
#ifdef __TARGET_OS__Windows
#include <windows.h>
#else
#include <pthread.h>
#endif
namespace etk {
/**
* @brief Generic semaphore wrapper ( it is os independent)
*/
class Semaphore {
private:
#ifdef __TARGET_OS__Windows
HANDLE m_semaphore;
#else
pthread_mutex_t m_mutex;
pthread_cond_t m_condition;
uint32_t m_data;
uint32_t m_maximum;
#endif
public:
/**
* @brief Contruct the inithialized semaphore.
* @param[in] _nbBasicElement Number of element basicly set in the semaphore list
* @param[in] _nbMessageMax Nunber of maximun message that can be set.
*/
Semaphore(uint32_t _nbBasicElement=0, uint32_t _nbMessageMax=1);
/**
* @brief Generic destructor.
*/
~Semaphore();
/**
* @brief Get the number of element in the semaphore.
* @return Number of stored elements.
*/
uint32_t getCount();
/**
* @brief Post a new semaphore
*/
void post();
/**
* @brief Wait for a new semaphore post by an other thread.
*/
void wait();
/**
* @brief Wait for a new semaphore post by an other thread,
* with a timeout in micro-second.
* @param[in] _timeOutInUs Number of micro-second to wait a semaphore.
* @return true The function get a semaphore.
* @return false The time-out appear or an error occured.
*/
bool wait(uint64_t _timeOutInUs);
};
};
#endif

View File

@ -28,13 +28,6 @@ def create(target):
'etk/archive/Archive.cpp', 'etk/archive/Archive.cpp',
'etk/archive/Zip.cpp']) 'etk/archive/Zip.cpp'])
if target.name=="Windows":
myModule.add_src_file('etk/os/Mutex.Windows.cpp')
myModule.add_src_file('etk/os/Semaphore.Windows.cpp')
else:
myModule.add_src_file('etk/os/Mutex.Generic.cpp')
myModule.add_src_file('etk/os/Semaphore.Generic.cpp')
if target.name=="IOs": if target.name=="IOs":
myModule.add_src_file('etk/logIOs.m') myModule.add_src_file('etk/logIOs.m')