Commit 1e561870 authored by neverlord's avatar neverlord

maintenance

parent f812b653
......@@ -149,6 +149,9 @@ nobase_library_include_HEADERS = \
cppa/fsm_actor.hpp \
cppa/get.hpp \
cppa/group.hpp \
cppa/intrusive/iterator.hpp \
cppa/intrusive/single_reader_queue.hpp \
cppa/intrusive/singly_linked_list.hpp \
cppa/intrusive_ptr.hpp \
cppa/local_actor.hpp \
cppa/match.hpp \
......@@ -182,7 +185,6 @@ nobase_library_include_HEADERS = \
cppa/util/comparable.hpp \
cppa/util/compare_tuples.hpp \
cppa/util/conjunction.hpp \
cppa/util/default_deallocator.hpp \
cppa/util/disable_if.hpp \
cppa/util/disjunction.hpp \
cppa/util/duration.hpp \
......@@ -213,8 +215,6 @@ nobase_library_include_HEADERS = \
cppa/util/rm_ref.hpp \
cppa/util/shared_lock_guard.hpp \
cppa/util/shared_spinlock.hpp \
cppa/util/single_reader_queue.hpp \
cppa/util/singly_linked_list.hpp \
cppa/util/static_foreach.hpp \
cppa/util/tbind.hpp \
cppa/util/type_list.hpp \
......
......@@ -48,8 +48,7 @@ cppa/util/replace_type.hpp
cppa/detail/serialize_tuple.hpp
unit_testing/test__atom.cpp
unit_testing/test__queue_performance.cpp
cppa/util/single_reader_queue.hpp
cppa/util/singly_linked_list.hpp
cppa/intrusive/single_reader_queue.hpp
unit_testing/test__local_group.cpp
cppa/detail/channel.hpp
cppa/local_actor.hpp
......@@ -232,7 +231,6 @@ benchmarks/mixed_case.erl
benchmarks/ActorCreation.scala
benchmarks/MailboxPerformance.scala
benchmarks/MixedCase.scala
cppa/util/default_deallocator.hpp
cppa/util/producer_consumer_list.hpp
cppa/util/arg_match_t.hpp
cppa/detail/types_array.hpp
......@@ -261,3 +259,6 @@ cppa/detail/tuple_cast_impl.hpp
cppa/match.hpp
cppa/partial_function.hpp
src/partial_function.cpp
cppa/intrusive/singly_linked_list.hpp
cppa/intrusive/iterator.hpp
unit_testing/test__intrusive_containers.cpp
......@@ -169,7 +169,7 @@ class abstract_actor : public Base
protected:
util::single_reader_queue<queue_node> m_mailbox;
intrusive::single_reader_queue<queue_node> m_mailbox;
template<typename T>
inline queue_node* fetch_node(actor* sender, T&& msg)
......
......@@ -36,8 +36,9 @@
#include "cppa/abstract_actor.hpp"
#include "cppa/util/fiber.hpp"
#include "cppa/util/singly_linked_list.hpp"
#include "cppa/util/single_reader_queue.hpp"
#include "cppa/intrusive/singly_linked_list.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
#include "cppa/detail/delegate.hpp"
......@@ -50,9 +51,9 @@ class abstract_scheduled_actor : public abstract_actor<local_actor>
{
friend class task_scheduler;
friend class util::single_reader_queue<abstract_scheduled_actor>;
friend class intrusive::single_reader_queue<abstract_scheduled_actor>;
abstract_scheduled_actor* next; // intrusive next pointer (single_reader_queue)
abstract_scheduled_actor* next; // intrusive next pointer
void enqueue_node(queue_node* node);
......@@ -63,8 +64,7 @@ class abstract_scheduled_actor : public abstract_actor<local_actor>
typedef abstract_actor super;
typedef super::queue_node queue_node;
typedef util::singly_linked_list<queue_node>
queue_node_buffer;
typedef intrusive::singly_linked_list<queue_node> queue_node_buffer;
enum dq_result
{
......
......@@ -48,7 +48,7 @@
#include "cppa/local_actor.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/abstract_actor.hpp"
#include "cppa/util/singly_linked_list.hpp"
#include "cppa/intrusive/singly_linked_list.hpp"
namespace cppa { namespace detail {
......@@ -86,8 +86,7 @@ class converted_thread_context : public abstract_actor<local_actor>
private:
typedef util::singly_linked_list<queue_node>
queue_node_buffer;
typedef intrusive::singly_linked_list<queue_node> queue_node_buffer;
enum throw_on_exit_result
{
......
......@@ -60,7 +60,9 @@ class invokable
public:
invokable() = default;
invokable* next;
inline invokable() : next(nullptr) { }
virtual ~invokable();
virtual bool invoke(any_tuple const&) const = 0;
......
......@@ -35,8 +35,8 @@
#include "cppa/actor_proxy.hpp"
#include "cppa/process_information.hpp"
#include "cppa/detail/native_socket.hpp"
#include "cppa/util/single_reader_queue.hpp"
#include "cppa/detail/addressed_message.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
namespace cppa { namespace detail {
......@@ -67,7 +67,7 @@ struct mailman_add_peer
class mailman_job
{
friend class util::single_reader_queue<mailman_job>;
friend class intrusive::single_reader_queue<mailman_job>;
public:
......@@ -136,7 +136,7 @@ class mailman_job
void mailman_loop();
util::single_reader_queue<mailman_job>& mailman_queue();
intrusive::single_reader_queue<mailman_job>& mailman_queue();
}} // namespace cppa::detail
......
......@@ -49,9 +49,9 @@ class network_manager
virtual void stop() = 0;
virtual util::single_reader_queue<mailman_job>& mailman_queue() = 0;
virtual intrusive::single_reader_queue<mailman_job>& mailman_queue() = 0;
virtual util::single_reader_queue<post_office_msg>& post_office_queue() = 0;
virtual intrusive::single_reader_queue<post_office_msg>& post_office_queue() = 0;
static network_manager* create_singleton();
......
......@@ -36,14 +36,14 @@
#include "cppa/intrusive_ptr.hpp"
#include "cppa/process_information.hpp"
#include "cppa/detail/native_socket.hpp"
#include "cppa/util/single_reader_queue.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
namespace cppa { namespace detail {
class post_office_msg
{
friend class util::single_reader_queue<post_office_msg>;
friend class intrusive::single_reader_queue<post_office_msg>;
public:
......
......@@ -34,7 +34,7 @@
#include "cppa/scheduler.hpp"
#include "cppa/detail/thread.hpp"
#include "cppa/detail/abstract_scheduled_actor.hpp"
#include "cppa/util/single_reader_queue.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
namespace cppa { namespace detail {
......@@ -43,7 +43,7 @@ class task_scheduler : public scheduler
typedef scheduler super;
typedef util::single_reader_queue<abstract_scheduled_actor> job_queue;
typedef intrusive::single_reader_queue<abstract_scheduled_actor> job_queue;
job_queue m_queue;
scheduled_actor_dummy m_dummy;
......
......@@ -44,8 +44,6 @@
#include "cppa/detail/yield_interface.hpp"
#include "cppa/detail/abstract_scheduled_actor.hpp"
#include "cppa/util/singly_linked_list.hpp"
namespace cppa { namespace detail {
class yielding_actor : public abstract_scheduled_actor
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef ITERATOR_HPP
#define ITERATOR_HPP
#include <iterator>
namespace cppa { namespace intrusive {
template<class T>
class iterator // : std::iterator<forward_iterator_tag, T>
{
public:
typedef T value_type;
typedef value_type& reference;
typedef value_type const& const_reference;
typedef value_type* pointer;
typedef value_type const* const_pointer;
typedef ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category;
inline iterator(T* ptr) : m_ptr(ptr) { }
iterator(iterator const&) = default;
iterator& operator=(iterator const&) = default;
inline iterator& operator++()
{
m_ptr = m_ptr->next;
return *this;
}
inline iterator operator++(int)
{
iterator tmp{*this};
m_ptr = m_ptr->next;
return tmp;
}
inline reference operator*() { return *m_ptr; }
inline const_reference operator*() const { return *m_ptr; }
inline pointer operator->() { return m_ptr; }
inline const_pointer operator->() const { return m_ptr; }
inline pointer ptr() { return m_ptr; }
inline const_pointer ptr() const { return m_ptr; }
private:
pointer m_ptr;
};
template<class T>
inline bool operator==(iterator<T> const& lhs, iterator<T> const& rhs)
{
return lhs.ptr() == rhs.ptr();
}
template<class T>
inline bool operator==(iterator<T> const& lhs, T const* rhs)
{
return lhs.ptr() == rhs;
}
template<class T>
inline bool operator==(T const* lhs, iterator<T> const& rhs)
{
return lhs == rhs.ptr();
}
template<class T>
inline bool operator==(iterator<T> const& lhs, decltype(nullptr))
{
return lhs.ptr() == nullptr;
}
template<class T>
inline bool operator==(decltype(nullptr), iterator<T> const& rhs)
{
return rhs.ptr() == nullptr;
}
template<class T>
inline bool operator!=(iterator<T> const& lhs, iterator<T> const& rhs)
{
return !(lhs == rhs);
}
template<class T>
inline bool operator!=(iterator<T> const& lhs, T const* rhs)
{
return !(lhs == rhs);
}
template<class T>
inline bool operator!=(T const* lhs, iterator<T> const& rhs)
{
return !(lhs == rhs);
}
template<class T>
inline bool operator!=(iterator<T> const& lhs, decltype(nullptr))
{
return !(lhs == nullptr);
}
template<class T>
inline bool operator!=(decltype(nullptr), iterator<T> const& rhs)
{
return !(nullptr == rhs);
}
} } // namespace cppa::intrusive
#endif // ITERATOR_HPP
......@@ -34,19 +34,18 @@
#include <atomic>
#include "cppa/detail/thread.hpp"
#include "cppa/util/default_deallocator.hpp"
#include "cppa/intrusive/singly_linked_list.hpp"
namespace cppa { namespace util {
namespace cppa { namespace intrusive {
/**
* @brief An intrusive, thread safe queue implementation.
*/
template<typename T, class Deallocator = default_deallocator<T> >
template<typename T>
class single_reader_queue
{
typedef detail::unique_lock<detail::mutex> lock_type;
Deallocator d;
public:
......@@ -97,8 +96,9 @@ class single_reader_queue
/**
* @warning call only from the reader (owner)
*/
template<typename List>
void push_front(List&& list)
//template<typename List>
//void push_front(List&& list)
void push_front(singly_linked_list<T>&& list)
{
if (!list.empty())
{
......@@ -172,8 +172,7 @@ class single_reader_queue
{
element_type* tmp = e;
e = e->next;
d(tmp);
//delete tmp;
delete tmp;
}
}
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef SINGLY_LINKED_LIST_HPP
#define SINGLY_LINKED_LIST_HPP
#include <cstddef>
#include <utility>
#include "cppa/config.hpp"
#include "cppa/intrusive/iterator.hpp"
namespace cppa { namespace intrusive {
template<class T>
class singly_linked_list
{
singly_linked_list(singly_linked_list const&) = delete;
singly_linked_list& operator=(singly_linked_list const&) = delete;
public:
typedef T value_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef value_type& reference;
typedef value_type const& const_reference;
typedef value_type* pointer;
typedef value_type const* const_pointer;
typedef ::cppa::intrusive::iterator<value_type> iterator;
typedef ::cppa::intrusive::iterator<value_type const> const_iterator;
singly_linked_list() : m_head(nullptr), m_tail(nullptr) { }
singly_linked_list(singly_linked_list&& other)
: m_head(other.m_head), m_tail(other.m_tail)
{
other.m_head = other.m_tail = nullptr;
}
singly_linked_list& operator=(singly_linked_list&& other)
{
std::swap(m_head, other.m_head);
std::swap(m_tail, other.m_tail);
return *this;
}
static singly_linked_list from(std::pair<pointer, pointer> const& p)
{
singly_linked_list result;
result.m_head = p.first;
result.m_tail = p.second;
return result;
}
~singly_linked_list() { clear(); }
// element access
inline reference front() { return *m_head; }
inline const_reference front() const { return *m_head; }
inline reference back() { return *m_tail; }
inline const_reference back() const { return *m_tail; }
// iterators
inline iterator begin() { return m_head; }
inline const_iterator begin() const { return m_head; }
inline const_iterator cbegin() const { return m_head; }
inline iterator before_end() { return m_tail; }
inline const_iterator before_end() const { return m_tail; }
inline const_iterator cbefore_end() const { return m_tail; }
inline iterator end() { return nullptr; }
inline const_iterator end() const { return nullptr; }
inline const_iterator cend() const { return nullptr; }
// capacity
inline bool empty() const { return m_head == nullptr; }
// no size member function because it would have O(n) complexity
// modifiers
void clear()
{
while (m_head)
{
pointer next = m_head->next;
delete m_head;
m_head = next;
}
m_tail = nullptr;
}
iterator insert_after(iterator i, pointer what)
{
what->next = i->next;
i->next = what;
return what;
}
template<typename... Args>
void emplace_after(iterator i, Args&&... args)
{
insert_after(i, new value_type(std::forward<Args>(args)...));
}
iterator erase_after(iterator pos)
{
CPPA_REQUIRE(pos != nullptr);
auto next = pos->next;
if (next)
{
pos->next = next->next;
delete next;
}
return pos->next;
}
void push_back(pointer what)
{
what->next = nullptr;
if (empty())
{
m_tail = m_head = what;
}
else
{
m_tail->next = what;
m_tail = what;
}
}
template<typename... Args>
void emplace_back(Args&&... args)
{
push_back(new value_type(std::forward<Args>(args)...));
}
// pop_back would have complexity O(n)
void push_front(pointer what)
{
if (empty())
{
what->next = nullptr;
m_tail = m_head = what;
}
else
{
what->next = m_head;
m_head = what;
}
}
template<typename... Args>
void emplace_front(Args&&... args)
{
push_front(new value_type(std::forward<Args>(args)...));
}
void pop_front()
{
if (!empty())
{
auto next = m_head->next;
delete m_head;
m_head = next;
if (m_head == nullptr) m_tail = nullptr;
}
}
std::pair<pointer, pointer> take()
{
auto result = std::make_pair(m_head, m_tail);
m_head = m_tail = nullptr;
return result;
}
void splice_after(iterator pos, singly_linked_list&& other)
{
CPPA_REQUIRE(pos != nullptr);
CPPA_REQUIRE(this != &other);
if (other.empty() == false)
{
auto next = pos->next;
auto pair = other.take();
pos->next = pair.first;
pair.second->next = next;
if (pos == m_tail)
{
CPPA_REQUIRE(next == nullptr);
m_tail = pair.second;
}
}
}
template<typename UnaryPredicate>
void remove_if(UnaryPredicate p)
{
auto i = begin();
while (!empty() && p(*i))
{
pop_front();
i = begin();
}
if (empty()) return;
auto predecessor = i;
++i;
while (i != nullptr)
{
if (p(*i))
{
i = erase_after(predecessor);
}
else
{
predecessor = i;
++i;
}
}
}
void remove(value_type const& value)
{
remove_if([&](value_type const& other) { return value == other; });
}
private:
pointer m_head;
pointer m_tail;
};
} } // namespace cppa::intrusive
#endif // SINGLY_LINKED_LIST_HPP
......@@ -35,7 +35,7 @@
#include "cppa/behavior.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/util/single_reader_queue.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
namespace cppa {
......
......@@ -37,6 +37,7 @@
#include <utility>
#include "cppa/detail/invokable.hpp"
#include "cppa/intrusive/singly_linked_list.hpp"
namespace cppa {
......@@ -69,7 +70,8 @@ class partial_function
template<class... Args>
partial_function& splice(partial_function&& arg0, Args&&... args)
{
m_funs.splice(m_funs.end(), std::move(arg0.m_funs));
if (m_funs.empty()) m_funs = std::move(arg0.m_funs);
else m_funs.splice_after(m_funs.before_end(), std::move(arg0.m_funs));
return splice(std::forward<Args>(args)...);
}
......@@ -85,7 +87,7 @@ class partial_function
typedef std::vector<detail::invokable*> cache_entry;
typedef std::pair<void const*, cache_entry> cache_element;
std::list<invokable_ptr> m_funs;
intrusive::singly_linked_list<detail::invokable> m_funs;
std::vector<cache_element> m_cache;
cache_element m_dummy; // binary search dummy
......
#ifndef DEFAULT_DEALLOCATOR_HPP
#define DEFAULT_DEALLOCATOR_HPP
namespace cppa { namespace util {
template<typename T>
struct default_deallocator
{
inline void operator()(T* ptr) { delete ptr; }
};
} } // namespace cppa::detail
#endif // DEFAULT_DEALLOCATOR_HPP
......@@ -184,7 +184,6 @@ auto abstract_scheduled_actor::dq(queue_node_ptr& node,
if (!buffer.empty())
{
m_mailbox.push_front(std::move(buffer));
buffer.clear();
}
return dq_timeout_occured;
}
......@@ -199,7 +198,6 @@ auto abstract_scheduled_actor::dq(queue_node_ptr& node,
if (!buffer.empty())
{
m_mailbox.push_front(std::move(buffer));
buffer.clear();
}
// expire pending request
if (m_has_pending_timeout_request)
......
......@@ -90,11 +90,6 @@ mailman_job::~mailman_job()
}
}
/*
// implemented in post_office.cpp
util::single_reader_queue<mailman_job>& mailman_queue();
*/
// known issues: send() should be asynchronous and select() should be used
void mailman_loop()
{
......
......@@ -51,8 +51,8 @@ using namespace cppa::detail;
struct network_manager_impl : network_manager
{
typedef util::single_reader_queue<post_office_msg> post_office_queue_t;
typedef util::single_reader_queue<mailman_job> mailman_queue_t;
typedef intrusive::single_reader_queue<post_office_msg> post_office_queue_t;
typedef intrusive::single_reader_queue<mailman_job> mailman_queue_t;
int m_pipe[2]; // m_pipe[0]: read; m_pipe[1]: write
......@@ -88,12 +88,12 @@ struct network_manager_impl : network_manager
return m_pipe[1];
}
util::single_reader_queue<mailman_job>& mailman_queue()
mailman_queue_t& mailman_queue()
{
return m_mailman_queue;
}
util::single_reader_queue<post_office_msg>& post_office_queue()
post_office_queue_t& post_office_queue()
{
return m_post_office_queue;
}
......
......@@ -37,7 +37,7 @@ namespace cppa {
partial_function::partial_function(invokable_ptr&& ptr)
{
m_funs.push_back(std::move(ptr));
m_funs.push_back(ptr.release());
}
partial_function::partial_function(partial_function&& other)
......@@ -68,12 +68,9 @@ auto partial_function::get_cache_entry(any_tuple const& value) -> cache_entry&
{
// ... create one (store all invokables with matching types)
cache_entry tmp;
for (auto& fun : m_funs)
for (auto f = m_funs.begin(); f != m_funs.end(); ++f)
{
if (fun->types_match(value))
{
tmp.push_back(fun.get());
}
if (f->types_match(value)) tmp.push_back(f.ptr());
}
// m_cache is always sorted,
// due to emplace(upper_bound, ...) insertions
......
......@@ -52,8 +52,8 @@
#include "cppa/deserializer.hpp"
#include "cppa/binary_deserializer.hpp"
// used cppa utility
#include "cppa/util/single_reader_queue.hpp"
// used cppa intrusive containers
#include "cppa/intrusive/single_reader_queue.hpp"
// used cppa details
#include "cppa/detail/thread.hpp"
......@@ -103,7 +103,7 @@ constexpr int s_rdflag = MSG_DONTWAIT;
namespace cppa { namespace detail {
util::single_reader_queue<mailman_job>& mailman_queue()
intrusive::single_reader_queue<mailman_job>& mailman_queue()
{
return singleton_manager::get_network_manager()->mailman_queue();
}
......
......@@ -53,7 +53,7 @@ void enqueue_fun(cppa::detail::thread_pool_scheduler* where,
typedef unique_lock<mutex> guard_type;
typedef std::unique_ptr<thread_pool_scheduler::worker> worker_ptr;
typedef util::single_reader_queue<thread_pool_scheduler::worker> worker_queue;
typedef intrusive::single_reader_queue<thread_pool_scheduler::worker> worker_queue;
} // namespace <anonmyous>
......
......@@ -47,7 +47,7 @@
#include "cppa/binary_serializer.hpp"
#include "cppa/binary_deserializer.hpp"
#include "cppa/util/single_reader_queue.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
#include "cppa/detail/mailman.hpp"
#include "cppa/detail/post_office.hpp"
......
......@@ -7,6 +7,7 @@ unit_tests_SOURCES = main.cpp \
ping_pong.cpp \
test__atom.cpp \
test__fixed_vector.cpp \
test__intrusive_containers.cpp \
test__intrusive_ptr.cpp \
test__local_group.cpp \
test__pattern.cpp \
......
......@@ -160,6 +160,7 @@ int main(int argc, char** argv)
size_t errors = 0;
RUN_TEST(test__ripemd_160);
RUN_TEST(test__primitive_variant);
RUN_TEST(test__intrusive_containers);
RUN_TEST(test__uniform_type);
RUN_TEST(test__pattern);
RUN_TEST(test__intrusive_ptr);
......
......@@ -64,6 +64,7 @@ size_t test__serialization();
size_t test__local_group();
size_t test__primitive_variant();
size_t test__fixed_vector();
size_t test__intrusive_containers();
void test__queue_performance();
......
......@@ -28,70 +28,89 @@
\******************************************************************************/
#ifndef SINGLY_LINKED_LIST_HPP
#define SINGLY_LINKED_LIST_HPP
#include <iterator>
#include <utility>
#include "cppa/util/default_deallocator.hpp"
#include "test.hpp"
#include "cppa/intrusive/singly_linked_list.hpp"
namespace cppa { namespace util {
using std::begin;
using std::end;
template<typename T, class Deallocator = default_deallocator<T> >
class singly_linked_list
{
Deallocator d;
T* m_head;
T* m_tail;
public:
namespace { size_t s_iint_instances = 0; }
typedef T element_type;
singly_linked_list() : m_head(nullptr), m_tail(nullptr) { }
struct iint
{
iint* next;
int value;
inline iint(int val = 0) : next(nullptr), value(val) { ++s_iint_instances; }
~iint() { --s_iint_instances; }
};
~singly_linked_list()
{
clear();
}
inline bool operator==(iint const& lhs, iint const& rhs)
{
return lhs.value == rhs.value;
}
inline bool empty() const { return m_head == nullptr; }
inline bool operator==(iint const& lhs, int rhs)
{
return lhs.value == rhs;
}
void push_back(element_type* what)
{
what->next = nullptr;
if (m_tail)
{
m_tail->next = what;
m_tail = what;
}
else
{
m_head = m_tail = what;
}
}
inline bool operator==(int lhs, iint const& rhs)
{
return lhs == rhs.value;
}
std::pair<element_type*, element_type*> take()
{
element_type* first = m_head;
element_type* last = m_tail;
m_head = m_tail = nullptr;
return { first, last };
}
typedef cppa::intrusive::singly_linked_list<iint> iint_list;
void clear()
size_t test__intrusive_containers()
{
CPPA_TEST(test__intrusive_containers);
iint_list ilist1;
ilist1.push_back(new iint(1));
ilist1.emplace_back(2);
ilist1.push_back(new iint(3));
{
while (m_head)
{
T* next = m_head->next;
d(m_head);
m_head = next;
}
m_head = m_tail = nullptr;
iint_list tmp;
tmp.push_back(new iint(4));
tmp.push_back(new iint(5));
ilist1.splice_after(ilist1.before_end(), std::move(tmp));
CPPA_CHECK(tmp.empty());
}
};
} } // namespace cppa::util
#endif // SINGLY_LINKED_LIST_HPP
int iarr1[] = { 1, 2, 3, 4, 5 };
CPPA_CHECK((std::equal(begin(iarr1), end(iarr1), begin(ilist1))));
CPPA_CHECK((std::equal(begin(ilist1), end(ilist1), begin(iarr1))));
ilist1.push_front(new iint(0));
auto i = ilist1.erase_after(ilist1.begin());
// i points to second element
CPPA_CHECK_EQUAL(*i, 2);
i = ilist1.insert_after(i, new iint(20));
CPPA_CHECK_EQUAL(*i, 20);
int iarr2[] = { 0, 2, 20, 3, 4, 5 };
CPPA_CHECK((std::equal(begin(iarr2), end(iarr2), begin(ilist1))));
auto p = ilist1.take();
CPPA_CHECK(ilist1.empty());
auto ilist2 = iint_list::from(p);
ilist2.emplace_front(1); // 1 0 2 20 3 4 5
i = ilist2.erase_after(ilist2.begin()); // 1 2 20 3 4 5
CPPA_CHECK_EQUAL(*i, 2);
ilist2.erase_after(i); // 1 2 3 4 5
CPPA_CHECK((std::equal(begin(iarr1), end(iarr1), begin(ilist2))));
CPPA_CHECK_EQUAL(s_iint_instances, 5);
ilist2.remove_if([](iint const& val) { return (val.value % 2) != 0; });
CPPA_CHECK_EQUAL(s_iint_instances, 2);
int iarr3[] = { 2, 4 };
CPPA_CHECK((std::equal(begin(iarr3), end(iarr3), begin(ilist2))));
ilist2.clear();
CPPA_CHECK_EQUAL(s_iint_instances, 0);
CPPA_CHECK(ilist2.empty());
return CPPA_TEST_RESULT;
}
......@@ -7,7 +7,7 @@
#include <boost/thread.hpp>
#include <boost/progress.hpp>
#include "cppa/util/single_reader_queue.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
//#define DEBUG_RESULTS
......@@ -22,7 +22,7 @@ const size_t trials = 10;
using cppa::util::single_reader_queue;
using cppa::intrusive::single_reader_queue;
using std::cout;
using std::cerr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment