#ifndef __SSIATOMICS_HH__
#define __SSIATOMICS_HH__
/******************************************************************************/
/* */
/* X r d S s i A t o m i c s . h h */
/* */
/* (c) 2015 by the Board of Trustees of the Leland Stanford, Jr., University */
/* Produced by Andrew Hanushevsky for Stanford University under contract */
/* DE-AC02-76-SFO0515 with the Department of Energy */
/* */
/* This file is part of the XRootD software suite. */
/* */
/* XRootD is free software: you can redistribute it and/or modify it under */
/* the terms of the GNU Lesser General Public License as published by the */
/* Free Software Foundation, either version 3 of the License, or (at your */
/* option) any later version. */
/* */
/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License */
/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
/* COPYING (GPL license). If not, see . */
/* */
/* The copyright holder's institutional names and contributor's names may not */
/* be used to endorse or promote products derived from this software without */
/* specific prior written permission of the institution or contributor. */
/******************************************************************************/
#include
#undef NEED_ATOMIC_MUTEX
//-----------------------------------------------------------------------------
//! Use native atomics at the c11 or higher level (-std=c++0x -lstdc++)
//-----------------------------------------------------------------------------
#if __cplusplus >= 201103L
#include
#define Atomic(type) std::atomic
#define Atomic_IMP "C++11"
#define Atomic_BEG(x)
#define Atomic_DEC(x) x.fetch_sub(1,std::memory_order_relaxed)
#define Atomic_GET(x) x.load(std::memory_order_relaxed)
#define Atomic_GET_STRICT(x) x.load(std::memory_order_acquire)
#define Atomic_INC(x) x.fetch_add(1,std::memory_order_relaxed)
#define Atomic_SET(x,y) x.store(y,std::memory_order_relaxed)
#define Atomic_SET_STRICT(x,y) x.store(y,std::memory_order_release)
#define Atomic_ZAP(x) x.store(0,std::memory_order_relaxed)
#define Atomic_END(x)
//-----------------------------------------------------------------------------
//! Use new gcc builtins at 4.7 or above
//-----------------------------------------------------------------------------
#elif __GNUC__ == 4 && __GNUC_MINOR__ > 6
#define Atomic(type) type
#define Atomic_IMP "gnu-atomic"
#define Atomic_BEG(x)
#define Atomic_DEC(x) __atomic_fetch_sub(&x,1,__ATOMIC_RELAXED)
#define Atomic_GET(x) __atomic_load_n (&x, __ATOMIC_RELAXED)
#define Atomic_GET_STRICT(x) __atomic_load_n (&x, __ATOMIC_ACQUIRE)
#define Atomic_INC(x) __atomic_fetch_add(&x,1,__ATOMIC_RELAXED)
#define Atomic_SET(x,y) __atomic_store_n (&x,y,__ATOMIC_RELAXED)
#define Atomic_SET_STRICT(x,y) __atomic_store_n (&x,y,__ATOMIC_RELEASE)
#define Atomic_ZAP(x) __atomic_store_n (&x,0,__ATOMIC_RELAXED)
#define Atomic_END(x)
//-----------------------------------------------------------------------------
//! Use old-style gcc builtins if they area available. The STRICT variants
//! are only effective on strict memory compliant machines (e.g. x86, SPARC).
//! This doesn't get resolved until gcc 4.7, sigh.
//-----------------------------------------------------------------------------
#elif HAVE_ATOMICS
#define Atomic(type) type
#define Atomic_IMP "gnu-sync"
#define Atomic_BEG(x)
#define Atomic_DEC(x) __sync_fetch_and_sub(&x, 1)
#define Atomic_GET(x) __sync_fetch_and_or (&x, 0)
#define Atomic_GET_STRICT(x) __sync_fetch_and_or (&x, 0)
#define Atomic_INC(x) __sync_fetch_and_add(&x, 1)
#define Atomic_SET(x,y) x=y,__sync_synchronize()
#define Atomic_SET_STRICT(x,y) __sync_synchronize(),x=y,__sync_synchronize()
#define Atomic_ZAP(x) __sync_fetch_and_and(&x, 0)
#define Atomic_END(x)
//-----------------------------------------------------------------------------
//! Use ordinary operators since the program needs to use mutexes
//-----------------------------------------------------------------------------
#else
#define NEED_ATOMIC_MUTEX 1
#define Atomic_IMP "missing"
#define Atomic(type) type
#define Atomic_BEG(x) pthread_mutex_lock(x)
#define Atomic_DEC(x) x--
#define Atomic_GET(x) x
#define Atomic_INC(x) x++
#define Atomic_SET(x,y) x = y
#define Atomic_ZAP(x) x = 0
#define Atomic_END(x) pthread_mutex_unlock(x)
#endif
/******************************************************************************/
/* X r d S s i M u t e x */
/******************************************************************************/
#include
class XrdSsiMutex
{
public:
inline bool TryLock() {return pthread_mutex_trylock( &cs ) == 0;}
inline void Lock() {pthread_mutex_lock(&cs);}
inline void UnLock() {pthread_mutex_unlock(&cs);}
enum MutexType {Simple = 0, Recursive = 1};
XrdSsiMutex(MutexType mt=Simple)
{int rc;
if (mt == Simple) rc = pthread_mutex_init(&cs, NULL);
else {pthread_mutexattr_t attr;
if (!(rc = pthread_mutexattr_init(&attr)))
{pthread_mutexattr_settype(&attr,
PTHREAD_MUTEX_RECURSIVE);
rc = pthread_mutex_init(&cs, &attr);
}
}
if (rc) throw Errno2Text(rc);
}
~XrdSsiMutex() {pthread_mutex_destroy(&cs);}
protected:
pthread_mutex_t cs;
private:
const char* Errno2Text(int ecode);
};
/******************************************************************************/
/* X r d S s i M u t e x M o n */
/******************************************************************************/
class XrdSsiMutexMon
{
public:
inline void Lock(XrdSsiMutex *mutex)
{if (mtx) {if (mtx != mutex) mtx->UnLock();
else return;
}
mutex->Lock();
mtx = mutex;
};
inline void Lock(XrdSsiMutex &mutex) {Lock(&mutex);}
inline void Reset() {mtx = 0;}
inline void UnLock() {if (mtx) {mtx->UnLock(); mtx = 0;}}
XrdSsiMutexMon(XrdSsiMutex *mutex=0)
{if (mutex) mutex->Lock();
mtx = mutex;
}
XrdSsiMutexMon(XrdSsiMutex &mutex)
{mutex.Lock();
mtx = &mutex;
}
~XrdSsiMutexMon() {if (mtx) UnLock();}
private:
XrdSsiMutex *mtx;
};
#endif