Migrate some headers and general tidying

This commit is contained in:
Vinnie Falco
2013-09-21 16:37:09 -07:00
parent 1a3cddc002
commit 9d9c822efb
30 changed files with 262 additions and 391 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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 ());

View File

@@ -222,7 +222,7 @@ public:
{
}
void testThreads (std::size_t nThreads)
void testThreads (int nThreads)
{
beginTestCase (String::fromNumber (nThreads) + " threads");