diff options
Diffstat (limited to 'src/base/tls.h.in')
-rw-r--r-- | src/base/tls.h.in | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/src/base/tls.h.in b/src/base/tls.h.in new file mode 100644 index 000000000..88969e250 --- /dev/null +++ b/src/base/tls.h.in @@ -0,0 +1,198 @@ +/********************* */ +/*! \file tls.h.in + ** \verbatim + ** Original author: ACSYS + ** Major contributors: Morgan Deters + ** Minor contributors (to current version): none + ** This file is part of the CVC4 project. + ** Copyright (c) 2009-2014 New York University and The University of Iowa + ** See the file COPYING in the top-level source directory for licensing + ** information.\endverbatim + ** + ** \brief Header to define CVC4_THREAD whether or not TLS is + ** supported by the compiler/runtime platform + ** + ** Header to define CVC4_THREAD whether or not TLS is supported by + ** the compiler/runtime platform. If not, an implementation based on + ** pthread_getspecific() / pthread_setspecific() is given. + **/ + +#include "cvc4_public.h" + +#ifndef __CVC4__TLS_H +#define __CVC4__TLS_H + +// A bit obnoxious: we have to take varargs to support multi-argument +// template types in the threadlocals. +// E.g. "CVC4_THREADLOCAL(hash_set<type, hasher>*)" fails otherwise, +// due to the embedded comma. +#if @CVC4_TLS_SUPPORTED@ +# define CVC4_THREADLOCAL(__type...) @CVC4_TLS@ __type +# define CVC4_THREADLOCAL_PUBLIC(__type...) @CVC4_TLS@ CVC4_PUBLIC __type +# define CVC4_THREADLOCAL_TYPE(__type...) __type +#else +# include <pthread.h> +# define CVC4_THREADLOCAL(__type...) ::CVC4::ThreadLocal< __type > +# define CVC4_THREADLOCAL_PUBLIC(__type...) CVC4_PUBLIC ::CVC4::ThreadLocal< __type > +# define CVC4_THREADLOCAL_TYPE(__type...) ::CVC4::ThreadLocal< __type > + +namespace CVC4 { + +template <class T, bool small> +class ThreadLocalImpl; + +template <class T> +class ThreadLocalImpl<T, true> { + pthread_key_t d_key; + + static void cleanup(void*) { + } + +public: + ThreadLocalImpl() { + pthread_key_create(&d_key, ThreadLocalImpl::cleanup); + } + + ThreadLocalImpl(const T& t) { + pthread_key_create(&d_key, ThreadLocalImpl::cleanup); + pthread_setspecific(d_key, const_cast<void*>(reinterpret_cast<const void*>(t))); + } + + ThreadLocalImpl(const ThreadLocalImpl& tl) { + pthread_key_create(&d_key, ThreadLocalImpl::cleanup); + pthread_setspecific(d_key, const_cast<void*>(reinterpret_cast<const void*>(static_cast<const T&>(tl)))); + } + + ThreadLocalImpl& operator=(const T& t) { + pthread_setspecific(d_key, const_cast<void*>(reinterpret_cast<const void*>(t))); + return *this; + } + ThreadLocalImpl& operator=(const ThreadLocalImpl& tl) { + pthread_setspecific(d_key, const_cast<void*>(reinterpret_cast<const void*>(static_cast<const T&>(tl)))); + return *this; + } + + operator T() const { + return static_cast<T>(reinterpret_cast<size_t>(pthread_getspecific(d_key))); + } +};/* class ThreadLocalImpl<T, true> */ + +template <class T> +class ThreadLocalImpl<T*, true> { + pthread_key_t d_key; + + static void cleanup(void*) { + } + +public: + ThreadLocalImpl() { + pthread_key_create(&d_key, ThreadLocalImpl::cleanup); + } + + ThreadLocalImpl(const T* t) { + pthread_key_create(&d_key, ThreadLocalImpl::cleanup); + pthread_setspecific(d_key, const_cast<void*>(reinterpret_cast<const void*>(t))); + } + + ThreadLocalImpl(const ThreadLocalImpl& tl) { + pthread_key_create(&d_key, ThreadLocalImpl::cleanup); + pthread_setspecific(d_key, const_cast<void*>(reinterpret_cast<const void*>(static_cast<const T*>(tl)))); + } + + ThreadLocalImpl& operator=(const T* t) { + pthread_setspecific(d_key, const_cast<void*>(reinterpret_cast<const void*>(t))); + return *this; + } + ThreadLocalImpl& operator=(const ThreadLocalImpl& tl) { + pthread_setspecific(d_key, const_cast<void*>(reinterpret_cast<const void*>(static_cast<const T*>(tl)))); + return *this; + } + + operator T*() const { + return static_cast<T*>(pthread_getspecific(d_key)); + } + + T operator*() { + return *static_cast<T*>(pthread_getspecific(d_key)); + } + T* operator->() { + return static_cast<T*>(pthread_getspecific(d_key)); + } +};/* class ThreadLocalImpl<T*, true> */ + +template <class T> +class ThreadLocalImpl<T, false> { +};/* class ThreadLocalImpl<T, false> */ + +template <class T> +class ThreadLocal : public ThreadLocalImpl<T, sizeof(T) <= sizeof(void*)> { + typedef ThreadLocalImpl<T, sizeof(T) <= sizeof(void*)> super; + +public: + ThreadLocal() : super() {} + ThreadLocal(const T& t) : super(t) {} + ThreadLocal(const ThreadLocal<T>& tl) : super(tl) {} + + ThreadLocal<T>& operator=(const T& t) { + return static_cast< ThreadLocal<T>& >(super::operator=(t)); + } + ThreadLocal<T>& operator=(const ThreadLocal<T>& tl) { + return static_cast< ThreadLocal<T>& >(super::operator=(tl)); + } +};/* class ThreadLocal<T> */ + +template <class T> +class ThreadLocal<T*> : public ThreadLocalImpl<T*, sizeof(T*) <= sizeof(void*)> { + typedef ThreadLocalImpl<T*, sizeof(T*) <= sizeof(void*)> super; + +public: + ThreadLocal() : super() {} + ThreadLocal(T* t) : super(t) {} + ThreadLocal(const ThreadLocal<T*>& tl) : super(tl) {} + + ThreadLocal<T*>& operator=(T* t) { + return static_cast< ThreadLocal<T*>& >(super::operator=(t)); + } + ThreadLocal<T*>& operator=(const ThreadLocal<T*>& tl) { + return static_cast< ThreadLocal<T*>& >(super::operator=(tl)); + } + // special operators for pointers + T& operator*() { + return *static_cast<T*>(*this); + } + const T& operator*() const { + return *static_cast<const T*>(*this); + } + T* operator->() { + return static_cast<T*>(*this); + } + const T* operator->() const { + return static_cast<const T*>(*this); + } + T* operator++() { + T* p = *this; + *this = ++p; + return p; + } + T* operator++(int) { + T* p = *this; + *this = p + 1; + return p; + } + T* operator--() { + T* p = *this; + *this = --p; + return p; + } + T* operator--(int) { + T* p = *this; + *this = p - 1; + return p; + } +};/* class ThreadLocal<T*> */ + +}/* CVC4 namespace */ + +#endif /* @CVC4_TLS_SUPPORTED@ */ + +#endif /* __CVC4__TLS_H */ |