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
This commit is contained in:
Hiram R. Chirino 2006-03-02 18:29:33 +00:00
parent 95d0dec008
commit 3bdf883d04
5 changed files with 715 additions and 0 deletions

View File

@ -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 <new>
#include <cstdlib>
#include <cassert>
#include <util/ifr/p>
namespace ifr {
namespace v1 {
template <typename T> class ap {
private:
struct Array : refcounted {
// Members
size_t size_;
p<T>* array_;
// Construct
Array (size_t size) : size_ (size) {
array_ = (p<T>*) malloc (size * sizeof(p<T>));
if (array_ == NULL) {
throw std::bad_alloc ();
}
memset (array_, 0, sizeof (p<T>) * size);
}
virtual ~Array () {
for (size_t i=0; i<size_; ++i) {
if (array_[i] != NULL) {
smartptr_release (reinterpret_cast<T*>(p_help::get_obj (array_[i])), reinterpret_cast<T*> (NULL));
}
}
free (array_);
}
};
p<Array> a;
public:
ap () {}
ap& operator = (class NullClass* nullclass) {
assert (nullclass == NULL);
a = NULL;
return *this;
}
ap (size_t size) : a (new Array (size)) {}
p<T>& operator [] (size_t pos) {
return a->array_[pos];
}
const p<T>& operator [] (size_t pos) const {
return array_[pos];
}
size_t size() const {
return a->size_;
}
};
}
}
#endif // IFR_V1_AP_HPP_

View File

@ -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_

View File

@ -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_

View File

@ -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 <typename T> 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 <typename T> static void* get_obj (const p<T>& sp) {
return sp.obj_;
}
};
/** Generic thread-safe reference counted smart pointer for any type.
*/
template <typename T> class p {
friend struct p_help;
private: // Should be private. But public because p<A> cannot be friend of p<B> 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<T*>(obj), reinterpret_cast<T*>(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<T> from
// an lvalue. p<T> 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<T*>(obj_), reinterpret_cast<T*>(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<T*>(obj_), reinterpret_cast<T*>(NULL));
}
/** Copy Constructor for p of compatible class.
Increments reference count since we also own the object now.
*/
template <class DerivedClass> p (const p<DerivedClass>& other) {
obj_ = smartptr_convert(
(T*)NULL,
(T*)NULL,
reinterpret_cast<DerivedClass*>(p_help::get_obj(other)),
(DerivedClass*)NULL);
if (obj_) smartptr_addref (reinterpret_cast<T*>(obj_), reinterpret_cast<T*>(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<T*>(other.obj_), reinterpret_cast<T*>(NULL));
if (obj_) smartptr_release (reinterpret_cast<T*>(obj_), reinterpret_cast<T*>(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 <class DerivedClass> p& operator = (const p<DerivedClass>& other) {
if (p_help::get_obj(other)) smartptr_addref (reinterpret_cast<DerivedClass*>(p_help::get_obj(other)), reinterpret_cast<DerivedClass*>(NULL));
if (obj_) smartptr_release (reinterpret_cast<T*>(obj_), reinterpret_cast<T*>(NULL));
obj_ = smartptr_convert((T*)NULL, (T*)NULL, reinterpret_cast<DerivedClass*>(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<T*>(obj_), reinterpret_cast<T*>(NULL));
if (obj) {
obj_ = smartptr_assign (reinterpret_cast<T*>(obj), reinterpret_cast<T*>(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<T> from
// an lvalue. p<T> 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<T*>(obj_), reinterpret_cast<T*>(NULL));}
/** Reference reach operator.
*/
T& operator * () const {
return *smartptr_get (reinterpret_cast<T*>(obj_), reinterpret_cast<T*>(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<T*>(obj_), reinterpret_cast<T*>(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<T*>(obj_), reinterpret_cast<T*>(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<T*>(obj_), reinterpret_cast<T*>(NULL)) <
smartptr_get(reinterpret_cast<T*>(other.obj_), reinterpret_cast<T*>(NULL));
}
};
/**
*/
template <typename T> long get_refcount (const p<T>& ptr) {
return smartptr_get_refcount (reinterpret_cast<const T*>(p_help::get_obj(ptr)), (const T*) NULL);
}
/**
*/
template <typename T> const T* getptr (const p<T>& ptr) {
return smartptr_get (reinterpret_cast<T*>(p_help::get_obj(ptr)), (T*) NULL);
}
/**
*/
template <typename T> T* getptr (p<T>& ptr) {
return smartptr_get (reinterpret_cast<T*>(p_help::get_obj(ptr)), (T*) NULL);
}
/**
*/
template <typename T> p<T> encapsulate (T* ptr) {
return smartptr_encapsulate (ptr, (T*) NULL);
}
/**
*/
template <typename T> 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 <typename T> void* smartptr_assign (T* obj, void*) {
return new PointerHolder<T> (obj, 1);
}
template <typename T> void smartptr_addref (T* obj, void*) {
reinterpret_cast<PointerHolder<T>*>(obj)->refcount_.increment();
}
template <typename T> void smartptr_release (T* obj, void*) {
reinterpret_cast<PointerHolder<T>*>(obj)->release();
}
template <typename T> T* smartptr_get (T* obj, void*) {
return (obj ? reinterpret_cast<PointerHolder<T>*>(obj)->obj_ : NULL);
}
template <typename Base, typename Derived> Base* smartptr_convert (Base*, void*, Derived* obj, void*) {
return obj;
}
template <typename T> long smartptr_get_refcount (const T* obj, const void*) {
return reinterpret_cast<const PointerHolder<T>*>(obj)->refcount_.get_value();
}
template <typename T> 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<your class>.
* 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 <typename T> T* smartptr_assign (T* obj, refcounted*) {
return obj;
}
template <typename T> void smartptr_addref (T* obj, refcounted*) {
addref (obj);
}
template <typename T> void smartptr_release (T* obj, refcounted*) {
release (obj);
}
template <typename T> T* smartptr_get (T* obj, refcounted*) {
return obj;
}
template <typename Base, typename Derived> Base* smartptr_convert (Base*, refcounted*, Derived* obj, refcounted*) {
return obj;
}
template <typename Base, typename Derived> 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 <typename T> long smartptr_get_refcount (const T* obj, const refcounted*) {
return get_refcount (obj);
}
template <typename T> 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 <typename T> T* smartptr_assign (T* obj, IUnknown*) {
return obj;
}
template <typename T> void smartptr_addref (T* obj, IUnknown*) {
obj->AddRef();
}
template <typename T> void smartptr_release (T* obj, IUnknown*) {
obj->Release();
}
template <typename T> T* smartptr_get (T* obj, IUnknown*) {
return obj;
}
template <typename Base, typename Derived> Base* smartptr_convert (Base*, IUnknown*, Derived* obj, IUnknown*) {
return obj;
}
template <typename Base, typename Derived> 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 <typename T> long smartptr_get_refcount (const T* obj, const IUnknown*) {
const_cast<T*>(obj)->AddRef();
return (long) const_cast<T*>(obj)->Release();
}
template <typename T> T* smartptr_encapsulate (T* obj, IUnknown*) {
obj->AddRef();
return obj;
}
}
}
#endif // IFR_V1_P_HPP_

View File

@ -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 <bits/c++config.h>
#include <bits/atomicity.h>
#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 <pthread.h>
#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<CRITICAL_SECTION*>(this);
}
};
}
}
}
}
#endif
#endif // IFR_V1_PLATFORM_HPP_