mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Large tidying up of Beast
- Move key classes into beast_core - Tidy up various macros and files - Disable leaking FifoFreeStoreWithTLS
This commit is contained in:
83
modules/beast_core/memory/beast_AtomicCounter.h
Normal file
83
modules/beast_core/memory/beast_AtomicCounter.h
Normal file
@@ -0,0 +1,83 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ATOMICCOUNTER_BEASTHEADER
|
||||
#define BEAST_ATOMICCOUNTER_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A thread safe usage counter.
|
||||
|
||||
This provides a simplified interface to an atomic integer suitable for
|
||||
measuring reference or usage counts. The counter is signaled when the
|
||||
count is non zero.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
class BEAST_API AtomicCounter
|
||||
{
|
||||
public:
|
||||
/** Create a new counter.
|
||||
|
||||
@param initialValue An optional starting usage count (default is 0).
|
||||
*/
|
||||
AtomicCounter (int initialValue = 0) noexcept
|
||||
:
|
||||
m_value (initialValue)
|
||||
{
|
||||
}
|
||||
|
||||
/** Increment the usage count.
|
||||
|
||||
@return `true` if the counter became signaled.
|
||||
*/
|
||||
inline bool addref () noexcept
|
||||
{
|
||||
return (++m_value) == 1;
|
||||
}
|
||||
|
||||
/** Decrements the usage count.
|
||||
|
||||
@return `true` if the counter became non-signaled.
|
||||
*/
|
||||
inline bool release () noexcept
|
||||
{
|
||||
// Unfortunately, AllocatorWithoutTLS breaks this assert
|
||||
//bassert (isSignaled ());
|
||||
|
||||
return (--m_value) == 0;
|
||||
}
|
||||
|
||||
/** Determine if the counter is signaled.
|
||||
|
||||
Note that another thread can cause the counter to become reset after
|
||||
this function returns true.
|
||||
|
||||
@return `true` if the counter was signaled.
|
||||
*/
|
||||
inline bool isSignaled () const noexcept
|
||||
{
|
||||
return m_value.get () > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
Atomic <int> m_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
102
modules/beast_core/memory/beast_AtomicFlag.h
Normal file
102
modules/beast_core/memory/beast_AtomicFlag.h
Normal file
@@ -0,0 +1,102 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ATOMICFLAG_BEASTHEADER
|
||||
#define BEAST_ATOMICFLAG_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A thread safe flag.
|
||||
|
||||
This provides a simplified interface to an atomic integer suitable for
|
||||
representing a flag. The flag is signaled when on, else it is considered
|
||||
reset.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
class BEAST_API AtomicFlag
|
||||
{
|
||||
public:
|
||||
/** Create an AtomicFlag in the reset state. */
|
||||
AtomicFlag () noexcept
|
||||
:
|
||||
m_value (0)
|
||||
{
|
||||
}
|
||||
|
||||
/** Signal the flag.
|
||||
|
||||
If two or more threads simultaneously attempt to signal the flag,
|
||||
only one will receive a true return value.
|
||||
|
||||
@return true if the flag was previously reset.
|
||||
*/
|
||||
inline bool trySignal () noexcept
|
||||
{
|
||||
return m_value.compareAndSetBool (1, 0);
|
||||
}
|
||||
|
||||
/** Signal the flag.
|
||||
|
||||
The flag must be in the reset state. Only one thread may
|
||||
call this at a time.
|
||||
*/
|
||||
inline void signal () noexcept
|
||||
{
|
||||
#if BEAST_DEBUG
|
||||
const bool success = m_value.compareAndSetBool (1, 0);
|
||||
bassert (success);
|
||||
#else
|
||||
m_value.set (1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Reset the flag.
|
||||
|
||||
The flag must be in the signaled state. Only one thread may
|
||||
call this at a time. Usually it is the thread that was successful
|
||||
in a previous call to trySignal().
|
||||
*/
|
||||
inline void reset () noexcept
|
||||
{
|
||||
#if BEAST_DEBUG
|
||||
const bool success = m_value.compareAndSetBool (0, 1);
|
||||
bassert (success);
|
||||
#else
|
||||
m_value.set (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Check if the AtomicFlag is signaled
|
||||
|
||||
The signaled status may change immediately after this call
|
||||
returns. The caller must synchronize.
|
||||
|
||||
@return true if the flag was signaled.
|
||||
*/
|
||||
inline bool isSignaled () const noexcept
|
||||
{
|
||||
return m_value.get () == 1;
|
||||
}
|
||||
|
||||
private:
|
||||
Atomic <int> m_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
133
modules/beast_core/memory/beast_AtomicPointer.h
Normal file
133
modules/beast_core/memory/beast_AtomicPointer.h
Normal file
@@ -0,0 +1,133 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ATOMICPOINTER_BEASTHEADER
|
||||
#define BEAST_ATOMICPOINTER_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A thread safe pointer.
|
||||
|
||||
This provides a simplified interface to an atomic pointer suitable
|
||||
for building containers or composite classes. Operator overloads
|
||||
allow access to the underlying pointer using natural C++ syntax.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
template <class P>
|
||||
class AtomicPointer
|
||||
{
|
||||
public:
|
||||
/** Create a pointer.
|
||||
|
||||
@param initialValue An optional starting value (default is null).
|
||||
*/
|
||||
explicit AtomicPointer (P* const initialValue = nullptr) noexcept
|
||||
:
|
||||
m_value (initialValue)
|
||||
{
|
||||
}
|
||||
|
||||
/** Retrieve the pointer value */
|
||||
inline P* get () const noexcept
|
||||
{
|
||||
return m_value.get ();
|
||||
}
|
||||
|
||||
/** Obtain a pointer to P through type conversion.
|
||||
|
||||
The caller must synchronize access to P.
|
||||
|
||||
@return A pointer to P.
|
||||
*/
|
||||
inline operator P* () const noexcept
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
|
||||
/** Dereference operator
|
||||
|
||||
The caller must synchronize access to P.
|
||||
|
||||
@return A reference to P.
|
||||
*/
|
||||
inline P& operator* () const noexcept
|
||||
{
|
||||
return &get ();
|
||||
}
|
||||
|
||||
/** Member selection
|
||||
|
||||
The caller must synchronize access to P.
|
||||
|
||||
@return A pointer to P.
|
||||
*/
|
||||
inline P* operator-> () const noexcept
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
|
||||
inline void set (P* p)
|
||||
{
|
||||
m_value.set (p);
|
||||
}
|
||||
|
||||
/** Atomically assign a new pointer
|
||||
|
||||
@param newValue The new value to assign.
|
||||
*/
|
||||
inline void operator= (P* newValue) noexcept
|
||||
{
|
||||
set (newValue);
|
||||
}
|
||||
|
||||
/** Atomically assign a new pointer and return the old value.
|
||||
|
||||
@param newValue The new value to assign.
|
||||
|
||||
@return The previous value.
|
||||
*/
|
||||
inline P* exchange (P* newValue)
|
||||
{
|
||||
return m_value.exchange (newValue);
|
||||
}
|
||||
|
||||
/** Conditionally perform an atomic assignment.
|
||||
|
||||
The current value is compared with oldValue and atomically
|
||||
set to newValue if the comparison is equal.
|
||||
|
||||
The caller is responsible for handling the ABA problem.
|
||||
|
||||
@param newValue The new value to assign.
|
||||
|
||||
@param oldValue The matching old value.
|
||||
|
||||
@return true if the assignment was performed.
|
||||
*/
|
||||
inline bool compareAndSet (P* newValue, P* oldValue)
|
||||
{
|
||||
return m_value.compareAndSetBool (newValue, oldValue);
|
||||
}
|
||||
|
||||
private:
|
||||
Atomic <P*> m_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
101
modules/beast_core/memory/beast_AtomicState.h
Normal file
101
modules/beast_core/memory/beast_AtomicState.h
Normal file
@@ -0,0 +1,101 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ATOMICSTATE_BEASTHEADER
|
||||
#define BEAST_ATOMICSTATE_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A thread safe state variable.
|
||||
|
||||
This provides a simplified interface to an integer used to control atomic
|
||||
state transitions. A state is distinguished by a single integer value.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
class BEAST_API AtomicState
|
||||
{
|
||||
public:
|
||||
/** Create a new state with an optional starting value.
|
||||
|
||||
@param initialState The initial state.
|
||||
*/
|
||||
|
||||
|
||||
explicit AtomicState (const int initialState = 0) noexcept
|
||||
:
|
||||
m_value (initialState)
|
||||
{
|
||||
}
|
||||
|
||||
/** Retrieve the current state.
|
||||
|
||||
This converts the object to an integer reflecting the current state.
|
||||
|
||||
Note that other threads may change the value immediately after this
|
||||
function returns. The caller is responsible for synchronizing.
|
||||
|
||||
@return The state at the time of the call.
|
||||
*/
|
||||
inline operator int () const
|
||||
{
|
||||
return m_value.get ();
|
||||
}
|
||||
|
||||
/** Attempt a state transition.
|
||||
|
||||
The current state is compared to `from`, and if the comparison is
|
||||
successful the state becomes `to`. The entire operation is atomic.
|
||||
|
||||
@param from The current state, for comparison.
|
||||
|
||||
@param to The desired new state.
|
||||
|
||||
@return true if the state transition succeeded.
|
||||
*/
|
||||
inline bool tryChangeState (const int from, const int to) noexcept
|
||||
{
|
||||
return m_value.compareAndSetBool (to, from);
|
||||
}
|
||||
|
||||
/** Perform a state transition.
|
||||
|
||||
This attempts to change the state and generates a diagnostic on
|
||||
failure. This routine can be used instead of tryChangeState()
|
||||
when program logic requires that the state change must succeed.
|
||||
|
||||
@param from The required current state.
|
||||
|
||||
@param to The new state.
|
||||
*/
|
||||
inline void changeState (const int from, const int to) noexcept
|
||||
{
|
||||
#if BEAST_DEBUG
|
||||
const bool success = tryChangeState (from, to);
|
||||
bassert (success);
|
||||
#else
|
||||
tryChangeState (from, to);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
Atomic <int> m_value;
|
||||
};
|
||||
|
||||
#endif
|
||||
476
modules/beast_core/memory/beast_CacheLine.h
Normal file
476
modules/beast_core/memory/beast_CacheLine.h
Normal file
@@ -0,0 +1,476 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CACHELINE_BEASTHEADER
|
||||
#define BEAST_CACHELINE_BEASTHEADER
|
||||
|
||||
// Allows turning off of all padding,
|
||||
// e.g. for memory-constrained systems or testing.
|
||||
//
|
||||
#define GLOBAL_PADDING_ENABLED 0
|
||||
|
||||
namespace CacheLine
|
||||
{
|
||||
|
||||
#if GLOBAL_PADDING_ENABLED
|
||||
|
||||
// Pads an object so that it starts on a cache line boundary.
|
||||
//
|
||||
template <typename T>
|
||||
class Aligned
|
||||
{
|
||||
public:
|
||||
~Aligned ()
|
||||
{
|
||||
ptr ()->~T ();
|
||||
}
|
||||
|
||||
Aligned ()
|
||||
{
|
||||
new (ptr ()) T;
|
||||
}
|
||||
|
||||
template <class T1>
|
||||
explicit Aligned (const T1& t1)
|
||||
{
|
||||
new (ptr ()) T (t1);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
Aligned (const T1& t1, const T2& t2)
|
||||
{
|
||||
new (ptr ()) T (t1, t2);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3, const T4& t4)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4, t5);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5, const T6& t6)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4, t5, t6);
|
||||
}
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7 >
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4, t5, t6, t7);
|
||||
}
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7, class T8 >
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7, const T8& t8)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4, t5, t6, t7, t8);
|
||||
}
|
||||
|
||||
void operator= (T const& other)
|
||||
{
|
||||
*ptr () = other;
|
||||
}
|
||||
|
||||
inline T& operator* () noexcept { return *ptr (); }
|
||||
inline T* operator-> () noexcept { return ptr (); }
|
||||
inline operator T& () noexcept { return *ptr (); }
|
||||
inline operator T* () noexcept { return ptr (); }
|
||||
|
||||
inline const T& operator* () const noexcept
|
||||
{
|
||||
return *ptr ();
|
||||
}
|
||||
inline const T* operator-> () const noexcept
|
||||
{
|
||||
return ptr ();
|
||||
}
|
||||
inline operator const T& () const noexcept
|
||||
{
|
||||
return *ptr ();
|
||||
}
|
||||
inline operator const T* () const noexcept
|
||||
{
|
||||
return ptr ();
|
||||
}
|
||||
|
||||
private:
|
||||
inline T* ptr () noexcept
|
||||
{
|
||||
return (T*) ((uintptr_t (m_storage) + Memory::cacheLineAlignMask)
|
||||
& ~Memory::cacheLineAlignMask);
|
||||
/*
|
||||
return reinterpret_cast <T*> (Memory::pointerAdjustedForAlignment (
|
||||
m_storage, Memory::cacheLineBytes));
|
||||
*/
|
||||
}
|
||||
|
||||
char m_storage [ (sizeof (T) + Memory::cacheLineAlignMask)
|
||||
& ~Memory::cacheLineAlignMask];
|
||||
};
|
||||
|
||||
// Holds an object padded it to completely fill a CPU cache line.
|
||||
// The caller must ensure that this object starts at the beginning
|
||||
// of a cache line.
|
||||
//
|
||||
template <typename T>
|
||||
class Padded
|
||||
{
|
||||
public:
|
||||
Padded ()
|
||||
{ }
|
||||
|
||||
template <class T1>
|
||||
explicit Padded (const T1& t1)
|
||||
: m_t (t1) { }
|
||||
|
||||
template <class T1, class T2>
|
||||
Padded (const T1& t1, const T2& t2)
|
||||
: m_t (t1, t2) { }
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3)
|
||||
: m_t (t1, t2, t3) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3, const T4& t4)
|
||||
: m_t (t1, t2, t3, t4) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5)
|
||||
: m_t (t1, t2, t3, t4, t5) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5, const T6& t6)
|
||||
: m_t (t1, t2, t3, t4, t5, t6) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7 >
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7, class T8 >
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7, const T8& t8)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7, t8) { }
|
||||
|
||||
void operator= (const T& other)
|
||||
{
|
||||
m_t = other;
|
||||
}
|
||||
|
||||
T& operator* () noexcept { return m_t; }
|
||||
T* operator-> () noexcept { return &m_t; }
|
||||
operator T& () noexcept { return m_t; }
|
||||
operator T* () noexcept { return &m_t; }
|
||||
|
||||
const T& operator* () const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
const T* operator-> () const noexcept
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
operator const T& () const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
operator const T* () const noexcept
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_t;
|
||||
char pad [Memory::cacheLineAlignBytes - sizeof (T)];
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template <typename T>
|
||||
class Aligned
|
||||
{
|
||||
public:
|
||||
Aligned ()
|
||||
{ }
|
||||
|
||||
template <class T1>
|
||||
explicit Aligned (const T1& t1)
|
||||
: m_t (t1) { }
|
||||
|
||||
template <class T1, class T2>
|
||||
Aligned (const T1& t1, const T2& t2)
|
||||
: m_t (t1, t2) { }
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3)
|
||||
: m_t (t1, t2, t3) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3, const T4& t4)
|
||||
: m_t (t1, t2, t3, t4) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5)
|
||||
: m_t (t1, t2, t3, t4, t5) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5, const T6& t6)
|
||||
: m_t (t1, t2, t3, t4, t5, t6) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7 >
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7, class T8 >
|
||||
Aligned (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7, const T8& t8)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7, t8) { }
|
||||
|
||||
void operator= (const T& other)
|
||||
{
|
||||
m_t = other;
|
||||
}
|
||||
|
||||
T& operator* () noexcept { return m_t; }
|
||||
T* operator-> () noexcept { return &m_t; }
|
||||
operator T& () noexcept { return m_t; }
|
||||
operator T* () noexcept { return &m_t; }
|
||||
|
||||
const T& operator* () const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
const T* operator-> () const noexcept
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
operator const T& () const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
operator const T* () const noexcept
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_t;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Padded
|
||||
{
|
||||
public:
|
||||
Padded ()
|
||||
{ }
|
||||
|
||||
template <class T1>
|
||||
explicit Padded (const T1& t1)
|
||||
: m_t (t1) { }
|
||||
|
||||
template <class T1, class T2>
|
||||
Padded (const T1& t1, const T2& t2)
|
||||
: m_t (t1, t2) { }
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3)
|
||||
: m_t (t1, t2, t3) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3, const T4& t4)
|
||||
: m_t (t1, t2, t3, t4) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5)
|
||||
: m_t (t1, t2, t3, t4, t5) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5, const T6& t6)
|
||||
: m_t (t1, t2, t3, t4, t5, t6) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7 >
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7, class T8 >
|
||||
Padded (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7, const T8& t8)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7, t8) { }
|
||||
|
||||
void operator= (const T& other)
|
||||
{
|
||||
m_t = other;
|
||||
}
|
||||
|
||||
T& operator* () noexcept { return m_t; }
|
||||
T* operator-> () noexcept { return &m_t; }
|
||||
operator T& () noexcept { return m_t; }
|
||||
operator T* () noexcept { return &m_t; }
|
||||
|
||||
const T& operator* () const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
const T* operator-> () const noexcept
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
operator const T& () const noexcept
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
operator const T* () const noexcept
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_t;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// Used to remove padding without changing code
|
||||
//
|
||||
|
||||
template <typename T>
|
||||
class Unpadded
|
||||
{
|
||||
public:
|
||||
Unpadded ()
|
||||
{ }
|
||||
|
||||
template <class T1>
|
||||
explicit Unpadded (const T1& t1)
|
||||
: m_t (t1) { }
|
||||
|
||||
template <class T1, class T2>
|
||||
Unpadded (const T1& t1, const T2& t2)
|
||||
: m_t (t1, t2) { }
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
Unpadded (const T1& t1, const T2& t2, const T3& t3)
|
||||
: m_t (t1, t2, t3) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
Unpadded (const T1& t1, const T2& t2, const T3& t3, const T4& t4)
|
||||
: m_t (t1, t2, t3, t4) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
Unpadded (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5)
|
||||
: m_t (t1, t2, t3, t4, t5) { }
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
Unpadded (const T1& t1, const T2& t2, const T3& t3,
|
||||
const T4& t4, const T5& t5, const T6& t6)
|
||||
: m_t (t1, t2, t3, t4, t5, t6) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7 >
|
||||
Unpadded (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7) { }
|
||||
|
||||
template < class T1, class T2, class T3, class T4,
|
||||
class T5, class T6, class T7, class T8 >
|
||||
Unpadded (const T1& t1, const T2& t2, const T3& t3, const T4& t4,
|
||||
const T5& t5, const T6& t6, const T7& t7, const T8& t8)
|
||||
: m_t (t1, t2, t3, t4, t5, t6, t7, t8) { }
|
||||
|
||||
void operator= (const T& other)
|
||||
{
|
||||
m_t = other;
|
||||
}
|
||||
|
||||
T& operator* ()
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
T* operator-> ()
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
operator T& ()
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
operator T* ()
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
|
||||
const T& operator* () const
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
const T* operator-> () const
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
operator const T& () const
|
||||
{
|
||||
return m_t;
|
||||
}
|
||||
operator const T* () const
|
||||
{
|
||||
return &m_t;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_t;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
67
modules/beast_core/memory/beast_MemoryAlignment.h
Normal file
67
modules/beast_core/memory/beast_MemoryAlignment.h
Normal file
@@ -0,0 +1,67 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_MEMORYALIGNMENT_BEASTHEADER
|
||||
#define BEAST_MEMORYALIGNMENT_BEASTHEADER
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constants
|
||||
//
|
||||
// These need to be set based on the target CPU
|
||||
//
|
||||
|
||||
const int cacheLineAlignBits = 6; // 64 bytes
|
||||
const int cacheLineAlignBytes = 1 << cacheLineAlignBits;
|
||||
const int cacheLineAlignMask = cacheLineAlignBytes - 1;
|
||||
|
||||
const int allocAlignBits = 3; // 8 bytes
|
||||
const int allocAlignBytes = 1 << allocAlignBits;
|
||||
const int allocAlignMask = allocAlignBytes - 1;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Returns the number of bytes needed to advance p to the correct alignment
|
||||
template <typename P>
|
||||
inline size_t bytesNeededForAlignment (P const* const p)
|
||||
{
|
||||
return (allocAlignBytes - (uintptr_t (p) & allocAlignMask))
|
||||
& allocAlignMask;
|
||||
}
|
||||
|
||||
// Returns the number of bytes to make "bytes" an aligned size
|
||||
inline size_t sizeAdjustedForAlignment (const size_t bytes)
|
||||
{
|
||||
return (bytes + allocAlignMask) & ~allocAlignMask;
|
||||
}
|
||||
|
||||
// Returns a pointer with alignment added.
|
||||
template <typename P>
|
||||
inline P* pointerAdjustedForAlignment (P* const p)
|
||||
{
|
||||
return reinterpret_cast <P*> (reinterpret_cast <char*> (p) +
|
||||
bytesNeededForAlignment (p));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
185
modules/beast_core/memory/beast_StaticObject.h
Normal file
185
modules/beast_core/memory/beast_StaticObject.h
Normal file
@@ -0,0 +1,185 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_STATICOBJECT_BEASTHEADER
|
||||
#define BEAST_STATICOBJECT_BEASTHEADER
|
||||
|
||||
//
|
||||
// A full suite of thread-safe objects designed for static storage duration.
|
||||
//
|
||||
// Wraps an object with a thread-safe initialization preamble so that it can
|
||||
// properly exist with static storage duration.
|
||||
//
|
||||
// Implementation notes:
|
||||
//
|
||||
// This is accomplished by omitting the constructor and relying on the C++
|
||||
// specification that plain data types with static storage duration are filled
|
||||
// with zeroes before any other initialization code executes.
|
||||
//
|
||||
// Spec: N2914=09-0104
|
||||
//
|
||||
// [3.6.2] Initialization of non-local objects
|
||||
//
|
||||
// Objects with static storage duration (3.7.1) or thread storage
|
||||
// duration (3.7.2) shall be zero-initialized (8.5) before any
|
||||
// other initialization takes place.
|
||||
//
|
||||
// Requirements:
|
||||
//
|
||||
// Object must be constructible without parameters.
|
||||
// The StaticObject must be declared with static storage duration or
|
||||
// the behavior is undefined.
|
||||
//
|
||||
// Usage example:
|
||||
//
|
||||
// Object* getInstance ()
|
||||
// {
|
||||
// static StaticObject <Object> instance;
|
||||
// return instance->getObject ();
|
||||
// }
|
||||
//
|
||||
|
||||
namespace Static
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Holds an object with static storage duration.
|
||||
// The owner determines if and when the object is constructed and destroyed.
|
||||
// Caller is responsible for synchronization.
|
||||
//
|
||||
template <class ObjectType, class Tag>
|
||||
class Storage
|
||||
{
|
||||
public:
|
||||
static inline void construct ()
|
||||
{
|
||||
new (getObjectPtr ()) ObjectType;
|
||||
}
|
||||
|
||||
static inline void destroy ()
|
||||
{
|
||||
getObjectPtr ()->~ObjectType ();
|
||||
}
|
||||
|
||||
static inline ObjectType* getObjectPtr ()
|
||||
{
|
||||
return reinterpret_cast <ObjectType*> (s_storage);
|
||||
}
|
||||
|
||||
static inline ObjectType& getObject ()
|
||||
{
|
||||
return *getObjectPtr ();
|
||||
}
|
||||
|
||||
inline ObjectType* operator-> () const
|
||||
{
|
||||
return getObjectPtr ();
|
||||
}
|
||||
|
||||
inline ObjectType& operator* () const
|
||||
{
|
||||
return getObject ();
|
||||
}
|
||||
|
||||
inline operator ObjectType* () const
|
||||
{
|
||||
return getObjectPtr ();
|
||||
}
|
||||
|
||||
// TODO: Crashes on iOS if not accessed before usage
|
||||
static char s_storage [sizeof (ObjectType)];
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
template <class ObjectType, class Tag>
|
||||
char Storage <ObjectType, Tag>::s_storage [sizeof (ObjectType)];
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Provides a thread safe flag for indicating if and when
|
||||
// initialization is required for an object with static storage duration.
|
||||
//
|
||||
class Initializer
|
||||
{
|
||||
public:
|
||||
/*
|
||||
bool inited () const
|
||||
{
|
||||
return m_state.get () == stateInitialized;
|
||||
}
|
||||
*/
|
||||
|
||||
// If the condition is not initialized, the first caller will
|
||||
// receive true, while concurrent callers get blocked until
|
||||
// initialization completes.
|
||||
//
|
||||
bool begin ()
|
||||
{
|
||||
bool shouldInitialize;
|
||||
|
||||
if (m_state.get () == stateUninitialized)
|
||||
{
|
||||
if (m_state.compareAndSetBool (stateInitializing, stateUninitialized))
|
||||
{
|
||||
shouldInitialize = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
SpinDelay delay;
|
||||
|
||||
do
|
||||
{
|
||||
delay.pause ();
|
||||
}
|
||||
while (m_state.get () != stateInitialized);
|
||||
|
||||
shouldInitialize = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
shouldInitialize = false;
|
||||
}
|
||||
|
||||
return shouldInitialize;
|
||||
}
|
||||
|
||||
// Called to signal that the initialization is complete
|
||||
//
|
||||
void end ()
|
||||
{
|
||||
m_state.set (stateInitialized);
|
||||
}
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
stateUninitialized = 0, // must be zero
|
||||
stateInitializing,
|
||||
stateInitialized
|
||||
};
|
||||
|
||||
Atomic <int> m_state;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
38
modules/beast_core/memory/beast_Uncopyable.h
Normal file
38
modules/beast_core/memory/beast_Uncopyable.h
Normal file
@@ -0,0 +1,38 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_UNCOPYABLE_BEASTHEADER
|
||||
#define BEAST_UNCOPYABLE_BEASTHEADER
|
||||
|
||||
// Prevents warnings about missing copy
|
||||
// constructors and assignment operators.
|
||||
|
||||
// Ideas based on boost
|
||||
class Uncopyable
|
||||
{
|
||||
protected:
|
||||
inline Uncopyable () { }
|
||||
inline ~Uncopyable () { }
|
||||
|
||||
private:
|
||||
Uncopyable (Uncopyable const&);
|
||||
Uncopyable const& operator= (Uncopyable const&);
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user