Fix various issues related to stability when using highly compliant compilers such as Comeau 4.3.0.1, VC7.1 and GCC 3.2
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@108 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
80e63b12a3
commit
b53b3265e4
56 changed files with 441 additions and 203 deletions
|
@ -16,7 +16,7 @@
|
|||
#ifndef FACTORY_INC_
|
||||
#define FACTORY_INC_
|
||||
|
||||
#include "TypeInfo.h"
|
||||
#include "LokiTypeInfo.h"
|
||||
#include "AssocVector.h"
|
||||
#include <exception>
|
||||
|
||||
|
|
|
@ -24,6 +24,12 @@
|
|||
|
||||
namespace Loki
|
||||
{
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1300
|
||||
#pragma warning( push )
|
||||
// 'class1' : base-class 'class2' is already a base-class of 'class3'
|
||||
#pragma warning( disable : 4584 )
|
||||
#endif // _MSC_VER
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template GenScatterHierarchy
|
||||
// Generates a scattered hierarchy starting from a typelist and a template
|
||||
|
@ -244,6 +250,9 @@ namespace Loki
|
|||
{
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1300
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
} // namespace Loki
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
|
||||
// Last update: June 20, 2001
|
||||
|
||||
#ifndef TYPEINFO_INC_
|
||||
#define TYPEINFO_INC_
|
||||
#ifndef LOKITYPEINFO_INC_
|
||||
#define LOKITYPEINFO_INC_
|
||||
|
||||
#include <typeinfo>
|
||||
#include <cassert>
|
||||
|
@ -62,7 +62,8 @@ namespace Loki
|
|||
inline bool TypeInfo::before(const TypeInfo& rhs) const
|
||||
{
|
||||
assert(pInfo_);
|
||||
return pInfo_->before(*rhs.pInfo_);
|
||||
// type_info::before return type is int in some VC libraries
|
||||
return pInfo_->before(*rhs.pInfo_) != 0;
|
||||
}
|
||||
|
||||
inline const std::type_info& TypeInfo::Get() const
|
||||
|
@ -80,7 +81,8 @@ namespace Loki
|
|||
// Comparison operators
|
||||
|
||||
inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return lhs.Get() == rhs.Get(); }
|
||||
// type_info::operator== return type is int in some VC libraries
|
||||
{ return (lhs.Get() == rhs.Get()) != 0; }
|
||||
|
||||
inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs)
|
||||
{ return lhs.before(rhs); }
|
||||
|
@ -103,4 +105,4 @@ namespace Loki
|
|||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // TYPEINFO_INC_
|
||||
#endif // LOKITYPEINFO_INC_
|
|
@ -17,7 +17,7 @@
|
|||
#define MULTIMETHODS_INC_
|
||||
|
||||
#include "Typelist.h"
|
||||
#include "TypeInfo.h"
|
||||
#include "LokiTypeInfo.h"
|
||||
#include "Functor.h"
|
||||
#include "AssocVector.h"
|
||||
|
||||
|
@ -77,13 +77,10 @@ namespace Loki
|
|||
Executor exec, NullType)
|
||||
{ return exec.OnError(lhs, rhs); }
|
||||
|
||||
template <class TList, class SomeLhs>
|
||||
template <class Head, class Tail, class SomeLhs>
|
||||
static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs,
|
||||
Executor exec, TList)
|
||||
{
|
||||
typedef typename TList::Head Head;
|
||||
typedef typename TList::Tail Tail;
|
||||
|
||||
Executor exec, Typelist<Head, Tail>)
|
||||
{
|
||||
if (Head* p2 = dynamic_cast<Head*>(&rhs))
|
||||
{
|
||||
Int2Type<(symmetric &&
|
||||
|
@ -102,13 +99,10 @@ namespace Loki
|
|||
Executor exec, NullType)
|
||||
{ return exec.OnError(lhs, rhs); }
|
||||
|
||||
template <class TList>
|
||||
template <class Head, class Tail>
|
||||
static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs,
|
||||
Executor exec, TList)
|
||||
{
|
||||
typedef typename TList::Head Head;
|
||||
typedef typename TList::Tail Tail;
|
||||
|
||||
Executor exec, Typelist<Head, Tail>)
|
||||
{
|
||||
if (Head* p1 = dynamic_cast<Head*>(&lhs))
|
||||
{
|
||||
return DispatchRhs(*p1, rhs, exec, TypesRhs());
|
||||
|
@ -286,7 +280,7 @@ namespace Loki
|
|||
template <class SomeLhs, class SomeRhs,
|
||||
ResultType (*callback)(SomeLhs&, SomeRhs&),
|
||||
bool symmetric>
|
||||
void Add()
|
||||
void Add(bool = true) // [gcc] dummy bool
|
||||
{
|
||||
typedef Private::FnDispatcherHelper<
|
||||
BaseLhs, BaseRhs,
|
||||
|
|
|
@ -178,6 +178,11 @@ namespace Loki
|
|||
|
||||
template <class T> struct CreateStatic
|
||||
{
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1300
|
||||
#pragma warning( push )
|
||||
// alignment of a member was sensitive to packing
|
||||
#pragma warning( disable : 4121 )
|
||||
#endif // _MSC_VER
|
||||
union MaxAlign
|
||||
{
|
||||
char t_[sizeof(T)];
|
||||
|
@ -191,6 +196,9 @@ namespace Loki
|
|||
int Test::* pMember_;
|
||||
int (Test::*pMemberFn_)(int);
|
||||
};
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1300
|
||||
#pragma warning( pop )
|
||||
#endif // _MSC_VER
|
||||
|
||||
static T* Create()
|
||||
{
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "SmallObj.h"
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
using namespace Loki;
|
||||
|
||||
|
@ -365,6 +366,20 @@ SmallObjAllocator::SmallObjAllocator(
|
|||
{
|
||||
}
|
||||
|
||||
namespace { // anoymous
|
||||
|
||||
// See LWG DR #270
|
||||
struct CompareFixedAllocatorSize
|
||||
: std::binary_function<const FixedAllocator &, std::size_t, bool>
|
||||
{
|
||||
bool operator()(const FixedAllocator &x, std::size_t numBytes) const
|
||||
{
|
||||
return x.BlockSize() < numBytes;
|
||||
}
|
||||
};
|
||||
|
||||
} // anoymous namespace
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SmallObjAllocator::Allocate
|
||||
// Allocates 'numBytes' memory
|
||||
|
@ -379,7 +394,8 @@ void* SmallObjAllocator::Allocate(std::size_t numBytes)
|
|||
{
|
||||
return pLastAlloc_->Allocate();
|
||||
}
|
||||
Pool::iterator i = std::lower_bound(pool_.begin(), pool_.end(), numBytes);
|
||||
Pool::iterator i = std::lower_bound(pool_.begin(), pool_.end(), numBytes,
|
||||
CompareFixedAllocatorSize());
|
||||
if (i == pool_.end() || i->BlockSize() != numBytes)
|
||||
{
|
||||
i = pool_.insert(i, FixedAllocator(numBytes));
|
||||
|
@ -404,7 +420,8 @@ void SmallObjAllocator::Deallocate(void* p, std::size_t numBytes)
|
|||
pLastDealloc_->Deallocate(p);
|
||||
return;
|
||||
}
|
||||
Pool::iterator i = std::lower_bound(pool_.begin(), pool_.end(), numBytes);
|
||||
Pool::iterator i = std::lower_bound(pool_.begin(), pool_.end(), numBytes,
|
||||
CompareFixedAllocatorSize());
|
||||
assert(i != pool_.end());
|
||||
assert(i->BlockSize() == numBytes);
|
||||
pLastDealloc_ = &*i;
|
||||
|
|
|
@ -86,9 +86,6 @@ namespace Loki
|
|||
// Returns the block size with which the FixedAllocator was initialized
|
||||
std::size_t BlockSize() const
|
||||
{ return blockSize_; }
|
||||
// Comparison operator for sorting
|
||||
bool operator<(std::size_t rhs) const
|
||||
{ return BlockSize() < rhs; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -152,56 +152,66 @@ namespace Loki
|
|||
// class template RefCountedMT
|
||||
// Implementation of the OwnershipPolicy used by SmartPtr
|
||||
// Implements external reference counting for multithreaded programs
|
||||
// Policy Usage: RefCountedMTAdj<ThreadingModel>::RefCountedMT
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <class P,
|
||||
template <class> class ThreadingModel>
|
||||
class RefCountedMT : public ThreadingModel< RefCountedMT<P, ThreadingModel> >
|
||||
{
|
||||
public:
|
||||
RefCountedMT()
|
||||
{
|
||||
pCount_ = static_cast<unsigned int*>(
|
||||
SmallObject<ThreadingModel>::operator new(
|
||||
sizeof(unsigned int)));
|
||||
assert(pCount_);
|
||||
*pCount_ = 1;
|
||||
}
|
||||
|
||||
RefCountedMT(const RefCountedMT& rhs)
|
||||
: pCount_(rhs.pCount_)
|
||||
{}
|
||||
|
||||
// MWCW lacks template friends, hence the following kludge
|
||||
template <typename P1>
|
||||
RefCountedMT(const RefCountedMT<P1, ThreadingModel>& rhs)
|
||||
: pCount_(reinterpret_cast<const RefCounted<P>&>(rhs).pCount_)
|
||||
{}
|
||||
|
||||
P Clone(const P& val)
|
||||
{
|
||||
ThreadingModel<RefCountedMT>::AtomicIncrement(*pCount_);
|
||||
return val;
|
||||
}
|
||||
|
||||
bool Release(const P&)
|
||||
{
|
||||
if (!ThreadingModel<RefCountedMT>::AtomicDecrement(*pCount_))
|
||||
{
|
||||
SmallObject<ThreadingModel>::operator delete(pCount_,
|
||||
sizeof(unsigned int));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Swap(RefCountedMT& rhs)
|
||||
{ std::swap(pCount_, rhs.pCount_); }
|
||||
|
||||
enum { destructiveCopy = false };
|
||||
template <template <class> class ThreadingModel>
|
||||
struct RefCountedMTAdj
|
||||
{
|
||||
template <class P>
|
||||
class RefCountedMT : public ThreadingModel< RefCountedMT<P> >
|
||||
{
|
||||
typedef ThreadingModel< RefCountedMT<P> > base_type;
|
||||
typedef typename base_type::IntType CountType;
|
||||
typedef volatile CountType *CountPtrType;
|
||||
|
||||
private:
|
||||
// Data
|
||||
volatile unsigned int* pCount_;
|
||||
public:
|
||||
RefCountedMT()
|
||||
{
|
||||
pCount_ = static_cast<CountPtrType>(
|
||||
SmallObject<ThreadingModel>::operator new(
|
||||
sizeof(*pCount_)));
|
||||
assert(pCount_);
|
||||
*pCount_ = 1;
|
||||
}
|
||||
|
||||
RefCountedMT(const RefCountedMT& rhs)
|
||||
: pCount_(rhs.pCount_)
|
||||
{}
|
||||
|
||||
//MWCW lacks template friends, hence the following kludge
|
||||
template <typename P1>
|
||||
RefCountedMT(const RefCountedMT<P1>& rhs)
|
||||
: pCount_(reinterpret_cast<const RefCountedMT<P>&>(rhs).pCount_)
|
||||
{}
|
||||
|
||||
P Clone(const P& val)
|
||||
{
|
||||
ThreadingModel<RefCountedMT>::AtomicIncrement(*pCount_);
|
||||
return val;
|
||||
}
|
||||
|
||||
bool Release(const P&)
|
||||
{
|
||||
if (!ThreadingModel<RefCountedMT>::AtomicDecrement(*pCount_))
|
||||
{
|
||||
SmallObject<ThreadingModel>::operator delete(
|
||||
const_cast<CountType *>(pCount_),
|
||||
sizeof(*pCount_));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Swap(RefCountedMT& rhs)
|
||||
{ std::swap(pCount_, rhs.pCount_); }
|
||||
|
||||
enum { destructiveCopy = false };
|
||||
|
||||
private:
|
||||
// Data
|
||||
CountPtrType pCount_;
|
||||
};
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -514,7 +524,7 @@ namespace Loki
|
|||
{}
|
||||
|
||||
static void OnDereference(P val)
|
||||
{ assert(val); }
|
||||
{ assert(val); (void)val; }
|
||||
|
||||
static void Swap(AssertCheck&)
|
||||
{}
|
||||
|
@ -691,6 +701,7 @@ namespace Loki
|
|||
// gcc doesn't like this:
|
||||
// operator const T&() const { return value_; }
|
||||
private:
|
||||
ByRef& operator=(const ByRef &);
|
||||
T& value_;
|
||||
};
|
||||
|
||||
|
@ -709,6 +720,33 @@ namespace Loki
|
|||
>
|
||||
class SmartPtr;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SmartPtrDef (definition)
|
||||
// this class added to unify the usage of SmartPtr
|
||||
// instead of writing SmartPtr<T,OP,CP,KP,SP> write SmartPtrDef<T,OP,CP,KP,SP>::type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template
|
||||
<
|
||||
typename T,
|
||||
template <class> class OwnershipPolicy = RefCounted,
|
||||
class ConversionPolicy = DisallowConversion,
|
||||
template <class> class CheckingPolicy = AssertCheck,
|
||||
template <class> class StoragePolicy = DefaultSPStorage
|
||||
>
|
||||
struct SmartPtrDef
|
||||
{
|
||||
typedef SmartPtr
|
||||
<
|
||||
T,
|
||||
OwnershipPolicy,
|
||||
ConversionPolicy,
|
||||
CheckingPolicy,
|
||||
StoragePolicy
|
||||
>
|
||||
type;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template SmartPtr (definition)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Loki
|
|||
struct Lock
|
||||
{
|
||||
Lock() {}
|
||||
Lock(const Host&) {}
|
||||
explicit Lock(const SingleThreaded&) {}
|
||||
};
|
||||
|
||||
typedef Host VolatileType;
|
||||
|
@ -96,10 +96,12 @@ namespace Loki
|
|||
Lock(const Lock&);
|
||||
Lock& operator=(const Lock&);
|
||||
public:
|
||||
Lock(Host& host) : host_(host)
|
||||
|
||||
explicit Lock(ObjectLevelLockable& host) : host_(host)
|
||||
{
|
||||
::EnterCriticalSection(&host_.mtx_);
|
||||
}
|
||||
|
||||
~Lock()
|
||||
{
|
||||
::LeaveCriticalSection(&host_.mtx_);
|
||||
|
@ -126,12 +128,10 @@ namespace Loki
|
|||
template <class Host>
|
||||
class ClassLevelLockable
|
||||
{
|
||||
static CRITICAL_SECTION mtx_;
|
||||
|
||||
struct Initializer;
|
||||
friend struct Initializer;
|
||||
struct Initializer
|
||||
{
|
||||
{
|
||||
CRITICAL_SECTION mtx_;
|
||||
|
||||
Initializer()
|
||||
{
|
||||
::InitializeCriticalSection(&mtx_);
|
||||
|
@ -155,15 +155,15 @@ namespace Loki
|
|||
public:
|
||||
Lock()
|
||||
{
|
||||
::EnterCriticalSection(&mtx_);
|
||||
::EnterCriticalSection(&initializer_.mtx_);
|
||||
}
|
||||
Lock(Host&)
|
||||
explicit Lock(ClassLevelLockable&)
|
||||
{
|
||||
::EnterCriticalSection(&mtx_);
|
||||
::EnterCriticalSection(&initializer_.mtx_);
|
||||
}
|
||||
~Lock()
|
||||
{
|
||||
::LeaveCriticalSection(&mtx_);
|
||||
::LeaveCriticalSection(&initializer_.mtx_);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -184,9 +184,6 @@ namespace Loki
|
|||
{ InterlockedExchange(&lval, val); }
|
||||
};
|
||||
|
||||
template <class Host>
|
||||
CRITICAL_SECTION ClassLevelLockable<Host>::mtx_;
|
||||
|
||||
template <class Host>
|
||||
typename ClassLevelLockable<Host>::Initializer
|
||||
ClassLevelLockable<Host>::initializer_;
|
||||
|
@ -197,8 +194,6 @@ namespace Loki
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Change log:
|
||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||
// January 10, 2002: Fixed bug in AtomicDivide - credit due to Jordi Guerrero
|
||||
// August 14, 2002: Changed some AtomicDivide's to AtomicDecrement's MKH
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
|
|
|
@ -67,6 +67,27 @@ namespace Loki
|
|||
typedef U Result;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template IsSameType
|
||||
// Return true iff two given types are the same
|
||||
// Invocation: SameType<T, U>::value
|
||||
// where:
|
||||
// T and U are types
|
||||
// Result evaluates to true iff U == T (types equal)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T, typename U>
|
||||
struct IsSameType
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct IsSameType<T,T>
|
||||
{
|
||||
enum { value = true };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -128,11 +149,11 @@ namespace Loki
|
|||
template <class T>
|
||||
struct Conversion<T, void>
|
||||
{
|
||||
enum { exists = 1, exists2Way = 0, sameType = 0 };
|
||||
enum { exists = 0, exists2Way = 0, sameType = 0 };
|
||||
};
|
||||
|
||||
template <>
|
||||
class Conversion<void, void>
|
||||
struct Conversion<void, void>
|
||||
{
|
||||
public:
|
||||
enum { exists = 1, exists2Way = 1, sameType = 1 };
|
||||
|
|
|
@ -407,15 +407,8 @@ namespace Loki
|
|||
};
|
||||
|
||||
template<>
|
||||
struct MakeTypelist
|
||||
<
|
||||
NullType, NullType, NullType,
|
||||
NullType, NullType, NullType,
|
||||
NullType, NullType, NullType,
|
||||
NullType, NullType, NullType,
|
||||
NullType, NullType, NullType,
|
||||
NullType, NullType, NullType
|
||||
>{
|
||||
struct MakeTypelist<>
|
||||
{
|
||||
typedef NullType Result;
|
||||
};
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ struct DefaultCatchAll
|
|||
static ReturnType AcceptImpl(T& visited, BaseVisitor& guest)
|
||||
{
|
||||
// Apply the Acyclic Visitor
|
||||
if (Visitor<T>* p = dynamic_cast<Visitor<T>*>(&guest))
|
||||
if (Visitor<T,R>* p = dynamic_cast<Visitor<T,R>*>(&guest))
|
||||
{
|
||||
return p->Visit(visited);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue