mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Migrate some headers and general tidying
This commit is contained in:
@@ -76,21 +76,28 @@
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace beast {
|
||||
extern BEAST_API bool BEAST_CALLTYPE beast_isRunningUnderDebugger();
|
||||
extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) noexcept;
|
||||
}
|
||||
|
||||
// New header-only library modeled more closely according to boost
|
||||
#include "../../beast/CStdInt.h"
|
||||
#include "../../beast/StaticAssert.h"
|
||||
#include "../../beast/Uncopyable.h"
|
||||
#include "../../beast/Atomic.h"
|
||||
#include "../../beast/Intrusive.h"
|
||||
#include "../../beast/Net.h"
|
||||
#include "../../beast/TypeTraits.h"
|
||||
#include "../../beast/Thread.h"
|
||||
|
||||
namespace beast
|
||||
{
|
||||
namespace beast {
|
||||
|
||||
class InputStream;
|
||||
class OutputStream;
|
||||
class FileInputStream;
|
||||
class FileOutputStream;
|
||||
|
||||
extern BEAST_API bool BEAST_CALLTYPE beast_isRunningUnderDebugger();
|
||||
extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) noexcept;
|
||||
|
||||
// Order matters, since headers don't have their own #include lines.
|
||||
// Add new includes to the bottom.
|
||||
|
||||
@@ -98,23 +105,8 @@ extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) n
|
||||
#include "memory/Memory.h"
|
||||
#include "maths/MathsFunctions.h"
|
||||
#include "memory/ByteOrder.h"
|
||||
#include "memory/Atomic.h"
|
||||
#include "text/CharacterFunctions.h"
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// New header-only library modeled more closely according to boost
|
||||
#include "../../beast/intrusive/ForwardList.h"
|
||||
#include "../../beast/Net.h"
|
||||
#include "../../beast/Thread.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace beast
|
||||
{
|
||||
|
||||
#if BEAST_MSVC
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable: 4514 4996)
|
||||
@@ -127,16 +119,12 @@ namespace beast
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
|
||||
# include "containers/detail/removecv.h"
|
||||
#include "containers/detail/copyconst.h"
|
||||
#include "diagnostic/Throw.h"
|
||||
#include "system/Functional.h"
|
||||
#include "memory/AtomicCounter.h"
|
||||
#include "memory/AtomicFlag.h"
|
||||
#include "memory/AtomicPointer.h"
|
||||
#include "memory/AtomicState.h"
|
||||
#include "containers/List.h"
|
||||
#include "containers/LockFreeStack.h"
|
||||
#include "threads/SpinDelay.h"
|
||||
#include "memory/StaticObject.h"
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ class DynamicArrayIterator
|
||||
typename V::size_type>
|
||||
{
|
||||
public:
|
||||
typedef typename copyconst <V, typename V::value_type>::type
|
||||
typedef typename mpl::CopyConst <V, typename V::value_type>::type
|
||||
|
||||
value_type;
|
||||
typedef value_type* pointer;
|
||||
@@ -216,7 +216,7 @@ class DynamicArrayReverseIterator
|
||||
typename V::size_type>
|
||||
{
|
||||
public:
|
||||
typedef typename copyconst <V, typename V::value_type>::type
|
||||
typedef typename mpl::CopyConst<V, typename V::value_type>::type
|
||||
|
||||
value_type;
|
||||
typedef value_type* pointer;
|
||||
|
||||
@@ -193,9 +193,9 @@ class HashMapIterator
|
||||
private:
|
||||
typedef typename M::Item Item;
|
||||
typedef typename M::Bucket Bucket;
|
||||
typedef detail::ListIterator <typename detail::copyconst <M,
|
||||
typedef detail::ListIterator <typename mpl::CopyConst <M,
|
||||
typename List <Bucket>::Node>::type> bucket_iterator;
|
||||
typedef detail::ListIterator <typename detail::copyconst <M,
|
||||
typedef detail::ListIterator <typename mpl::CopyConst <M,
|
||||
typename List <Item, detail::BucketTag>::Node>::type> item_iterator;
|
||||
|
||||
public:
|
||||
|
||||
@@ -1,720 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_CORE_CONTAINERS_LIST_H_INCLUDED
|
||||
#define BEAST_CORE_CONTAINERS_LIST_H_INCLUDED
|
||||
|
||||
/** Intrusive Containers
|
||||
|
||||
# Introduction
|
||||
|
||||
Intrusive containers are special containers that offer better performance
|
||||
and exception safety guarantees than non-intrusive containers (like the
|
||||
STL containers). They are useful building blocks for high performance
|
||||
concurrent systems or other purposes where allocations are restricted
|
||||
(such as the AudioIODeviceCallback object), because intrusive list
|
||||
operations do not allocate or free memory.
|
||||
|
||||
While intrusive containers were and are widely used in C, they became more
|
||||
and more forgotten in C++ due to the presence of the standard containers
|
||||
which don't support intrusive techniques. VFLib not only reintroduces this
|
||||
technique to C++ for lists, it also encapsulates the implementation in a
|
||||
mostly compliant STL interface. Hence anyone familiar with standard
|
||||
containers can easily use them.
|
||||
|
||||
# Interface
|
||||
|
||||
The interface for intrusive elements in this library is unified for all
|
||||
containers. Unlike STL containers, objects placed into intrusive containers
|
||||
are not copied. Instead, a pointer to the object is stored. All
|
||||
responsibility for object lifetime is the responsibility of the caller;
|
||||
the intrusive container just keeps track of what is in it.
|
||||
|
||||
Summary of intrusive container differences:
|
||||
|
||||
- Holds pointers to existing objects instead of copies.
|
||||
|
||||
- Does not allocate or free any objects.
|
||||
|
||||
- Requires a element's class declaration to be modified.
|
||||
|
||||
- Methods never throw exceptions when called with valid arguments.
|
||||
|
||||
# Usage
|
||||
|
||||
Like STL containers, intrusive containers are all template based, where the
|
||||
template argument specifies the type of object that the container will hold.
|
||||
These declarations specify a doubly linked list where each element points
|
||||
to a user defined class:
|
||||
|
||||
@code
|
||||
|
||||
struct Object; // Forward declaration
|
||||
|
||||
List <Object> list; // Doubly-linked list of Object
|
||||
|
||||
@endcode
|
||||
|
||||
Because intrusive containers allocate no memory, allowing objects to be
|
||||
placed inside requires a modification to their class declaration. Each
|
||||
intrusive container declares a nested class `Node` which elements must be
|
||||
derived from, using the Curiously Recurring Template Pattern (CRTP). We
|
||||
will continue to fully declare the Object type from the previous example
|
||||
to support emplacement into an intrusive container:
|
||||
|
||||
@code
|
||||
|
||||
struct Object : public List <Object>::Node // Required for List
|
||||
{
|
||||
void performAction ();
|
||||
};
|
||||
|
||||
@endcode
|
||||
|
||||
Usage of a typedef eliminates redundant specification of the template
|
||||
arguments but requires a forward declaration. The following code is
|
||||
equivalent.
|
||||
|
||||
@code
|
||||
|
||||
struct Object; // Forward declaration
|
||||
|
||||
// Specify template parameters just once
|
||||
typedef List <Object> ListType;
|
||||
|
||||
struct Object : public ListType::Node
|
||||
{
|
||||
void performAction ();
|
||||
};
|
||||
|
||||
ListType::Node list;
|
||||
|
||||
@endcode
|
||||
|
||||
With these declarations we may proceed to create our objects, add them to
|
||||
the list, and perform operations:
|
||||
|
||||
@code
|
||||
|
||||
// Create a few objects and put them in the list
|
||||
for (i = 0; i < 5; ++i)
|
||||
list.push_back (*new Object);
|
||||
|
||||
// Call a method on each list
|
||||
for (ListType::iterator iter = list.begin(); iter != list.end (); ++iter)
|
||||
iter->performAction ();
|
||||
|
||||
@endcode
|
||||
|
||||
Unlike regular STL containers, an object derived from an intrusive container
|
||||
node cannot exist in more than one instance of that list at a time. This is
|
||||
because the bookkeeping information for maintaining the list is kept in
|
||||
the object rather than the list.
|
||||
|
||||
To support objects existing in multiple containers, templates variations
|
||||
are instantiated by distinguishing them with an empty structure, called a
|
||||
tag. The object is derived from multiple instances of Node, where each
|
||||
instance specifies a unique tag. The tag is passed as the second template
|
||||
argument. When the second argument is unspecified, the default tag is used.
|
||||
|
||||
This declaration example shows the usage of tags to allow an object to exist
|
||||
simultaneously in two separate lists:
|
||||
|
||||
@code
|
||||
|
||||
struct GlobalListTag { }; // list of all objects
|
||||
struct ActiveListTag { }; // subset of all objects that are active
|
||||
|
||||
class Object : public List <Object, GlobalListTag>
|
||||
, public List <Object, ActiveListTag>
|
||||
{
|
||||
public:
|
||||
Object () : m_isActive (false)
|
||||
{
|
||||
// Add ourselves to the global list
|
||||
s_globalList.push_front (*this);
|
||||
}
|
||||
|
||||
~Object ()
|
||||
{
|
||||
deactivate ();
|
||||
}
|
||||
|
||||
void becomeActive ()
|
||||
{
|
||||
// Add ourselves to the active list
|
||||
if (!m_isActive)
|
||||
{
|
||||
s_activeList.push_front (*this);
|
||||
m_isActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
void deactivate ()
|
||||
{
|
||||
if (m_isActive)
|
||||
{
|
||||
// Doesn't delete the object
|
||||
s_activeList.erase (s_activeList.iterator_to (this));
|
||||
|
||||
m_isActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_isActive;
|
||||
|
||||
static List <Object, GlobalListTag> s_globalList;
|
||||
static List <Object, ActiveListTag> s_activeList;
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
||||
@defgroup intrusive intrusive
|
||||
@ingroup beast_core
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <typename, typename>
|
||||
class List;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// This is the intrusive portion of the doubly linked list.
|
||||
// One derivation per list that the object may appear on
|
||||
// concurrently is required.
|
||||
//
|
||||
template <typename T, typename Tag>
|
||||
class ListNode : public Uncopyable
|
||||
{
|
||||
private:
|
||||
typedef T value_type;
|
||||
|
||||
template <typename, typename>
|
||||
friend class List;
|
||||
|
||||
template <typename>
|
||||
friend class ListIterator;
|
||||
|
||||
ListNode* m_next;
|
||||
ListNode* m_prev;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <typename N>
|
||||
class ListIterator : public std::iterator <
|
||||
std::bidirectional_iterator_tag, std::size_t>
|
||||
{
|
||||
public:
|
||||
typedef typename copyconst <N, typename N::value_type>::type
|
||||
|
||||
value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
ListIterator (N* node = nullptr) noexcept
|
||||
: m_node (node)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
ListIterator (ListIterator <M> const& other) noexcept
|
||||
: m_node (other.m_node)
|
||||
{
|
||||
}
|
||||
|
||||
#if 0
|
||||
template <typename M>
|
||||
ListIterator& operator= (ListIterator <M> const& other) noexcept
|
||||
{
|
||||
m_node = other.m_node;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
template <typename M>
|
||||
bool operator== (ListIterator <M> const& other) const noexcept
|
||||
{
|
||||
return m_node == other.m_node;
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
bool operator!= (ListIterator <M> const& other) const noexcept
|
||||
{
|
||||
return ! ((*this) == other);
|
||||
}
|
||||
|
||||
reference operator* () const noexcept
|
||||
{
|
||||
return dereference ();
|
||||
}
|
||||
|
||||
pointer operator-> () const noexcept
|
||||
{
|
||||
return &dereference ();
|
||||
}
|
||||
|
||||
ListIterator& operator++ () noexcept
|
||||
{
|
||||
increment ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ListIterator operator++ (int) noexcept
|
||||
{
|
||||
ListIterator result (*this);
|
||||
increment ();
|
||||
return result;
|
||||
}
|
||||
|
||||
ListIterator& operator-- () noexcept
|
||||
{
|
||||
decrement ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ListIterator operator-- (int) noexcept
|
||||
{
|
||||
ListIterator result (*this);
|
||||
decrement ();
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
reference dereference () const noexcept
|
||||
{
|
||||
return static_cast <reference> (*m_node);
|
||||
}
|
||||
|
||||
void increment () noexcept
|
||||
{
|
||||
bassert (m_node->m_next);
|
||||
m_node = m_node->m_next;
|
||||
}
|
||||
|
||||
void decrement () noexcept
|
||||
{
|
||||
bassert (m_node->m_prev &&
|
||||
m_node->m_prev->m_prev != nullptr);
|
||||
m_node = m_node->m_prev;
|
||||
}
|
||||
|
||||
N* m_node;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Intrusive doubly linked list.
|
||||
|
||||
This intrusive List is a container similar in operation to std::list in the
|
||||
Standard Template Library (STL). Like all @ref intrusive containers, List
|
||||
requires you to first derive your class from List<>::Node:
|
||||
|
||||
@code
|
||||
|
||||
struct Object : List <Object>::Node
|
||||
{
|
||||
explicit Object (int value) : m_value (value)
|
||||
{
|
||||
}
|
||||
|
||||
int m_value;
|
||||
};
|
||||
|
||||
@endcode
|
||||
|
||||
Now we define the list, and add a couple of items.
|
||||
|
||||
@code
|
||||
|
||||
List <Object> list;
|
||||
|
||||
list.push_back (* (new Object (1)));
|
||||
list.push_back (* (new Object (2)));
|
||||
|
||||
@endcode
|
||||
|
||||
For compatibility with the standard containers, push_back() expects a
|
||||
reference to the object. Unlike the standard container, however, push_back()
|
||||
places the actual object in the list and not a copy-constructed duplicate.
|
||||
|
||||
Iterating over the list follows the same idiom as the STL:
|
||||
|
||||
@code
|
||||
|
||||
for (List <Object>::iterator iter = list.begin(); iter != list.end; ++iter)
|
||||
std::cout << iter->m_value;
|
||||
|
||||
@endcode
|
||||
|
||||
You can even use BOOST_FOREACH, or range based for loops:
|
||||
|
||||
@code
|
||||
|
||||
BOOST_FOREACH (Object& object, list) // boost only
|
||||
std::cout << object.m_value;
|
||||
|
||||
for (Object& object : list) // C++11 only
|
||||
std::cout << object.m_value;
|
||||
|
||||
@endcode
|
||||
|
||||
Because List is mostly STL compliant, it can be passed into STL algorithms:
|
||||
e.g. `std::for_each()` or `std::find_first_of()`.
|
||||
|
||||
In general, objects placed into a List should be dynamically allocated
|
||||
although this cannot be enforced at compile time. Since the caller provides
|
||||
the storage for the object, the caller is also responsible for deleting the
|
||||
object. An object still exists after being removed from a List, until the
|
||||
caller deletes it. This means an element can be moved from one List to
|
||||
another with practically no overhead.
|
||||
|
||||
Unlike the standard containers, an object may only exist in one list at a
|
||||
time, unless special preparations are made. The Tag template parameter is
|
||||
used to distinguish between different list types for the same object,
|
||||
allowing the object to exist in more than one list simultaneously.
|
||||
|
||||
For example, consider an actor system where a global list of actors is
|
||||
maintained, so that they can each be periodically receive processing
|
||||
time. We wish to also maintain a list of the subset of actors that require
|
||||
a domain-dependent update. To achieve this, we declare two tags, the
|
||||
associated list types, and the list element thusly:
|
||||
|
||||
@code
|
||||
|
||||
struct Actor; // Forward declaration required
|
||||
|
||||
struct ProcessTag { };
|
||||
struct UpdateTag { };
|
||||
|
||||
typedef List <Actor, ProcessTag> ProcessList;
|
||||
typedef List <Actor, UpdateTag> UpdateList;
|
||||
|
||||
// Derive from both node types so we can be in each list at once.
|
||||
//
|
||||
struct Actor : ProcessList::Node, UpdateList::Node
|
||||
{
|
||||
bool process (); // returns true if we need an update
|
||||
void update ();
|
||||
};
|
||||
|
||||
@endcode
|
||||
|
||||
@tparam T The base type of element which the list will store
|
||||
pointers to.
|
||||
|
||||
@tparam Tag An optional unique type name used to distinguish lists and nodes,
|
||||
when the object can exist in multiple lists simultaneously.
|
||||
|
||||
@ingroup beast_core intrusive
|
||||
*/
|
||||
template <typename T, typename Tag = void>
|
||||
class List : public Uncopyable
|
||||
{
|
||||
public:
|
||||
typedef typename detail::ListNode <T, Tag> Node;
|
||||
|
||||
typedef T value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef value_type& reference;
|
||||
typedef value_type const* const_pointer;
|
||||
typedef value_type const& const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef detail::ListIterator <Node> iterator;
|
||||
typedef detail::ListIterator <Node const> const_iterator;
|
||||
|
||||
/** Create an empty list. */
|
||||
List ()
|
||||
{
|
||||
m_head.m_prev = nullptr; // identifies the head
|
||||
m_tail.m_next = nullptr; // identifies the tail
|
||||
clear ();
|
||||
}
|
||||
|
||||
/** Determine if the list is empty.
|
||||
@return `true` if the list is empty.
|
||||
*/
|
||||
bool empty () const noexcept
|
||||
{
|
||||
return size () == 0;
|
||||
}
|
||||
|
||||
/** Returns the number of elements in the list. */
|
||||
size_type size () const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
/** Obtain a reference to the first element.
|
||||
@invariant The list may not be empty.
|
||||
@return A reference to the first element.
|
||||
*/
|
||||
reference front () noexcept
|
||||
{
|
||||
return element_from (m_head.m_next);
|
||||
}
|
||||
|
||||
/** Obtain a const reference to the first element.
|
||||
@invariant The list may not be empty.
|
||||
@return A const reference to the first element.
|
||||
*/
|
||||
const_reference front () const noexcept
|
||||
{
|
||||
return element_from (m_head.m_next);
|
||||
}
|
||||
|
||||
/** Obtain a reference to the last element.
|
||||
@invariant The list may not be empty.
|
||||
@return A reference to the last element.
|
||||
*/
|
||||
reference back () noexcept
|
||||
{
|
||||
return element_from (m_tail.m_prev);
|
||||
}
|
||||
|
||||
/** Obtain a const reference to the last element.
|
||||
@invariant The list may not be empty.
|
||||
@return A const reference to the last element.
|
||||
*/
|
||||
const_reference back () const noexcept
|
||||
{
|
||||
return element_from (m_tail.m_prev);
|
||||
}
|
||||
|
||||
/** Obtain an iterator to the beginning of the list.
|
||||
@return An iterator pointing to the beginning of the list.
|
||||
*/
|
||||
iterator begin () noexcept
|
||||
{
|
||||
return iterator (m_head.m_next);
|
||||
}
|
||||
|
||||
/** Obtain a const iterator to the beginning of the list.
|
||||
@return A const iterator pointing to the beginning of the list.
|
||||
*/
|
||||
const_iterator begin () const noexcept
|
||||
{
|
||||
return const_iterator (m_head.m_next);
|
||||
}
|
||||
|
||||
/** Obtain a const iterator to the beginning of the list.
|
||||
@return A const iterator pointing to the beginning of the list.
|
||||
*/
|
||||
const_iterator cbegin () const noexcept
|
||||
{
|
||||
return const_iterator (m_head.m_next);
|
||||
}
|
||||
|
||||
/** Obtain a iterator to the end of the list.
|
||||
@return An iterator pointing to the end of the list.
|
||||
*/
|
||||
iterator end () noexcept
|
||||
{
|
||||
return iterator (&m_tail);
|
||||
}
|
||||
|
||||
/** Obtain a const iterator to the end of the list.
|
||||
@return A constiterator pointing to the end of the list.
|
||||
*/
|
||||
const_iterator end () const noexcept
|
||||
{
|
||||
return const_iterator (&m_tail);
|
||||
}
|
||||
|
||||
/** Obtain a const iterator to the end of the list
|
||||
@return A constiterator pointing to the end of the list.
|
||||
*/
|
||||
const_iterator cend () const noexcept
|
||||
{
|
||||
return const_iterator (&m_tail);
|
||||
}
|
||||
|
||||
/** Clear the list.
|
||||
@note This does not free the elements.
|
||||
*/
|
||||
void clear () noexcept
|
||||
{
|
||||
m_head.m_next = &m_tail;
|
||||
m_tail.m_prev = &m_head;
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
/** Insert an element.
|
||||
@invariant The element must not already be in the list.
|
||||
@param pos The location to insert after.
|
||||
@param element The element to insert.
|
||||
@return An iterator pointing to the newly inserted element.
|
||||
*/
|
||||
iterator insert (iterator pos, T& element) noexcept
|
||||
{
|
||||
Node* node = static_cast <Node*> (&element);
|
||||
node->m_next = &*pos;
|
||||
node->m_prev = node->m_next->m_prev;
|
||||
node->m_next->m_prev = node;
|
||||
node->m_prev->m_next = node;
|
||||
++m_size;
|
||||
return iterator (node);
|
||||
}
|
||||
|
||||
/** Insert another list into this one.
|
||||
The other list is cleared.
|
||||
@param pos The location to insert after.
|
||||
@param other The list to insert.
|
||||
*/
|
||||
|
||||
void insert (iterator pos, List& other) noexcept
|
||||
{
|
||||
if (!other.empty ())
|
||||
{
|
||||
Node* before = &*pos;
|
||||
other.m_head.m_next->m_prev = before->m_prev;
|
||||
before->m_prev->m_next = other.m_head.m_next;
|
||||
other.m_tail.m_prev->m_next = before;
|
||||
before->m_prev = other.m_tail.m_prev;
|
||||
m_size += other.m_size;
|
||||
other.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove an element.
|
||||
@invariant The element must exist in the list.
|
||||
@param pos An iterator pointing to the element to remove.
|
||||
@return An iterator pointing to the next element after the one removed.
|
||||
*/
|
||||
iterator erase (iterator pos) noexcept
|
||||
{
|
||||
Node* node = &*pos;
|
||||
++pos;
|
||||
node->m_next->m_prev = node->m_prev;
|
||||
node->m_prev->m_next = node->m_next;
|
||||
--m_size;
|
||||
return pos;
|
||||
}
|
||||
|
||||
/** Insert an element at the beginning of the list.
|
||||
@invariant The element must not exist in the list.
|
||||
@param element The element to insert.
|
||||
*/
|
||||
iterator push_front (T& element) noexcept
|
||||
{
|
||||
return insert (begin (), element);
|
||||
}
|
||||
|
||||
/** Remove the element at the beginning of the list.
|
||||
@invariant The list must not be empty.
|
||||
@return A reference to the popped element.
|
||||
*/
|
||||
T& pop_front () noexcept
|
||||
{
|
||||
T& element (front ());
|
||||
erase (begin ());
|
||||
return element;
|
||||
}
|
||||
|
||||
/** Append an element at the end of the list.
|
||||
@invariant The element must not exist in the list.
|
||||
@param element The element to append.
|
||||
*/
|
||||
iterator push_back (T& element) noexcept
|
||||
{
|
||||
return insert (end (), element);
|
||||
}
|
||||
|
||||
/** Remove the element at the end of the list.
|
||||
@invariant The list must not be empty.
|
||||
@return A reference to the popped element.
|
||||
*/
|
||||
T& pop_back () noexcept
|
||||
{
|
||||
T& element (back ());
|
||||
erase (--end ());
|
||||
return element;
|
||||
}
|
||||
|
||||
/** Swap contents with another list. */
|
||||
void swap (List& other) noexcept
|
||||
{
|
||||
List temp;
|
||||
temp.append (other);
|
||||
other.append (*this);
|
||||
append (temp);
|
||||
}
|
||||
|
||||
/** Insert another list at the beginning of this list.
|
||||
The other list is cleared.
|
||||
@param list The other list to insert.
|
||||
*/
|
||||
iterator prepend (List& list) noexcept
|
||||
{
|
||||
return insert (begin (), list);
|
||||
}
|
||||
|
||||
/** Append another list at the end of this list.
|
||||
The other list is cleared.
|
||||
@param list the other list to append.
|
||||
*/
|
||||
iterator append (List& list) noexcept
|
||||
{
|
||||
return insert (end (), list);
|
||||
}
|
||||
|
||||
/** Obtain an iterator from an element.
|
||||
@invariant The element must exist in the list.
|
||||
@param element The element to obtain an iterator for.
|
||||
@return An iterator to the element.
|
||||
*/
|
||||
iterator iterator_to (T& element) const noexcept
|
||||
{
|
||||
return iterator (static_cast <Node*> (&element));
|
||||
}
|
||||
|
||||
/** Obtain a const iterator from an element.
|
||||
@invariant The element must exist in the list.
|
||||
@param element The element to obtain an iterator for.
|
||||
@return A const iterator to the element.
|
||||
*/
|
||||
const_iterator const_iterator_to (T const& element) const noexcept
|
||||
{
|
||||
return const_iterator (static_cast <Node const*> (&element));
|
||||
}
|
||||
|
||||
private:
|
||||
reference element_from (Node* node) noexcept
|
||||
{
|
||||
return *(static_cast <pointer> (node));
|
||||
}
|
||||
|
||||
const_reference element_from (Node const* node) const noexcept
|
||||
{
|
||||
return *(static_cast <const_pointer> (node));
|
||||
}
|
||||
|
||||
private:
|
||||
size_type m_size;
|
||||
Node m_head;
|
||||
Node m_tail;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -17,14 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_LOCKFREEQUEUE_H_INCLUDED
|
||||
#define BEAST_LOCKFREEQUEUE_H_INCLUDED
|
||||
|
||||
/** Default tag for LockFreeQueue
|
||||
|
||||
@ingroup beast_core intrusive
|
||||
*/
|
||||
struct LockFreeQueueDefaultTag { };
|
||||
#ifndef BEAST_INTRUSIVE_LOCKFREEQUEUE_H_INCLUDED
|
||||
#define BEAST_INTRUSIVE_LOCKFREEQUEUE_H_INCLUDED
|
||||
|
||||
/** Multiple Producer, Single Consumer (MPSC) intrusive FIFO.
|
||||
|
||||
@@ -46,7 +40,7 @@ struct LockFreeQueueDefaultTag { };
|
||||
|
||||
@ingroup beast_core intrusive
|
||||
*/
|
||||
template <class Element, class Tag = LockFreeQueueDefaultTag>
|
||||
template <class Element, class Tag = void>
|
||||
class LockFreeQueue
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -1,310 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_LOCKFREESTACK_H_INCLUDED
|
||||
#define BEAST_LOCKFREESTACK_H_INCLUDED
|
||||
|
||||
struct LockFreeStackDefaultTag;
|
||||
|
||||
/*============================================================================*/
|
||||
|
||||
template <class Container, bool IsConst>
|
||||
class LockFreeStackIterator
|
||||
: public std::iterator <
|
||||
std::forward_iterator_tag,
|
||||
typename Container::value_type,
|
||||
typename Container::difference_type,
|
||||
typename mpl::IfCond <IsConst,
|
||||
typename Container::const_pointer,
|
||||
typename Container::pointer>::type,
|
||||
typename mpl::IfCond <IsConst,
|
||||
typename Container::const_reference,
|
||||
typename Container::reference>::type>
|
||||
{
|
||||
protected:
|
||||
typedef typename Container::Node Node;
|
||||
typedef typename mpl::IfCond <IsConst, Node const*, Node*>::type NodePtr;
|
||||
|
||||
public:
|
||||
typedef typename Container::value_type value_type;
|
||||
typedef typename mpl::IfCond <IsConst,
|
||||
typename Container::const_pointer,
|
||||
typename Container::pointer>::type pointer;
|
||||
typedef typename mpl::IfCond <IsConst,
|
||||
typename Container::const_reference,
|
||||
typename Container::reference>::type reference;
|
||||
|
||||
LockFreeStackIterator ()
|
||||
: m_node ()
|
||||
{
|
||||
}
|
||||
|
||||
LockFreeStackIterator (NodePtr node)
|
||||
: m_node (node)
|
||||
{
|
||||
}
|
||||
|
||||
template <bool OtherIsConst>
|
||||
explicit LockFreeStackIterator (LockFreeStackIterator <Container, OtherIsConst> const& other)
|
||||
: m_node (other.m_node)
|
||||
{
|
||||
}
|
||||
|
||||
LockFreeStackIterator& operator= (NodePtr node)
|
||||
{
|
||||
m_node = node;
|
||||
return static_cast <LockFreeStackIterator&> (*this);
|
||||
}
|
||||
|
||||
LockFreeStackIterator& operator++ ()
|
||||
{
|
||||
m_node = m_node->m_next;
|
||||
return static_cast <LockFreeStackIterator&> (*this);
|
||||
}
|
||||
|
||||
LockFreeStackIterator operator++ (int)
|
||||
{
|
||||
LockFreeStackIterator result (*this);
|
||||
m_node = m_node->m_next;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <bool OtherIsConst>
|
||||
bool operator== (LockFreeStackIterator <Container, OtherIsConst> const& other)
|
||||
{
|
||||
return m_node == other.m_node;
|
||||
}
|
||||
|
||||
template <bool OtherIsConst>
|
||||
bool operator!= (LockFreeStackIterator <Container, OtherIsConst> const& other)
|
||||
{
|
||||
return m_node != other.m_node;
|
||||
}
|
||||
|
||||
reference operator* () const
|
||||
{
|
||||
return *this->operator-> ();
|
||||
}
|
||||
|
||||
pointer operator-> () const
|
||||
{
|
||||
return static_cast <pointer> (m_node);
|
||||
}
|
||||
|
||||
private:
|
||||
NodePtr m_node;
|
||||
};
|
||||
|
||||
/**
|
||||
Multiple Producer, Multiple Consumer (MPMC) intrusive stack.
|
||||
|
||||
This stack is implemented using the same intrusive interface as List. All
|
||||
operations are lock-free.
|
||||
|
||||
The caller is responsible for preventing the "ABA" problem
|
||||
(http://en.wikipedia.org/wiki/ABA_problem)
|
||||
|
||||
@param Tag A type name used to distinguish lists and nodes, for
|
||||
putting objects in multiple lists. If this parameter is
|
||||
omitted, the default tag is used.
|
||||
|
||||
@ingroup beast_core intrusive
|
||||
*/
|
||||
template <class Element, class Tag = void>
|
||||
class LockFreeStack : public Uncopyable
|
||||
{
|
||||
public:
|
||||
class Node : public Uncopyable
|
||||
{
|
||||
public:
|
||||
Node ()
|
||||
{
|
||||
}
|
||||
|
||||
explicit Node (Node* next) : m_next (next)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend class LockFreeStack;
|
||||
|
||||
template <class Container, bool IsConst>
|
||||
friend class LockFreeStackIterator;
|
||||
|
||||
// VFALCO TODO Use regular Atomic<>
|
||||
AtomicPointer <Node> m_next;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef Element value_type;
|
||||
typedef Element* pointer;
|
||||
typedef Element& reference;
|
||||
typedef Element const* const_pointer;
|
||||
typedef Element const& const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef LockFreeStackIterator <
|
||||
LockFreeStack <Element, Tag>, false> iterator;
|
||||
typedef LockFreeStackIterator <
|
||||
LockFreeStack <Element, Tag>, true> const_iterator;
|
||||
|
||||
LockFreeStack () : m_head (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** Create a LockFreeStack from another stack.
|
||||
|
||||
The contents of the other stack are atomically acquired.
|
||||
The other stack is cleared.
|
||||
|
||||
@param other The other stack to acquire.
|
||||
*/
|
||||
explicit LockFreeStack (LockFreeStack& other)
|
||||
{
|
||||
Node* head;
|
||||
|
||||
do
|
||||
{
|
||||
head = other.m_head.get ();
|
||||
}
|
||||
while (!other.m_head.compareAndSet (0, head));
|
||||
|
||||
m_head = head;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Return the number of elements in the stack.
|
||||
|
||||
Thread safety:
|
||||
Safe to call from any thread but the value may be inaccurate.
|
||||
*/
|
||||
size_type size () const
|
||||
{
|
||||
return m_size.get ();
|
||||
}
|
||||
|
||||
/** Push a node onto the stack.
|
||||
|
||||
The caller is responsible for preventing the ABA problem. This operation
|
||||
is lock-free.
|
||||
|
||||
@param node The node to push.
|
||||
|
||||
@return True if the stack was previously empty. If multiple threads
|
||||
are attempting to push, only one will receive true.
|
||||
*/
|
||||
bool push_front (Node* node)
|
||||
{
|
||||
bool first;
|
||||
Node* head;
|
||||
|
||||
do
|
||||
{
|
||||
head = m_head.get ();
|
||||
first = head == 0;
|
||||
node->m_next = head;
|
||||
}
|
||||
while (!m_head.compareAndSet (node, head));
|
||||
|
||||
++m_size;
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
/** Pop an element off the stack.
|
||||
|
||||
The caller is responsible for preventing the ABA problem. This operation
|
||||
is lock-free.
|
||||
|
||||
@return The element that was popped, or nullptr if the stack was empty.
|
||||
*/
|
||||
Element* pop_front ()
|
||||
{
|
||||
Node* node;
|
||||
Node* head;
|
||||
|
||||
do
|
||||
{
|
||||
node = m_head.get ();
|
||||
|
||||
if (node == 0)
|
||||
break;
|
||||
|
||||
head = node->m_next.get ();
|
||||
}
|
||||
while (!m_head.compareAndSet (head, node));
|
||||
|
||||
--m_size;
|
||||
|
||||
return node ? static_cast <Element*> (node) : nullptr;
|
||||
}
|
||||
|
||||
/** Swap the contents of this stack with another stack.
|
||||
|
||||
This call is not thread safe or atomic. The caller is responsible for
|
||||
synchronizing access.
|
||||
|
||||
@param other The other stack to swap contents with.
|
||||
*/
|
||||
void swap (LockFreeStack& other)
|
||||
{
|
||||
Node* temp = other.m_head.get ();
|
||||
other.m_head.set (m_head.get ());
|
||||
m_head.set (temp);
|
||||
|
||||
std::swap (m_size.value, other.m_size.value);
|
||||
}
|
||||
|
||||
iterator begin ()
|
||||
{
|
||||
return iterator (m_head.get ());
|
||||
}
|
||||
|
||||
iterator end ()
|
||||
{
|
||||
return iterator ();
|
||||
}
|
||||
|
||||
const_iterator begin () const
|
||||
{
|
||||
return const_iterator (m_head.get ());
|
||||
}
|
||||
|
||||
const_iterator end () const
|
||||
{
|
||||
return const_iterator ();
|
||||
}
|
||||
|
||||
const_iterator cbegin () const
|
||||
{
|
||||
return const_iterator (m_head.get ());
|
||||
}
|
||||
|
||||
const_iterator cend () const
|
||||
{
|
||||
return const_iterator ();
|
||||
}
|
||||
|
||||
private:
|
||||
Atomic <size_type> m_size;
|
||||
AtomicPointer <Node> m_head;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,41 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_CORE_CONTAINERS_DETAIL_COPYCONST_H_INCLUDED
|
||||
#define BEAST_CORE_CONTAINERS_DETAIL_COPYCONST_H_INCLUDED
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Copy const attribute from T to U if present
|
||||
template <typename T, typename U>
|
||||
struct copyconst
|
||||
{
|
||||
typedef typename removecv <U>::type type;
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct copyconst <T const, U>
|
||||
{
|
||||
typedef typename removecv <U>::type const type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,73 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_CORE_CONTAINERS_DETAIL_REMOVECV_H_INCLUDED
|
||||
#define BEAST_CORE_CONTAINERS_DETAIL_REMOVECV_H_INCLUDED
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Strip all cv qualifiers from T
|
||||
template <typename T>
|
||||
struct removecv
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct removecv <const T>
|
||||
{
|
||||
typedef typename removecv <T>::type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct removecv <volatile T>
|
||||
{
|
||||
typedef typename removecv <T>::type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct removecv <const volatile T>
|
||||
{
|
||||
typedef typename removecv <T>::type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct removecv <T*>
|
||||
{
|
||||
typedef typename removecv <T>::type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct removecv <T&>
|
||||
{
|
||||
typedef typename removecv <T>::type type;
|
||||
};
|
||||
|
||||
#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
template <typename T>
|
||||
struct removecv <T&&>
|
||||
{
|
||||
typedef typename removecv <T>::type type;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,389 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Portions of this file are from JUCE.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
Please visit http://www.juce.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_ATOMIC_H_INCLUDED
|
||||
#define BEAST_ATOMIC_H_INCLUDED
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Simple class to hold a primitive value and perform atomic operations on it.
|
||||
|
||||
The type used must be a 32 or 64 bit primitive, like an int, pointer, etc.
|
||||
There are methods to perform most of the basic atomic operations.
|
||||
*/
|
||||
template <typename Type>
|
||||
class Atomic
|
||||
{
|
||||
public:
|
||||
/** Creates a new value, initialised to zero. */
|
||||
inline Atomic() noexcept
|
||||
: value (0)
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a new value, with a given initial value. */
|
||||
inline Atomic (const Type initialValue) noexcept
|
||||
: value (initialValue)
|
||||
{
|
||||
}
|
||||
|
||||
/** Copies another value (atomically). */
|
||||
inline Atomic (const Atomic& other) noexcept
|
||||
: value (other.get())
|
||||
{
|
||||
}
|
||||
|
||||
/** Destructor. */
|
||||
inline ~Atomic() noexcept
|
||||
{
|
||||
// This class can only be used for types which are 32 or 64 bits in size.
|
||||
static_bassert (sizeof (Type) == 4 || sizeof (Type) == 8);
|
||||
}
|
||||
|
||||
/** Atomically reads and returns the current value. */
|
||||
Type get() const noexcept;
|
||||
|
||||
/** Copies another value onto this one (atomically). */
|
||||
inline Atomic& operator= (const Atomic& other) noexcept { exchange (other.get()); return *this; }
|
||||
|
||||
/** Copies another value onto this one (atomically). */
|
||||
inline Atomic& operator= (const Type newValue) noexcept { exchange (newValue); return *this; }
|
||||
|
||||
/** Atomically sets the current value. */
|
||||
void set (Type newValue) noexcept { exchange (newValue); }
|
||||
|
||||
/** Atomically sets the current value, returning the value that was replaced. */
|
||||
Type exchange (Type value) noexcept;
|
||||
|
||||
/** Atomically adds a number to this value, returning the new value. */
|
||||
Type operator+= (Type amountToAdd) noexcept;
|
||||
|
||||
/** Atomically subtracts a number from this value, returning the new value. */
|
||||
Type operator-= (Type amountToSubtract) noexcept;
|
||||
|
||||
/** Atomically increments this value, returning the new value. */
|
||||
Type operator++() noexcept;
|
||||
|
||||
/** Atomically decrements this value, returning the new value. */
|
||||
Type operator--() noexcept;
|
||||
|
||||
/** Atomically compares this value with a target value, and if it is equal, sets
|
||||
this to be equal to a new value.
|
||||
|
||||
This operation is the atomic equivalent of doing this:
|
||||
@code
|
||||
bool compareAndSetBool (Type newValue, Type valueToCompare)
|
||||
{
|
||||
if (get() == valueToCompare)
|
||||
{
|
||||
set (newValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@returns true if the comparison was true and the value was replaced; false if
|
||||
the comparison failed and the value was left unchanged.
|
||||
@see compareAndSetValue
|
||||
*/
|
||||
bool compareAndSetBool (Type newValue, Type valueToCompare) noexcept;
|
||||
|
||||
/** Atomically compares this value with a target value, and if it is equal, sets
|
||||
this to be equal to a new value.
|
||||
|
||||
This operation is the atomic equivalent of doing this:
|
||||
@code
|
||||
Type compareAndSetValue (Type newValue, Type valueToCompare)
|
||||
{
|
||||
Type oldValue = get();
|
||||
if (oldValue == valueToCompare)
|
||||
set (newValue);
|
||||
|
||||
return oldValue;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@returns the old value before it was changed.
|
||||
@see compareAndSetBool
|
||||
*/
|
||||
Type compareAndSetValue (Type newValue, Type valueToCompare) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
#if BEAST_64BIT
|
||||
BEAST_ALIGN (8)
|
||||
#else
|
||||
BEAST_ALIGN (4)
|
||||
#endif
|
||||
|
||||
/** The raw value that this class operates on.
|
||||
This is exposed publically in case you need to manipulate it directly
|
||||
for performance reasons.
|
||||
*/
|
||||
volatile Type value;
|
||||
|
||||
private:
|
||||
template <typename Dest, typename Source>
|
||||
static inline Dest castTo (Source value) noexcept { union { Dest d; Source s; } u; u.s = value; return u.d; }
|
||||
|
||||
static inline Type castFrom32Bit (int32 value) noexcept { return castTo <Type, int32> (value); }
|
||||
static inline Type castFrom64Bit (int64 value) noexcept { return castTo <Type, int64> (value); }
|
||||
static inline int32 castTo32Bit (Type value) noexcept { return castTo <int32, Type> (value); }
|
||||
static inline int64 castTo64Bit (Type value) noexcept { return castTo <int64, Type> (value); }
|
||||
|
||||
|
||||
Type operator++ (int); // better to just use pre-increment with atomics..
|
||||
Type operator-- (int);
|
||||
|
||||
/** This templated negate function will negate pointers as well as integers */
|
||||
template <typename ValueType>
|
||||
inline ValueType negateValue (ValueType n) noexcept
|
||||
{
|
||||
return sizeof (ValueType) == 1 ? (ValueType) -(signed char) n
|
||||
: (sizeof (ValueType) == 2 ? (ValueType) -(short) n
|
||||
: (sizeof (ValueType) == 4 ? (ValueType) -(int) n
|
||||
: ((ValueType) -(int64) n)));
|
||||
}
|
||||
|
||||
/** This templated negate function will negate pointers as well as integers */
|
||||
template <typename PointerType>
|
||||
inline PointerType* negateValue (PointerType* n) noexcept
|
||||
{
|
||||
return reinterpret_cast <PointerType*> (-reinterpret_cast <pointer_sized_int> (n));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/*
|
||||
The following code is in the header so that the atomics can be inlined where possible...
|
||||
*/
|
||||
#if BEAST_IOS || (BEAST_MAC && (BEAST_PPC || BEAST_CLANG || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)))
|
||||
#define BEAST_ATOMICS_MAC 1 // Older OSX builds using gcc4.1 or earlier
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
|
||||
#define BEAST_MAC_ATOMICS_VOLATILE
|
||||
#else
|
||||
#define BEAST_MAC_ATOMICS_VOLATILE volatile
|
||||
#endif
|
||||
|
||||
#if BEAST_PPC || BEAST_IOS
|
||||
// None of these atomics are available for PPC or for iOS 3.1 or earlier!!
|
||||
template <typename Type> static Type OSAtomicAdd64Barrier (Type b, BEAST_MAC_ATOMICS_VOLATILE Type* a) noexcept { bassertfalse; return *a += b; }
|
||||
template <typename Type> static Type OSAtomicIncrement64Barrier (BEAST_MAC_ATOMICS_VOLATILE Type* a) noexcept { bassertfalse; return ++*a; }
|
||||
template <typename Type> static Type OSAtomicDecrement64Barrier (BEAST_MAC_ATOMICS_VOLATILE Type* a) noexcept { bassertfalse; return --*a; }
|
||||
template <typename Type> static bool OSAtomicCompareAndSwap64Barrier (Type old, Type newValue, BEAST_MAC_ATOMICS_VOLATILE Type* value) noexcept
|
||||
{ bassertfalse; if (old == *value) { *value = newValue; return true; } return false; }
|
||||
#define BEAST_64BIT_ATOMICS_UNAVAILABLE 1
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#elif BEAST_GCC
|
||||
#define BEAST_ATOMICS_GCC 1 // GCC with intrinsics
|
||||
|
||||
#if BEAST_IOS || BEAST_ANDROID // (64-bit ops will compile but not link on these mobile OSes)
|
||||
#define BEAST_64BIT_ATOMICS_UNAVAILABLE 1
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#else
|
||||
#define BEAST_ATOMICS_WINDOWS 1 // Windows with intrinsics
|
||||
|
||||
#if BEAST_USE_INTRINSICS
|
||||
#ifndef __INTEL_COMPILER
|
||||
#pragma intrinsic (_InterlockedExchange, _InterlockedIncrement, _InterlockedDecrement, _InterlockedCompareExchange, \
|
||||
_InterlockedCompareExchange64, _InterlockedExchangeAdd, _ReadWriteBarrier)
|
||||
#endif
|
||||
#define beast_InterlockedExchange(a, b) _InterlockedExchange(a, b)
|
||||
#define beast_InterlockedIncrement(a) _InterlockedIncrement(a)
|
||||
#define beast_InterlockedDecrement(a) _InterlockedDecrement(a)
|
||||
#define beast_InterlockedExchangeAdd(a, b) _InterlockedExchangeAdd(a, b)
|
||||
#define beast_InterlockedCompareExchange(a, b, c) _InterlockedCompareExchange(a, b, c)
|
||||
#define beast_InterlockedCompareExchange64(a, b, c) _InterlockedCompareExchange64(a, b, c)
|
||||
#define beast_MemoryBarrier _ReadWriteBarrier
|
||||
#else
|
||||
long beast_InterlockedExchange (volatile long* a, long b) noexcept;
|
||||
long beast_InterlockedIncrement (volatile long* a) noexcept;
|
||||
long beast_InterlockedDecrement (volatile long* a) noexcept;
|
||||
long beast_InterlockedExchangeAdd (volatile long* a, long b) noexcept;
|
||||
long beast_InterlockedCompareExchange (volatile long* a, long b, long c) noexcept;
|
||||
__int64 beast_InterlockedCompareExchange64 (volatile __int64* a, __int64 b, __int64 c) noexcept;
|
||||
inline void beast_MemoryBarrier() noexcept { long x = 0; beast_InterlockedIncrement (&x); }
|
||||
#endif
|
||||
|
||||
#if BEAST_64BIT
|
||||
#ifndef __INTEL_COMPILER
|
||||
#pragma intrinsic (_InterlockedExchangeAdd64, _InterlockedExchange64, _InterlockedIncrement64, _InterlockedDecrement64)
|
||||
#endif
|
||||
#define beast_InterlockedExchangeAdd64(a, b) _InterlockedExchangeAdd64(a, b)
|
||||
#define beast_InterlockedExchange64(a, b) _InterlockedExchange64(a, b)
|
||||
#define beast_InterlockedIncrement64(a) _InterlockedIncrement64(a)
|
||||
#define beast_InterlockedDecrement64(a) _InterlockedDecrement64(a)
|
||||
#else
|
||||
// None of these atomics are available in a 32-bit Windows build!!
|
||||
template <typename Type> static Type beast_InterlockedExchangeAdd64 (volatile Type* a, Type b) noexcept { bassertfalse; Type old = *a; *a += b; return old; }
|
||||
template <typename Type> static Type beast_InterlockedExchange64 (volatile Type* a, Type b) noexcept { bassertfalse; Type old = *a; *a = b; return old; }
|
||||
template <typename Type> static Type beast_InterlockedIncrement64 (volatile Type* a) noexcept { bassertfalse; return ++*a; }
|
||||
template <typename Type> static Type beast_InterlockedDecrement64 (volatile Type* a) noexcept { bassertfalse; return --*a; }
|
||||
#define BEAST_64BIT_ATOMICS_UNAVAILABLE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BEAST_MSVC
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4311) // (truncation warning)
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::get() const noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) OSAtomicAdd32Barrier ((int32_t) 0, (BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value))
|
||||
: castFrom64Bit ((int64) OSAtomicAdd64Barrier ((int64_t) 0, (BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value));
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) beast_InterlockedExchangeAdd ((volatile long*) &value, (long) 0))
|
||||
: castFrom64Bit ((int64) beast_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) 0));
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_add_and_fetch ((volatile int32*) &value, 0))
|
||||
: castFrom64Bit ((int64) __sync_add_and_fetch ((volatile int64*) &value, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::exchange (const Type newValue) noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC || BEAST_ATOMICS_GCC
|
||||
Type currentVal = value;
|
||||
while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; }
|
||||
return currentVal;
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) beast_InterlockedExchange ((volatile long*) &value, (long) castTo32Bit (newValue)))
|
||||
: castFrom64Bit ((int64) beast_InterlockedExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue)));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::operator+= (const Type amountToAdd) noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
return sizeof (Type) == 4 ? (Type) OSAtomicAdd32Barrier ((int32_t) castTo32Bit (amountToAdd), (BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value)
|
||||
: (Type) OSAtomicAdd64Barrier ((int64_t) amountToAdd, (BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value);
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? (Type) (beast_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd)
|
||||
: (Type) (beast_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd);
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
return (Type) __sync_add_and_fetch (&value, amountToAdd);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::operator-= (const Type amountToSubtract) noexcept
|
||||
{
|
||||
return operator+= (negateValue (amountToSubtract));
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::operator++() noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
return sizeof (Type) == 4 ? (Type) OSAtomicIncrement32Barrier ((BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value)
|
||||
: (Type) OSAtomicIncrement64Barrier ((BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value);
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? (Type) beast_InterlockedIncrement ((volatile long*) &value)
|
||||
: (Type) beast_InterlockedIncrement64 ((volatile __int64*) &value);
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
return (Type) __sync_add_and_fetch (&value, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::operator--() noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
return sizeof (Type) == 4 ? (Type) OSAtomicDecrement32Barrier ((BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value)
|
||||
: (Type) OSAtomicDecrement64Barrier ((BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value);
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? (Type) beast_InterlockedDecrement ((volatile long*) &value)
|
||||
: (Type) beast_InterlockedDecrement64 ((volatile __int64*) &value);
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
return (Type) __sync_add_and_fetch (&value, -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline bool Atomic<Type>::compareAndSetBool (const Type newValue, const Type valueToCompare) noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
return sizeof (Type) == 4 ? OSAtomicCompareAndSwap32Barrier ((int32_t) castTo32Bit (valueToCompare), (int32_t) castTo32Bit (newValue), (BEAST_MAC_ATOMICS_VOLATILE int32_t*) &value)
|
||||
: OSAtomicCompareAndSwap64Barrier ((int64_t) castTo64Bit (valueToCompare), (int64_t) castTo64Bit (newValue), (BEAST_MAC_ATOMICS_VOLATILE int64_t*) &value);
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return compareAndSetValue (newValue, valueToCompare) == valueToCompare;
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
return sizeof (Type) == 4 ? __sync_bool_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue))
|
||||
: __sync_bool_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue));
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type Atomic<Type>::compareAndSetValue (const Type newValue, const Type valueToCompare) noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
for (;;) // Annoying workaround for only having a bool CAS operation..
|
||||
{
|
||||
if (compareAndSetBool (newValue, valueToCompare))
|
||||
return valueToCompare;
|
||||
|
||||
const Type result = value;
|
||||
if (result != valueToCompare)
|
||||
return result;
|
||||
}
|
||||
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) beast_InterlockedCompareExchange ((volatile long*) &value, (long) castTo32Bit (newValue), (long) castTo32Bit (valueToCompare)))
|
||||
: castFrom64Bit ((int64) beast_InterlockedCompareExchange64 ((volatile __int64*) &value, (__int64) castTo64Bit (newValue), (__int64) castTo64Bit (valueToCompare)));
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
return sizeof (Type) == 4 ? castFrom32Bit ((int32) __sync_val_compare_and_swap ((volatile int32*) &value, castTo32Bit (valueToCompare), castTo32Bit (newValue)))
|
||||
: castFrom64Bit ((int64) __sync_val_compare_and_swap ((volatile int64*) &value, castTo64Bit (valueToCompare), castTo64Bit (newValue)));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void memoryBarrier() noexcept
|
||||
{
|
||||
#if BEAST_ATOMICS_MAC
|
||||
OSMemoryBarrier();
|
||||
#elif BEAST_ATOMICS_GCC
|
||||
__sync_synchronize();
|
||||
#elif BEAST_ATOMICS_WINDOWS
|
||||
beast_MemoryBarrier();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BEAST_MSVC
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,10 +30,7 @@ namespace CacheLine
|
||||
|
||||
#if GLOBAL_PADDING_ENABLED
|
||||
|
||||
// Pads an object so that it starts on a cache line boundary.
|
||||
//
|
||||
/** Pad an object to start on a cache line boundary.
|
||||
|
||||
Up to 8 constructor parameters are passed through.
|
||||
*/
|
||||
template <typename T>
|
||||
@@ -42,83 +39,83 @@ class Aligned
|
||||
public:
|
||||
Aligned ()
|
||||
{
|
||||
new (ptr ()) T;
|
||||
new (&get()) T;
|
||||
}
|
||||
|
||||
template <class T1>
|
||||
Aligned (T1 t1)
|
||||
{
|
||||
new (ptr ()) T (t1);
|
||||
new (&get()) T (t1);
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
Aligned (T1 t1, T2 t2)
|
||||
{
|
||||
new (ptr ()) T (t1, t2);
|
||||
new (&get()) T (t1, t2);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
Aligned (T1 t1, T2 t2, T3 t3)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3);
|
||||
new (&get()) T (t1, t2, t3);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
Aligned (T1 t1, T2 t2, T3 t3, T4 t4)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4);
|
||||
new (&get()) T (t1, t2, t3, t4);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
Aligned (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4, t5);
|
||||
new (&get()) T (t1, t2, t3, t4, t5);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
Aligned (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4, t5, t6);
|
||||
new (&get()) T (t1, t2, t3, t4, t5, t6);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
|
||||
Aligned (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4, t5, t6, t7);
|
||||
new (&get()) 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 (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
|
||||
{
|
||||
new (ptr ()) T (t1, t2, t3, t4, t5, t6, t7, t8);
|
||||
new (&get()) T (t1, t2, t3, t4, t5, t6, t7, t8);
|
||||
}
|
||||
|
||||
~Aligned ()
|
||||
{
|
||||
ptr ()->~T ();
|
||||
get().~T ();
|
||||
}
|
||||
|
||||
T& operator= (T const& other)
|
||||
{
|
||||
*ptr () = other;
|
||||
return *ptr ();
|
||||
return (get() = 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 T const& () const noexcept { return *ptr (); }
|
||||
inline operator T const* () const noexcept { return ptr (); }
|
||||
T& get () noexcept { return *ptr(); }
|
||||
T& operator* () noexcept { return get(); }
|
||||
T* operator-> () noexcept { return &get(); }
|
||||
operator T& () noexcept { return get(); }
|
||||
operator T* () noexcept { return &get(); }
|
||||
T const& get () const noexcept { return *ptr(); }
|
||||
const T& operator* () const noexcept { return get(); }
|
||||
const T* operator-> () const noexcept { return &get(); }
|
||||
operator T const& () const noexcept { return get(); }
|
||||
operator T const* () const noexcept { return &get(); }
|
||||
|
||||
private:
|
||||
inline T* ptr () noexcept
|
||||
T* ptr () const noexcept
|
||||
{
|
||||
return (T*) ((uintptr_t (m_storage) + Memory::cacheLineAlignMask)
|
||||
& ~Memory::cacheLineAlignMask);
|
||||
& ~Memory::cacheLineAlignMask);
|
||||
/*
|
||||
return reinterpret_cast <T*> (Memory::pointerAdjustedForAlignment (
|
||||
m_storage, Memory::cacheLineBytes));
|
||||
@@ -128,8 +125,9 @@ private:
|
||||
char m_storage [ (sizeof (T) + Memory::cacheLineAlignMask) & ~Memory::cacheLineAlignMask];
|
||||
};
|
||||
|
||||
/** End-pads an object to completely fill straddling CPU cache lines.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** End-pads an object to completely fill straddling CPU cache lines.
|
||||
The caller must ensure that this object starts at the beginning
|
||||
of a cache line.
|
||||
*/
|
||||
@@ -195,15 +193,16 @@ public:
|
||||
return m_t;
|
||||
}
|
||||
|
||||
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 T const& () const noexcept { return m_t; }
|
||||
operator T const* () const noexcept { return &m_t; }
|
||||
T& get() noexcept { return m_t;}
|
||||
T& operator* () noexcept { return get(); }
|
||||
T* operator-> () noexcept { return &get(); }
|
||||
operator T& () noexcept { return get(); }
|
||||
operator T* () noexcept { return &get(); }
|
||||
T const& get () const noexcept { return m_t; }
|
||||
const T& operator* () const noexcept { return get(); }
|
||||
const T* operator-> () const noexcept { return &get(); }
|
||||
operator T const& () const noexcept { return get(); }
|
||||
operator T const* () const noexcept { return &get(); }
|
||||
|
||||
private:
|
||||
T m_t;
|
||||
@@ -257,32 +256,21 @@ public:
|
||||
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)
|
||||
T& operator= (const T& other)
|
||||
{
|
||||
m_t = other;
|
||||
reutrn (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;
|
||||
}
|
||||
T& get () noexcept { return m_t; }
|
||||
T& operator* () noexcept { return get(); }
|
||||
T* operator-> () noexcept { return &get(); }
|
||||
operator T& () noexcept { return get(); }
|
||||
operator T* () noexcept { return &get(); }
|
||||
T const& get () const noexcept { return m_t; }
|
||||
const T& operator* () const noexcept { return get(); }
|
||||
const T* operator-> () const noexcept { return &get(); }
|
||||
operator T const& () const noexcept { return get(); }
|
||||
operator T const* () const noexcept { return &get(); }
|
||||
|
||||
private:
|
||||
T m_t;
|
||||
@@ -338,27 +326,16 @@ public:
|
||||
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;
|
||||
}
|
||||
T& get () noexcept { return m_t; }
|
||||
T& operator* () noexcept { return get(); }
|
||||
T* operator-> () noexcept { return &get(); }
|
||||
operator T& () noexcept { return get(); }
|
||||
operator T* () noexcept { return &get(); }
|
||||
T const& get () const noexcept { return m_t; }
|
||||
const T& operator* () const noexcept { return get(); }
|
||||
const T* operator-> () const noexcept { return &get(); }
|
||||
operator T const& () const noexcept { return get(); }
|
||||
operator T const* () const noexcept { return &get(); }
|
||||
|
||||
private:
|
||||
T m_t;
|
||||
@@ -415,44 +392,21 @@ public:
|
||||
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)
|
||||
T* operator= (const T& other)
|
||||
{
|
||||
m_t = other;
|
||||
return (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;
|
||||
}
|
||||
T& get () noexcept { return m_t; }
|
||||
T& operator* () noexcept { return get(); }
|
||||
T* operator-> () noexcept { return &get(); }
|
||||
operator T& () noexcept { return get(); }
|
||||
operator T* () noexcept { return &get(); }
|
||||
T const& get () const noexcept { return m_t; }
|
||||
const T& operator* () const noexcept { return get(); }
|
||||
const T* operator-> () const noexcept { return &get(); }
|
||||
operator T const& () const noexcept { return get(); }
|
||||
operator T const* () const noexcept { return &get(); }
|
||||
|
||||
private:
|
||||
T m_t;
|
||||
|
||||
@@ -181,7 +181,7 @@ void PagedFreeStore::onDeadlineTimer (DeadlineTimer&)
|
||||
}
|
||||
}
|
||||
|
||||
m_cold->fresh->swap (m_cold->garbage);
|
||||
std::swap (m_cold->fresh, m_cold->garbage);
|
||||
|
||||
// Swap atomically with respect to m_hot
|
||||
Pool* temp = m_hot;
|
||||
@@ -224,6 +224,6 @@ void PagedFreeStore::dispose (Pages& pages)
|
||||
|
||||
void PagedFreeStore::dispose (Pool& pool)
|
||||
{
|
||||
dispose (pool.fresh);
|
||||
dispose (pool.garbage);
|
||||
dispose (pool.fresh_c);
|
||||
dispose (pool.garbage_c);
|
||||
}
|
||||
|
||||
@@ -64,8 +64,16 @@ private:
|
||||
|
||||
struct Pool
|
||||
{
|
||||
CacheLine::Padded <Pages> fresh;
|
||||
CacheLine::Padded <Pages> garbage;
|
||||
Pool()
|
||||
: fresh (&fresh_c.get())
|
||||
, garbage (&garbage_c.get())
|
||||
{
|
||||
}
|
||||
|
||||
Pages* fresh;
|
||||
Pages* garbage;
|
||||
CacheLine::Padded <Pages> fresh_c;
|
||||
CacheLine::Padded <Pages> garbage_c;
|
||||
};
|
||||
|
||||
static inline void* fromPage (Page* const p);
|
||||
|
||||
@@ -275,10 +275,10 @@ public:
|
||||
};
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < threads.size(); ++i)
|
||||
for (int i = 0; i < threads.size(); ++i)
|
||||
threads[i]->stop ();
|
||||
|
||||
for (std::size_t i = 0; i < threads.size(); ++i)
|
||||
for (int i = 0; i < threads.size(); ++i)
|
||||
threads[i]->waitForThreadToExit();
|
||||
|
||||
double const secondsElapsed ((Time::getCurrentTime() - startTime).inSeconds ());
|
||||
|
||||
@@ -222,7 +222,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void testThreads (std::size_t nThreads)
|
||||
void testThreads (int nThreads)
|
||||
{
|
||||
beginTestCase (String::fromNumber (nThreads) + " threads");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user