Add LockFreeStack iterators

This commit is contained in:
Vinnie Falco
2013-09-14 16:04:28 -07:00
parent d94e4c2491
commit 277e32bb1e

View File

@@ -23,6 +23,94 @@
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.
@@ -38,7 +126,7 @@ struct LockFreeStackDefaultTag;
@ingroup beast_core intrusive
*/
template <class Element, class Tag = LockFreeStackDefaultTag>
template <class Element, class Tag = void>
class LockFreeStack : public Uncopyable
{
public:
@@ -55,16 +143,32 @@ public:
private:
friend class LockFreeStack;
template <class Container, bool IsConst>
friend class LockFreeStackIterator;
// VFALCO TODO Use regular Atomic<>
AtomicPointer <Node> m_next;
};
public:
LockFreeStack () : m_head (0)
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.
@@ -84,6 +188,17 @@ public:
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.
@@ -108,6 +223,8 @@ public:
}
while (!m_head.compareAndSet (node, head));
++m_size;
return first;
}
@@ -134,6 +251,8 @@ public:
}
while (!m_head.compareAndSet (head, node));
--m_size;
return node ? static_cast <Element*> (node) : nullptr;
}
@@ -149,17 +268,43 @@ public:
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;
};
/*============================================================================*/
/** Default tag for LockFreeStack
@ingroup beast_core intrusive
*/
struct LockFreeStackDefaultTag { };
#endif