From 3bdf883d0490d81f77ece834d1f1dd45ecdcf082 Mon Sep 17 00:00:00 2001 From: "Hiram R. Chirino" Date: Thu, 2 Mar 2006 18:29:33 +0000 Subject: [PATCH] BSDish lic. we can redistribut this code. git-svn-id: https://svn.apache.org/repos/asf/incubator/activemq/trunk@382462 13f79535-47bb-0310-9956-ffa450edef68 --- openwire-cpp/src/util/ifr/v1/ap.hpp | 85 +++++ openwire-cpp/src/util/ifr/v1/atomic.hpp | 122 +++++++ openwire-cpp/src/util/ifr/v1/namespace.hpp | 35 ++ openwire-cpp/src/util/ifr/v1/p.hpp | 351 +++++++++++++++++++++ openwire-cpp/src/util/ifr/v1/platform.hpp | 122 +++++++ 5 files changed, 715 insertions(+) create mode 100755 openwire-cpp/src/util/ifr/v1/ap.hpp create mode 100755 openwire-cpp/src/util/ifr/v1/atomic.hpp create mode 100755 openwire-cpp/src/util/ifr/v1/namespace.hpp create mode 100755 openwire-cpp/src/util/ifr/v1/p.hpp create mode 100755 openwire-cpp/src/util/ifr/v1/platform.hpp diff --git a/openwire-cpp/src/util/ifr/v1/ap.hpp b/openwire-cpp/src/util/ifr/v1/ap.hpp new file mode 100755 index 0000000000..53425263d7 --- /dev/null +++ b/openwire-cpp/src/util/ifr/v1/ap.hpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006, David Fahlander + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of slurk.org nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef IFR_V1_AP_HPP_ +#define IFR_V1_AP_HPP_ + +#include +#include +#include +#include + +namespace ifr { + namespace v1 { + +template class ap { +private: + struct Array : refcounted { + // Members + size_t size_; + p* array_; + // Construct + Array (size_t size) : size_ (size) { + array_ = (p*) malloc (size * sizeof(p)); + if (array_ == NULL) { + throw std::bad_alloc (); + } + memset (array_, 0, sizeof (p) * size); + } + virtual ~Array () { + for (size_t i=0; i(p_help::get_obj (array_[i])), reinterpret_cast (NULL)); + } + } + free (array_); + } + }; + p a; +public: + ap () {} + ap& operator = (class NullClass* nullclass) { + assert (nullclass == NULL); + a = NULL; + return *this; + } + ap (size_t size) : a (new Array (size)) {} + p& operator [] (size_t pos) { + return a->array_[pos]; + } + const p& operator [] (size_t pos) const { + return array_[pos]; + } + size_t size() const { + return a->size_; + } +}; + + } +} + +#endif // IFR_V1_AP_HPP_ diff --git a/openwire-cpp/src/util/ifr/v1/atomic.hpp b/openwire-cpp/src/util/ifr/v1/atomic.hpp new file mode 100755 index 0000000000..72edca954c --- /dev/null +++ b/openwire-cpp/src/util/ifr/v1/atomic.hpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2005-2006, David Fahlander + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of slurk.org nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef IFR_V1_ATOMIC_HPP_ +#define IFR_V1_ATOMIC_HPP_ + +#include "platform.hpp" + +namespace ifr { + namespace v1 { + class atomic { + private: + // Invalidate copy constructor and assignment operator + atomic (const atomic&); + atomic& operator= (const atomic&); + +#ifdef BUN_USE_PTHREAD + protected: + long counter_; + pthread_mutex_t m_; + public: + atomic () : counter_ (0) { + pthread_mutex_init(&m_, NULL); + } + atomic (long init_value) : counter_ (init_value) { + pthread_mutex_init(&m_, NULL); + } + ~atomic () { + pthread_mutex_destroy(&m_); + } + void increment() { + pthread_mutex_lock(&m_); + ++counter_; + pthread_mutex_unlock(&m_); + } + bool decrement() { + pthread_mutex_lock(&m_); + if (!--counter_) { + pthread_mutex_unlock(&m_); + return true; + } else { + pthread_mutex_unlock(&m_); + return false; + } + } + long get_value() const { + pthread_mutex_lock(&m_); + long retval = counter_; + pthread_mutex_unlock(&m_); + return retval; + } + static const char* implementation () { + return "pthread"; + } +#elif defined BUN_USE_GNU_ATOMIC + protected: + mutable _Atomic_word counter_; + public: + atomic () : counter_ (0) {} + atomic (long init_value) : counter_ (init_value) {} + void increment() { + __atomic_add(&counter_, 1); + } + bool decrement() { + return (__exchange_and_add(&counter_, -1) == 1); + } + long get_value() const { + return __exchange_and_add(&counter_, 0); + } + static const char* implementation () { + return "gnu atomic"; + } +#elif defined BUN_USE_INTERLOCKED + protected: + mutable long counter_; + public: + atomic () : counter_ (0) {} + atomic (long init_value) : counter_ (init_value) {} + void increment() { + _InterlockedIncrement (&counter_); + } + bool decrement() { + return (_InterlockedDecrement (&counter_) == 0); + } + long get_value() const { + return _InterlockedExchangeAdd (&counter_, 0); + } + static const char* implementation () { + return "windows interlocked"; + } +#else +#error "Atomic Operations Unsupported" +#endif + }; + } +} +#endif // IFR_V1_ATOMIC_HPP_ + diff --git a/openwire-cpp/src/util/ifr/v1/namespace.hpp b/openwire-cpp/src/util/ifr/v1/namespace.hpp new file mode 100755 index 0000000000..6e74a5acf3 --- /dev/null +++ b/openwire-cpp/src/util/ifr/v1/namespace.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2005-2006, David Fahlander + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of slurk.org nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef IFR_V1_NAMESPACE_HPP_ +#define IFR_V1_NAMESPACE_HPP_ + +namespace ifr { + using namespace v1; +} + +#endif // IFR_V1_NAMESPACE_HPP_ diff --git a/openwire-cpp/src/util/ifr/v1/p.hpp b/openwire-cpp/src/util/ifr/v1/p.hpp new file mode 100755 index 0000000000..608bf9c964 --- /dev/null +++ b/openwire-cpp/src/util/ifr/v1/p.hpp @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2005-2006, David Fahlander + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of slurk.org nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef IFR_V1_P_HPP_ +#define IFR_V1_P_HPP_ + +#include "atomic.hpp" + +namespace ifr { + namespace v1 { + // Forward declaration of p + template class p; + + // This is an internal class that helps getting the private member obj_ from p. + // The normal thing would be to use "friend" but that is not possible since + // there are template methods and classes that must be friends. + struct p_help { + template static void* get_obj (const p& sp) { + return sp.obj_; + } + }; + + /** Generic thread-safe reference counted smart pointer for any type. + */ + template class p { + friend struct p_help; + private: // Should be private. But public because p cannot be friend of p on GCC compiler. + void* obj_; + public: + /** Default constructor. Initiates pointer to zero. + */ + p () : obj_ (0) {} + /** Constructor taking ownership of given pointer. Caller looses the ownership of given object. + */ + p (T* obj) { + if (obj) { + obj_ = smartptr_assign (reinterpret_cast(obj), reinterpret_cast(NULL)); + } else { + obj_ = NULL; + } + } + p (T*& obj) { + // This constructor is not ment to compile! + // It is here to generate an error when trying to assign a p from + // an lvalue. p must only be assigned directly from the return value + // of the new() operator. + // + // Compiler will not complain about the error text below, but will complain + // about "ambigous call to overloaded function"... + ERROR_CANNOT_ASSIGN_P_FROM_LVALUE(obj); + } + + /** Destructor. Decrements reference count and eventually deletes the object. + */ + ~p () { + if (obj_) smartptr_release (reinterpret_cast(obj_), reinterpret_cast(NULL)); + } + /** Copy Constructor. Increments reference count since we also own the object now. + */ + p (const p& other) { + obj_ = other.obj_; + if (obj_) smartptr_addref (reinterpret_cast(obj_), reinterpret_cast(NULL)); + } + /** Copy Constructor for p of compatible class. + Increments reference count since we also own the object now. + */ + template p (const p& other) { + obj_ = smartptr_convert( + (T*)NULL, + (T*)NULL, + reinterpret_cast(p_help::get_obj(other)), + (DerivedClass*)NULL); + if (obj_) smartptr_addref (reinterpret_cast(obj_), reinterpret_cast(NULL)); + } + /** Assignment operator. Increments reference count since we also own the object now. + Decrements refcount of the old object because we don't own that anymore. + */ + p& operator = (const p& other) { + if (other.obj_) smartptr_addref (reinterpret_cast(other.obj_), reinterpret_cast(NULL)); + if (obj_) smartptr_release (reinterpret_cast(obj_), reinterpret_cast(NULL)); + obj_ = other.obj_; + return *this; + } + /** Assignment operator for p of compatible class. + Increments reference count since we also own the object now. Decrements refcount + of the old object because we don't own that anymore. + */ + template p& operator = (const p& other) { + if (p_help::get_obj(other)) smartptr_addref (reinterpret_cast(p_help::get_obj(other)), reinterpret_cast(NULL)); + if (obj_) smartptr_release (reinterpret_cast(obj_), reinterpret_cast(NULL)); + obj_ = smartptr_convert((T*)NULL, (T*)NULL, reinterpret_cast(p_help::get_obj(other)), (DerivedClass*)NULL); + return *this; + } + /** Assignment operator taking ownership of given pointer. + Caller looses the ownership of given object. Decrements refcount + of the old object because we don't own that anymore. + */ + p& operator = (T* obj) { + if (obj_) smartptr_release (reinterpret_cast(obj_), reinterpret_cast(NULL)); + if (obj) { + obj_ = smartptr_assign (reinterpret_cast(obj), reinterpret_cast(NULL)); + } else { + obj_ = NULL; + } + return *this; + } + p& operator = (T*& obj) { + // This constructor is not ment to compile! + // It is here to generate an error when trying to assign a p from + // an lvalue. p must only be assigned directly from the return value + // of the new() operator. + // + // Compiler will not complain about the error text below, but will complain + // about "ambigous call to overloaded function"... + ERROR_CANNOT_ASSIGN_P_FROM_LVALUE(obj); + return *this; + } + /** Member reach operator. + */ + T* operator -> () const {return smartptr_get (reinterpret_cast(obj_), reinterpret_cast(NULL));} + /** Reference reach operator. + */ + T& operator * () const { + return *smartptr_get (reinterpret_cast(obj_), reinterpret_cast(NULL)); + } + /** Equal Operator. Compares the container's pointer value. Used in order to insert the p in std::maps and std::set. + */ + bool operator == (const p& other) const {return obj_ == other.obj_;} + /** Equal Operator. Compares the pointer value. Used mainly to compare with NULL. + */ + bool operator == (const T* other) const { + return smartptr_get(reinterpret_cast(obj_), reinterpret_cast(NULL)) == other; + } + /** No-Equal Operator. Compares the container's pointer value. Used in order to insert the p in std collections. + */ + bool operator != (const p& other) const {return obj_ != other.obj_;} + /** No-Equal Operator. Compares the pointer value. Used mainly to compare with NULL. + */ + bool operator != (const T* other) const { + return smartptr_get(reinterpret_cast(obj_), reinterpret_cast(NULL)) != other; + } + /** Less Operator. Compares the container's pointer value. Used in order to insert the p in std collections. + */ + bool operator < (const p& other) const { + return smartptr_get(reinterpret_cast(obj_), reinterpret_cast(NULL)) < + smartptr_get(reinterpret_cast(other.obj_), reinterpret_cast(NULL)); + } + }; + + /** + */ + template long get_refcount (const p& ptr) { + return smartptr_get_refcount (reinterpret_cast(p_help::get_obj(ptr)), (const T*) NULL); + } + + /** + */ + template const T* getptr (const p& ptr) { + return smartptr_get (reinterpret_cast(p_help::get_obj(ptr)), (T*) NULL); + } + + /** + */ + template T* getptr (p& ptr) { + return smartptr_get (reinterpret_cast(p_help::get_obj(ptr)), (T*) NULL); + } + + /** + */ + template p encapsulate (T* ptr) { + return smartptr_encapsulate (ptr, (T*) NULL); + } + + /** + */ + template struct PointerHolder { + atomic refcount_; + T* obj_; + PointerHolder (T* obj, long initcount) : refcount_ (initcount), obj_ (obj) {} + void addref () { + refcount_.increment(); + } + void release () { + if (refcount_.decrement()) { + delete obj_; + delete this; + } + } + }; + + + /* Overloaded smartptr functions for void + */ + template void* smartptr_assign (T* obj, void*) { + return new PointerHolder (obj, 1); + } + template void smartptr_addref (T* obj, void*) { + reinterpret_cast*>(obj)->refcount_.increment(); + } + template void smartptr_release (T* obj, void*) { + reinterpret_cast*>(obj)->release(); + } + template T* smartptr_get (T* obj, void*) { + return (obj ? reinterpret_cast*>(obj)->obj_ : NULL); + } + template Base* smartptr_convert (Base*, void*, Derived* obj, void*) { + return obj; + } + template long smartptr_get_refcount (const T* obj, const void*) { + return reinterpret_cast*>(obj)->refcount_.get_value(); + } + template T* smartptr_encapsulate (T* obj, void*) { + // This constructor is not ment to compile! + // It is here to generate an error when trying to call encapsulate() on + // an instance of a class that is not possible to re-encapsulate into a smart pointer. + // This error can occur if the class does not derive from recounted, IUnknown + // or any other class that supports re-encapsulation into a smart pointer. + ERROR_TYPE_NOT_POSSIBLE_TO_ENCAPSULATE(obj); + } + + + /** Base class that, when derived from, makes your class + * Faster to assign to a p. + * Faster to delete when your refcount reaches zero. + * Possible to use with encapsulate(). + */ + class refcounted { + friend void addref (refcounted*); + friend void release (refcounted*); + friend long get_refcount (const refcounted*); + private: + atomic refcount_; + public: + refcounted() : refcount_ (1) {} + virtual ~refcounted() {} + }; + + inline void addref (refcounted* o) { + o->refcount_.increment(); + } + inline void release (refcounted* o) { + if (o->refcount_.decrement()) delete o; + } + inline long get_refcount (const refcounted* o) { + return o->refcount_.get_value(); + } + + /* Overloaded smartptr functions for refcounted + */ + template T* smartptr_assign (T* obj, refcounted*) { + return obj; + } + template void smartptr_addref (T* obj, refcounted*) { + addref (obj); + } + template void smartptr_release (T* obj, refcounted*) { + release (obj); + } + template T* smartptr_get (T* obj, refcounted*) { + return obj; + } + template Base* smartptr_convert (Base*, refcounted*, Derived* obj, refcounted*) { + return obj; + } + template Base* smartptr_convert (Base*, void*, Derived* obj, refcounted*) { + // This overloaded method must not compile. + // It is here to generate an error when trying to mix instances of refcounted and non-refcounted. + // If you get a compilation error here, you should derive from refcount already in given + // base class and not only in given subclass. + // If that is not possible, your subclass must not derive from refcounted. + ERROR_CANNOT_ASSIGN_REFCOUNTED_INSTANCE_TO_NON_REFCOUNTED_BASE((Base*) NULL, obj); + return NULL; + } + template long smartptr_get_refcount (const T* obj, const refcounted*) { + return get_refcount (obj); + } + template T* smartptr_encapsulate (T* obj, refcounted*) { + addref(obj); + return obj; + } + } +} + +/** IUnknown - Makes p<> hold COM objects according to it's standard. +*/ +struct IUnknown; + +namespace bun { + namespace v1 { + /* Overloaded smartptr functions for IUnknown + */ + template T* smartptr_assign (T* obj, IUnknown*) { + return obj; + } + template void smartptr_addref (T* obj, IUnknown*) { + obj->AddRef(); + } + template void smartptr_release (T* obj, IUnknown*) { + obj->Release(); + } + template T* smartptr_get (T* obj, IUnknown*) { + return obj; + } + template Base* smartptr_convert (Base*, IUnknown*, Derived* obj, IUnknown*) { + return obj; + } + template Base* smartptr_convert (Base*, void*, Derived* obj, IUnknown*) { + // This overloaded method must not compile. + // It is here to generate an error when trying to mix instances of IUnknown and non-IUnknown. + // If you get a compilation error here, you should derive from IUnknown already in given + // base class and not only in given subclass. + // If that is not possible, your subclass must not derive from IUnknown. + ERROR_CANNOT_ASSIGN_IUNKNOWN_INSTANCE_TO_NON_IUNKNOWN_BASE((Base*) NULL, obj); + return NULL; + } + template long smartptr_get_refcount (const T* obj, const IUnknown*) { + const_cast(obj)->AddRef(); + return (long) const_cast(obj)->Release(); + } + template T* smartptr_encapsulate (T* obj, IUnknown*) { + obj->AddRef(); + return obj; + } + } +} + +#endif // IFR_V1_P_HPP_ diff --git a/openwire-cpp/src/util/ifr/v1/platform.hpp b/openwire-cpp/src/util/ifr/v1/platform.hpp new file mode 100755 index 0000000000..ed42484562 --- /dev/null +++ b/openwire-cpp/src/util/ifr/v1/platform.hpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2005-2006, David Fahlander + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. Redistributions in binary + * form must reproduce the above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or other materials provided + * with the distribution. Neither the name of slurk.org nor the names + * of its contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef IFR_V1_PLATFORM_HPP_ +#define IFR_V1_PLATFORM_HPP_ + +// GCC +#if defined __GNUC__ +#ifndef STDCALL +#define STDCALL __attribute__ ((stdcall)) +#endif +// Microsoft Visual C++ +#elif defined _MSC_VER +#define STDCALL __stdcall +#endif + +#if !defined (_WIN64) && defined (WIN64) +#define _WIN64 +#endif + +#if !defined (_WIN32) && defined (WIN32) +#define _WIN32 +#endif + +#if !defined (_WINDOWS) && (defined (_WIN32) || defined (_WIN64)) +#define _WINDOWS +#endif + +#if (defined __GNUC__) +#define BUN_USE_GNU_ATOMIC +#include +#include +#ifdef __GLIBCXX__ +using __gnu_cxx::__atomic_add; +using __gnu_cxx::__exchange_and_add; +#endif +#elif (!defined __GNUC__) && ( defined _WINDOWS ) // Non-GCC compiler, windows platform: +#define BUN_USE_INTERLOCKED +#else // Compiler or processor for which we got no atomic count support +#define BUN_USE_PTHREAD +#include +#endif + + + +#ifdef _WINDOWS + +// Defining Critical Section, needed for windows critical section handling. +// We dont want to include windows.h since it contains TOO much dirt. +extern "C" { + #ifdef __GNUC__ + // GNU C Compiler + struct _CRITICAL_SECTION; + typedef struct _CRITICAL_SECTION CRITICAL_SECTION; + #else + // Other Windows Compilers. Same structure as in windows.h + struct _RTL_CRITICAL_SECTION; + typedef struct _RTL_CRITICAL_SECTION CRITICAL_SECTION; + #ifdef _MSC_VER + // Interlocked functions. Only for MSVC Compiler. GCC uses inline assembler. + // Todo: Support Borland and other c++ compilers on windows with either inline + // assember or using Interlocked functions. + long __cdecl _InterlockedIncrement(volatile long*); + long __cdecl _InterlockedDecrement(volatile long*); + long __cdecl _InterlockedExchangeAdd (volatile long*, long); + #pragma intrinsic( _InterlockedIncrement ) + #pragma intrinsic( _InterlockedDecrement ) + #pragma intrinsic( _InterlockedExchangeAdd ) + #endif + #endif + // Declare CriticalSection functions: + __declspec(dllimport) void STDCALL InitializeCriticalSection (CRITICAL_SECTION*); + __declspec(dllimport) void STDCALL EnterCriticalSection (CRITICAL_SECTION*); + __declspec(dllimport) void STDCALL LeaveCriticalSection (CRITICAL_SECTION*); + __declspec(dllimport) void STDCALL DeleteCriticalSection (CRITICAL_SECTION*); + + namespace bun { + namespace v1 { + namespace windows { + struct CriticalSection { + void* DebugInfo; + long LockCount; + long RecursionCount; + void* OwningThread; + void* LockSemaphore; + unsigned long SpinCount; + operator CRITICAL_SECTION* () { + return reinterpret_cast(this); + } + }; + } + } + } +} +#endif + +#endif // IFR_V1_PLATFORM_HPP_ +