diff --git a/src/libCom/cxxTemplates/epicsGuard.h b/src/libCom/cxxTemplates/epicsGuard.h new file mode 100644 index 000000000..ea929aebb --- /dev/null +++ b/src/libCom/cxxTemplates/epicsGuard.h @@ -0,0 +1,77 @@ + +#ifndef epicsGuardh +#define epicsGuardh + +/* + * $Id$ + * + * Author: Jeffrey O. Hill + * + */ + +template < class T > class epicsGuardRelease; + +// Automatically applies and releases the mutex. +// This is for use in situations where C++ exceptions are possible. +template < class T > +class epicsGuard { +public: + epicsGuard ( T & ); + ~epicsGuard (); +private: + T & targetMutex; + friend class epicsGuardRelease < T >; + // epicsGuard ( const epicsGuard & ); visual c++ warning bug + // epicsGuard & operator = ( const epicsGuard & ); visual c++ warning bug +}; + +// Automatically releases and reapplies the mutex. +// This is for use in situations where C++ exceptions are possible. +template < class T > +class epicsGuardRelease { +public: + epicsGuardRelease ( epicsGuard < T > & ); + ~epicsGuardRelease (); +private: + epicsGuard < T > & guard; + // epicsGuardRelease ( const epicsGuardRelease & ); visual c++ warning bug + // epicsGuardRelease & operator = ( const epicsGuardRelease & ); visual c++ warning bug +}; + +class epicsMutexNOOP { +public: + void lock () {} + bool lock ( double timeOut ) { return true; } + bool tryLock () { return true; } + void unlock () {} + void show ( unsigned /* level */ ) const {} +}; + +template < class T > +inline epicsGuard < T > :: epicsGuard ( T & mutexIn ) : + targetMutex ( mutexIn ) +{ + this->targetMutex.lock (); +} + +template < class T > +inline epicsGuard < T > :: ~epicsGuard () +{ + this->targetMutex.unlock (); +} + +template < class T > +inline epicsGuardRelease < T > :: + epicsGuardRelease ( epicsGuard & guardIn ) : + guard ( guardIn ) +{ + this->guard.targetMutex.unlock (); +} + +template < class T > +inline epicsGuardRelease < T > :: ~epicsGuardRelease () +{ + this->guard.targetMutex.lock (); +} + +#endif // epicsGuardh diff --git a/src/libCom/cxxTemplates/epicsOnce.cpp b/src/libCom/cxxTemplates/epicsOnce.cpp new file mode 100644 index 000000000..21f6a48e5 --- /dev/null +++ b/src/libCom/cxxTemplates/epicsOnce.cpp @@ -0,0 +1,86 @@ + +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeff Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#define epicsExportSharedSymbols +#include "epicsMutex.h" +#include "epicsSingleton.h" +#include "epicsGuard.h" +#include "epicsOnce.h" +#include "tsFreeList.h" + +class epicsOnceImpl : public epicsOnce { +public: + epicsOnceImpl ( epicsOnceNotify & notifyIn ); + void * operator new ( size_t size ); + void operator delete ( void * pCadaver, size_t size ); +private: + epicsOnceNotify & notify; + bool onceFlag; + void destroy (); + void once (); + static epicsSingleton < epicsMutex > pMutex; + static epicsSingleton < tsFreeList < class epicsOnceImpl, 16 > > pFreeList; +}; + +epicsSingleton < epicsMutex > epicsOnceImpl::pMutex; + +epicsSingleton < tsFreeList < class epicsOnceImpl, 16 > > epicsOnceImpl::pFreeList; + +inline void * epicsOnceImpl::operator new ( size_t size ) +{ + return epicsOnceImpl::pFreeList->allocate ( size ); +} + +inline void epicsOnceImpl::operator delete ( void *pCadaver, size_t size ) +{ + epicsOnceImpl::pFreeList->release ( pCadaver, size ); +} + +inline epicsOnceImpl::epicsOnceImpl ( epicsOnceNotify & notifyIn ) : + notify ( notifyIn ), onceFlag ( false ) +{ +} + +void epicsOnceImpl::once () +{ + if ( ! this->onceFlag ) { + epicsGuard < epicsMutex > guard ( *this->pMutex ); + if ( ! this->onceFlag ) { + this->notify.initialize (); + this->onceFlag = true; + } + } +} + +void epicsOnceImpl::destroy () +{ + delete this; +} + +epicsOnce & epicsOnce::create ( epicsOnceNotify & notifyIn ) +{ + // free list throws exception in no memory situation + return * new epicsOnceImpl ( notifyIn ); +} + +epicsOnce::~epicsOnce () +{ +} + +epicsOnceNotify::~epicsOnceNotify () +{ +} \ No newline at end of file diff --git a/src/libCom/cxxTemplates/epicsOnce.h b/src/libCom/cxxTemplates/epicsOnce.h new file mode 100644 index 000000000..28b84df6e --- /dev/null +++ b/src/libCom/cxxTemplates/epicsOnce.h @@ -0,0 +1,37 @@ +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeff Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#ifndef epicsOnceh +#define epicsOnceh + +#include "shareLib.h" + +class epicsShareClass epicsOnceNotify { +public: + virtual ~epicsOnceNotify (); + virtual void initialize () = 0; +}; + +class epicsShareClass epicsOnce { +public: + static epicsOnce & create ( epicsOnceNotify & notifyIn ); + virtual ~epicsOnce (); + virtual void once () = 0; + virtual void destroy () = 0; +}; + +#endif // epicsOnceh + diff --git a/src/libCom/cxxTemplates/epicsSingleton.h b/src/libCom/cxxTemplates/epicsSingleton.h new file mode 100644 index 000000000..0780f9142 --- /dev/null +++ b/src/libCom/cxxTemplates/epicsSingleton.h @@ -0,0 +1,77 @@ + +/* + * $Id$ + * + * Author: Jeff O. Hill + * + */ + +#ifndef epicsSingleton_h +#define epicsSingleton_h + +#include "shareLib.h" + +class epicsShareClass epicsSingletonBase { +public: + epicsSingletonBase (); +protected: + virtual ~epicsSingletonBase (); + void lockedFactory (); + void * singletonPointer () const; +private: + void * pSingleton; + static class epicsMutex mutex; + virtual void * factory () = 0; +}; + +template +class epicsSingleton : private epicsSingletonBase { +public: + virtual ~epicsSingleton (); + T * operator -> (); + T & operator * (); +private: + void * factory (); +}; + +inline epicsSingletonBase::epicsSingletonBase () : pSingleton ( 0 ) +{ +} + +inline void * epicsSingletonBase::singletonPointer () const +{ + return this->pSingleton; +} + +template < class T > +inline epicsSingleton::~epicsSingleton () +{ + delete static_cast < T * > ( this->singletonPointer () ); +} + +template < class T > +inline T * epicsSingleton::operator -> () +{ + if ( ! this->singletonPointer () ) { + this->lockedFactory (); + } + return static_cast < T * > ( this->singletonPointer () ); +} + +template < class T > +inline T & epicsSingleton::operator * () +{ + if ( ! this->singletonPointer () ) { + this->lockedFactory (); + } + return * static_cast < T * > ( this->singletonPointer () ); +} + +template < class T > +void * epicsSingleton::factory () +{ + return static_cast < void * > ( new T ); +} + +#endif // epicsSingleton_h + diff --git a/src/libCom/cxxTemplates/epicsSingletonBase.cpp b/src/libCom/cxxTemplates/epicsSingletonBase.cpp new file mode 100644 index 000000000..f3eb2d37e --- /dev/null +++ b/src/libCom/cxxTemplates/epicsSingletonBase.cpp @@ -0,0 +1,30 @@ +/* + * $Id$ + * + * Author: Jeffrey O. Hill + * + */ + +#include + +#define epicsExportSharedSymbols +#include "epicsMutex.h" +#include "epicsGuard.h" +#include "epicsSingleton.h" + +epicsMutex epicsSingletonBase::mutex; + +epicsSingletonBase::~epicsSingletonBase () +{ +} + +void epicsSingletonBase::lockedFactory () +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + if ( ! this->pSingleton ) { + this->pSingleton = this->factory (); + if ( ! this->pSingleton ) { + throw std::bad_alloc (); + } + } +} \ No newline at end of file diff --git a/src/libCom/osi/epicsEvent.cpp b/src/libCom/osi/epicsEvent.cpp new file mode 100644 index 000000000..66f753218 --- /dev/null +++ b/src/libCom/osi/epicsEvent.cpp @@ -0,0 +1,86 @@ + +/* epicsMutex.c */ +/* Author: Jeff Hill */ +/***************************************************************** + COPYRIGHT NOTIFICATION +***************************************************************** + +(C) COPYRIGHT 1991 Regents of the University of California, +and the University of Chicago Board of Governors. + +This software was developed under a United States Government license +described on the COPYRIGHT_Combined file included as part +of this distribution. +**********************************************************************/ + +#include + +#define epicsExportSharedSymbols +#include "epicsEvent.h" + +// +// Its probably preferable to not make these inline because they are in +// the sharable library interface. The use of inline or not here is probably +// not an issue because all of this ends up in the operating system in system +// calls +// + +epicsEvent::epicsEvent ( epicsEventInitialState initial ) : + id ( epicsEventCreate ( initial ) ) +{ + if ( this->id == 0 ) { + throw std::bad_alloc (); + } +} + +epicsEvent::~epicsEvent () +{ + epicsEventDestroy ( this->id ); +} + +void epicsEvent::signal () +{ + epicsEventSignal ( this->id ); +} + +void epicsEvent::wait () +{ + epicsEventWaitStatus status; + status = epicsEventWait (this->id); + if (status!=epicsEventWaitOK) { + throwWithLocation ( invalidSemaphore () ); + } +} + +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; +} + +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; +} + +void epicsEvent::show ( unsigned level ) const +{ + epicsEventShow ( this->id, level ); +}