pthread_helpers.h 3.21 KB
/*
 * pthread_helpers.h
 *
 *  Created on: 11 sty 2019
 *      Author: mariuszo
 */

#ifndef PTHREAD_HELPERS_H_
#define PTHREAD_HELPERS_H_
/*
#include <pthread.h>
#include <semaphore.h>
#include <errno.h>
#include <math.h>
//#include <string.h>
//#include <stdio.h>
#include <stdint.h>
#include <time.h>
*/
#ifndef NS_IN_S
#define NS_IN_S 1000000000
#endif

inline bool semPost(sem_t& sem){
	return sem_post(&sem)==0;
}

inline bool semWait(sem_t& sem, const uint64_t& timeoutns=UINT64_MAX){
	if (timeoutns==0) {
		while(1){
			if (sem_trywait(&sem)!=0){
				if (errno==EINTR)
					continue;
				else if (errno==EAGAIN)
					errno=ETIMEDOUT;
				return false;
			}
			return true;
		}
	} else if (timeoutns==UINT64_MAX){
		while (1) {
			if (sem_wait(&sem)!=0){
				if (errno==EINTR)
					continue;
				return false;
			}
			return true;
		};
	} else {
		timespec  time;
		clock_gettime(CLOCK_REALTIME, &time);
		time.tv_nsec+=timeoutns;
		time.tv_sec+=(time.tv_nsec/NS_IN_S);
		time.tv_nsec%=NS_IN_S;
		while (1) {
			if (sem_timedwait(&(sem),&time)!=0){
				if (errno==EINTR)
					continue;
				return false;
			}
			return true;
		}
	}
}

inline int wrLock(pthread_rwlock_t& lock, const uint64_t& timeoutns=UINT64_MAX){
	if (timeoutns==0) {
		return pthread_rwlock_trywrlock(&lock);
	} else if (timeoutns==UINT64_MAX){
		while (1) {
			if (pthread_rwlock_wrlock(&lock)==0)
				return 0;
		};
	} else {
		int err;
		timespec  time;
		clock_gettime(CLOCK_REALTIME, &time);
		time.tv_nsec+=timeoutns;
		time.tv_sec+=(time.tv_nsec/NS_IN_S);
		time.tv_nsec%=NS_IN_S;
		while (1) {
			if ((err=pthread_rwlock_timedwrlock(&lock,&time))==0)
				return 0;
			else if (err==ETIMEDOUT)
				return err;
		}
	}
}


inline int rdLock(pthread_rwlock_t& lock, const uint64_t& timeoutns=UINT64_MAX){
	if (timeoutns==0) {
		return pthread_rwlock_tryrdlock(&lock);
	} else if (timeoutns==UINT64_MAX){
		while (1) {
			if (pthread_rwlock_rdlock(&lock)==0)
				return 0;
		};
	} else {
		int err;
		timespec  time;
		clock_gettime(CLOCK_REALTIME, &time);
		time.tv_nsec+=timeoutns;
		time.tv_sec+=(time.tv_nsec/NS_IN_S);
		time.tv_nsec%=NS_IN_S;
		while (1) {
			if ((err=pthread_rwlock_timedrdlock(&lock,&time))==0)
				return 0;
			else if (err==ETIMEDOUT)
				return err;
		}
	}
}
inline int rwUnlock(pthread_rwlock_t& lock){
	return pthread_rwlock_unlock(&lock);
}

inline int mutexLock(pthread_mutex_t& lock, const uint64_t& timeoutns=UINT64_MAX){
	if (timeoutns==0) {
		int err;
		if ((err=pthread_mutex_trylock(&lock))==EOWNERDEAD)
			pthread_mutex_consistent(&lock);
		return err;
	} else if (timeoutns==UINT64_MAX){
		int err;
		while (1) {
			if ((err=pthread_mutex_lock(&lock))==0)
				return 0;
			if (err==EOWNERDEAD){
				pthread_mutex_consistent(&lock);
				return err;
			}
		};
	} else {
		int err;
		timespec  time;
		clock_gettime(CLOCK_REALTIME, &time);
		time.tv_nsec+=timeoutns;
		time.tv_sec+=(time.tv_nsec/NS_IN_S);
		time.tv_nsec%=NS_IN_S;
		while (1) {
			if ((err=pthread_mutex_timedlock(&lock,&time))==0)
				return 0;
			else if (err==ETIMEDOUT)
				return err;
			else if (err==EOWNERDEAD){
				pthread_mutex_consistent(&lock);
				return err;
			}
		}
	}
}
inline int mutexUnlock(pthread_mutex_t& lock){
	return pthread_mutex_unlock(&lock);
}

#endif /* PTHREAD_HELPERS_H_ */