I think i solved this question, with a workaround code.
I used this code in linux (c++)
myMutex.cpp
struct myMutexW_s {
std::mutex m_wait;
std::mutex m_thw;
pthread_t tWId = 0;
uint32_t tout = 1;
};
void Aux_Millisleep(int ms) {
if (ms > 0) {
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = ms * 1000;
select(0, NULL, NULL, NULL, &tv);
}
}
static void* myWait_ThFcn(void* arg) {
myMutexW_ts* m_ = (myMutexW_ts*)arg;
pthread_detach(pthread_self());
int s = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
if (s != 0) { printf("pthread_setcancelstate: FAIL %d, %X\n", s, m_); }
s = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
if (s != 0) { printf("pthread_setcanceltype: FAIL %d, %X\n", s, m_); }
m_->m_thw.lock();
Aux_Millisleep(m_->tout);
m_->m_wait.unlock();
m_->tWId = 0;
return nullptr;
}
int myMutexTryLock(myMutexW_ts* m_) {
return m_->m_wait.try_lock();
}
int myMutexWaitms(uint32_t tms, bool CrlI, myMutexW_ts* m_) {
if (tms <= 0) return -1; // "timeout"
if (m_ == nullptr) return -10;
if (CrlI) m_->m_wait.try_lock();
m_->m_thw.try_lock();
m_->tout = tms;
if ((ret = pthread_create(&m_->tWId, nullptr, &myWait_ThFcn, m_)) == 0) {
pthread_yield();
} else {
printf("myMutexWaitms: FAIL %X, r:%d, th:%d, to:%d\n",
m_, ret, m_->tWId, m_->tout);
Aux_Millisleep(m_->tout); // fake timeout
return -20; // !!!!!!
}
m_->m_thw.unlock();
m_->m_wait.lock();
if (m_->tWId) {
pthread_cancel(m_->tWId);
return 0; // unlocked before timeout
}
return -1; // timeout
}
void myMutexUnlock(myMutexW_ts* m_) {
if (m_ == nullptr) return;
m_->m_wait.unlock();
}
myMutexW_ts* myMutexNew(void) {
return new myMutexW_ts;
}
void myMutexDel(myMutexW_ts** m_) {
if (m_) {
if (*m_) {
if ((*m_)->tWId) {
pthread_cancel((*m_)->tWId);
(*m_)->tWId = 0;
(*m_)->m_wait.unlock();
}
delete (*m_);
}
(*m_) = nullptr;
}
}
myMutex.h
#include <stdint.h>
#include <stdbool.h>
typedef struct myMutexW_s myMutexW_ts;
#ifdef __cplusplus
extern "C" {
#endif
int myMutexTryLock(myMutexW_ts* m_) ;
int myMutexWaitms(uint32_t tms, bool CrlI, myMutexW_ts* m_);
void myMutexUnlock(myMutexW_ts* m_) ;
myMutexW_ts* myMutexNew(void);
void myMutexDel(myMutexW_ts** m_);
#ifdef __cplusplus
}
#endif
Usage is like a normal mutex.
I'm still testing its performance, but apparently it's been behaving well.