diff --git a/src/libCom/osi/epicsEvent.h b/src/libCom/osi/epicsEvent.h new file mode 100644 index 000000000..f8c2199dc --- /dev/null +++ b/src/libCom/osi/epicsEvent.h @@ -0,0 +1,124 @@ +#ifndef epicsEventh +#define epicsEventh + +#include "epicsAssert.h" +#include "shareLib.h" + +typedef void *epicsEventId; + +typedef enum { + epicsEventWaitOK,epicsEventWaitTimeout,epicsEventWaitError +} epicsEventWaitStatus; + +typedef enum {epicsEventEmpty,epicsEventFull} epicsEventInitialState; + +#ifdef __cplusplus +#include "locationException.h" +class epicsShareClass epicsEvent { +public: + epicsEvent (epicsEventInitialState initial=epicsEventEmpty); + ~epicsEvent (); + void signal (); + void wait (); /* blocks until full */ + bool wait ( double timeOut ); /* false if empty at time out */ + bool tryWait (); /* false if empty */ + void show ( unsigned level ) const; + + class invalidSemaphore {}; /* exception */ + class noMemory {}; /* exception */ +private: + epicsEventId id; +}; +#endif /*__cplusplus */ + +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus */ + +epicsShareFunc epicsEventId epicsShareAPI epicsEventCreate( + epicsEventInitialState initialState); +epicsShareFunc epicsEventId epicsShareAPI epicsEventMustCreate ( + epicsEventInitialState initialState); +epicsShareFunc void epicsShareAPI epicsEventDestroy(epicsEventId id); +epicsShareFunc void epicsShareAPI epicsEventSignal(epicsEventId id); +epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventWait( + epicsEventId id); +#define epicsEventMustWait(ID) assert((epicsEventWait ((ID))==epicsEventWaitOK)) +epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventWaitWithTimeout( + epicsEventId id, double timeOut); +epicsShareFunc epicsEventWaitStatus epicsShareAPI epicsEventTryWait( + epicsEventId id); +epicsShareFunc void epicsShareAPI epicsEventShow( + epicsEventId id, unsigned int level); + +#ifdef __cplusplus +} +#endif /*__cplusplus */ + +#include "osdEvent.h" + +/*The c++ implementation consists of inline calls to the c code */ +#ifdef __cplusplus +inline epicsEvent::epicsEvent (epicsEventInitialState initial) +{ + this->id = epicsEventCreate (initial); + if (this->id==0) { + throwWithLocation ( noMemory () ); + } +} + +inline epicsEvent::~epicsEvent () +{ + epicsEventDestroy (this->id); +} + +inline void epicsEvent::signal () +{ + epicsEventSignal (this->id); +} + +inline void epicsEvent::wait () +{ + epicsEventWaitStatus status; + status = epicsEventWait (this->id); + if (status!=epicsEventWaitOK) { + throwWithLocation ( invalidSemaphore () ); + } +} + +inline bool epicsEvent::wait (double timeOut) +{ + epicsEventWaitStatus status; + status = epicsEventWaitWithTimeout (this->id, timeOut); + if (status==epicsEventWaitOK) { + return true; + } else if (status==epicsEventWaitTimeout) { + return false; + } else { + throwWithLocation ( invalidSemaphore () ); + return false; + } +} + +inline bool epicsEvent::tryWait () +{ + epicsEventWaitStatus status; + status = epicsEventTryWait (this->id); + if (status==epicsEventWaitOK) { + return true; + } else if (status==epicsEventWaitTimeout) { + return false; + } else { + throwWithLocation ( invalidSemaphore () ); + return false; + } +} + +inline void epicsEvent::show ( unsigned level ) const +{ + epicsEventShow ( this->id, level ); +} + +#endif /*__cplusplus */ + +#endif /* epicsEventh */ diff --git a/src/libCom/osi/epicsMutex.h b/src/libCom/osi/epicsMutex.h new file mode 100644 index 000000000..606ce9fc7 --- /dev/null +++ b/src/libCom/osi/epicsMutex.h @@ -0,0 +1,145 @@ +#ifndef epicsMutexh +#define epicsMutexh + +#include "epicsAssert.h" +#include "shareLib.h" + +typedef void *epicsMutexId; +typedef enum { + epicsMutexLockOK,epicsMutexLockTimeout,epicsMutexLockError +} epicsMutexLockStatus; + +#ifdef __cplusplus +#include "locationException.h" +class epicsShareClass epicsMutex { +public: + epicsMutex (); + ~epicsMutex (); + void lock () const; /* blocks until success */ + bool lock ( double timeOut ) const; /* true if successful */ + bool tryLock () const; /* true if successful */ + void unlock () const; + void show ( unsigned level ) const; + + class invalidSemaphore {}; /* exception */ + class noMemory {}; /* exception */ +private: + mutable semMutexId id; +}; +#endif /*__cplusplus*/ + +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus*/ + +epicsShareFunc epicsMutexId epicsShareAPI epicsMutexCreate(void); +epicsShareFunc epicsMutexId epicsShareAPI epicsMutexMustCreate (void); +epicsShareFunc void epicsShareAPI epicsMutexDestroy(epicsMutexId id); +epicsShareFunc void epicsShareAPI epicsMutexUnlock(epicsMutexId id); +epicsShareFunc epicsMutexLockStatus epicsShareAPI epicsMutexLock( + epicsMutexId id); +#define epicsMutexMustLock(ID) assert((epicsMutexLock((ID))==epicsMutexLockOK)) +epicsShareFunc epicsMutexLockStatus epicsShareAPI epicsMutexLockWithTimeout( + epicsMutexId id, double timeOut); +epicsShareFunc epicsMutexLockStatus epicsShareAPI epicsMutexTryLock( + epicsMutexId id); +epicsShareFunc void epicsShareAPI epicsMutexShow( + epicsMutexId id,unsigned int level); + +/*NOTES: + epicsMutex MUST implement recursive locking + epicsMutex should implement priority inheritance and deletion safe +*/ + +#ifdef __cplusplus +} +#endif + +#include "osdMutex.h" + +/* The c++ implementation is inline calls to thye c code */ +#ifdef __cplusplus +// Automatically applies and releases the mutex. +// This is for use in situations where C++ exceptions are possible. +class epicsAutoMutex { +public: + epicsAutoMutex ( epicsMutex & ); + ~epicsAutoMutex (); +private: + epicsMutex &mutex; +}; + +inline epicsMutex::epicsMutex () +{ + this->id = epicsMutexCreate (); + if (this->id==0) { + throwWithLocation ( noMemory () ); + } +} + +inline epicsMutex::~epicsMutex () +{ + epicsMutexDestroy (this->id); +} + +inline void epicsMutex::lock () const +{ + epicsMutexLockStatus status; + status = epicsMutexLock (this->id); + if (status!=epicsMutexLockOK) { + throwWithLocation ( invalidSemaphore () ); + } +} + +inline bool epicsMutex::lock (double timeOut) const +{ + epicsMutexLockStatus status; + status = epicsMutexLockWithTimeout (this->id, timeOut); + if (status==epicsMutexLockOK) { + return true; + } else if (status==epicsMutexLockTimeout) { + return false; + } else { + throwWithLocation ( invalidSemaphore () ); + return false; // never here, compiler is happy + } +} + +inline bool epicsMutex::tryLock () const +{ + epicsMutexLockStatus status; + status = epicsMutexTryLock (this->id); + if (status==epicsMutexLockOK) { + return true; + } else if (status==epicsMutexLockTimeout) { + return false; + } else { + throwWithLocation ( invalidSemaphore () ); + return false; // never here, but compiler is happy + } +} + +inline void epicsMutex::unlock () const +{ + epicsMutexUnlock (this->id); +} + +inline void epicsMutex::show (unsigned level) const +{ + epicsMutexShow (this->id, level); +} + +inline epicsAutoMutex::epicsAutoMutex ( epicsMutex &mutexIn ) : + mutex ( mutexIn ) +{ + this->mutex.lock (); +} + +inline epicsAutoMutex::~epicsAutoMutex () +{ + this->mutex.unlock (); +} + +#endif /*__cplusplus*/ + +#endif /* epicsMutexh */