Commit 912f9cd9 authored by Dominik Charousset's avatar Dominik Charousset

improved any_tuple interface

this patch adds the member functions `drop`, `drop_right`, `take`,
and `take_right` to the class `any_tuple`.
parent 6804da2f
...@@ -103,6 +103,7 @@ set(LIBCPPA_SRC ...@@ -103,6 +103,7 @@ set(LIBCPPA_SRC
src/context_switching_actor.cpp src/context_switching_actor.cpp
src/continuable_reader.cpp src/continuable_reader.cpp
src/continuable_writer.cpp src/continuable_writer.cpp
src/decorated_tuple.cpp
src/default_actor_addressing.cpp src/default_actor_addressing.cpp
src/default_actor_proxy.cpp src/default_actor_proxy.cpp
src/default_peer.cpp src/default_peer.cpp
......
...@@ -294,3 +294,4 @@ src/get_mac_addresses.cpp ...@@ -294,3 +294,4 @@ src/get_mac_addresses.cpp
cppa/util/get_root_uuid.hpp cppa/util/get_root_uuid.hpp
src/get_root_uuid.cpp src/get_root_uuid.cpp
cppa/util/type_traits.hpp cppa/util/type_traits.hpp
src/decorated_tuple.cpp
...@@ -110,7 +110,27 @@ class any_tuple { ...@@ -110,7 +110,27 @@ class any_tuple {
/** /**
* @brief Gets the size of this tuple. * @brief Gets the size of this tuple.
*/ */
size_t size() const; inline size_t size() const;
/**
* @brief Creates a new tuple with all but the first n values.
*/
any_tuple drop(size_t n) const;
/**
* @brief Creates a new tuple with all but the last n values.
*/
any_tuple drop_right(size_t n) const;
/**
* @brief Creates a new tuple from the first n values.
*/
inline any_tuple take(size_t n) const;
/**
* @brief Creates a new tuple from the last n values.
*/
inline any_tuple take_right(size_t n) const;
/** /**
* @brief Gets a mutable pointer to the element at position @p p. * @brief Gets a mutable pointer to the element at position @p p.
...@@ -310,6 +330,18 @@ inline void any_tuple::force_detach() { ...@@ -310,6 +330,18 @@ inline void any_tuple::force_detach() {
m_vals.detach(); m_vals.detach();
} }
inline size_t any_tuple::size() const {
return m_vals->size();
}
inline any_tuple any_tuple::take(size_t n) const {
return n >= size() ? *this : drop_right(size() - n);
}
inline any_tuple any_tuple::take_right(size_t n) const {
return n >= size() ? *this : drop(size() - n);
}
template<typename T, bool IsIterable = true> template<typename T, bool IsIterable = true>
struct any_tuple_view_trait_impl { struct any_tuple_view_trait_impl {
static constexpr bool is_mutable_ref = std::is_reference<T>::value static constexpr bool is_mutable_ref = std::is_reference<T>::value
......
...@@ -73,7 +73,6 @@ class cow_tuple<Head, Tail...> { ...@@ -73,7 +73,6 @@ class cow_tuple<Head, Tail...> {
friend class any_tuple; friend class any_tuple;
typedef detail::tuple_vals<Head, Tail...> data_type; typedef detail::tuple_vals<Head, Tail...> data_type;
typedef detail::decorated_tuple<Head, Tail...> decorated_type;
cow_ptr<detail::abstract_tuple> m_vals; cow_ptr<detail::abstract_tuple> m_vals;
...@@ -114,7 +113,8 @@ class cow_tuple<Head, Tail...> { ...@@ -114,7 +113,8 @@ class cow_tuple<Head, Tail...> {
static cow_tuple offset_subtuple(cow_ptr_type ptr, size_t offset) { static cow_tuple offset_subtuple(cow_ptr_type ptr, size_t offset) {
CPPA_REQUIRE(offset > 0); CPPA_REQUIRE(offset > 0);
return {priv_ctor{}, decorated_type::create(std::move(ptr), offset)}; auto ti = detail::static_type_list<Head, Tail...>::by_offset(offset);
return {priv_ctor{}, detail::decorated_tuple::create(std::move(ptr), ti, offset)};
} }
/** /**
...@@ -152,9 +152,15 @@ class cow_tuple<Head, Tail...> { ...@@ -152,9 +152,15 @@ class cow_tuple<Head, Tail...> {
return {priv_ctor{}, std::move(ptr)}; return {priv_ctor{}, std::move(ptr)};
} }
static cow_tuple from(cow_ptr_type ptr, static cow_tuple from(cow_ptr_type ptr, std::vector<size_t> mv) {
const util::limited_vector<size_t, num_elements>& mv) { auto ti = detail::static_type_list<Head, Tail...>::list;
return {priv_ctor{}, decorated_type::create(std::move(ptr), mv)}; return {priv_ctor{}, detail::decorated_tuple::create(std::move(ptr), ti, std::move(mv))};
}
static cow_tuple from(cow_ptr_type ptr, const util::limited_vector<size_t, num_elements>& mv) {
std::vector<size_t> v(mv.size());
std::copy(mv.begin(), mv.end(), v.begin());
return from(ptr, std::move(v));
} }
inline const cow_ptr<detail::abstract_tuple>& vals() const { inline const cow_ptr<detail::abstract_tuple>& vals() const {
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/limited_vector.hpp"
#include "cppa/detail/tuple_vals.hpp" #include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/abstract_tuple.hpp" #include "cppa/detail/abstract_tuple.hpp"
...@@ -48,97 +47,72 @@ ...@@ -48,97 +47,72 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<typename... Ts>
class decorated_tuple : public abstract_tuple { class decorated_tuple : public abstract_tuple {
typedef abstract_tuple super; typedef abstract_tuple super;
static_assert(sizeof...(Ts) > 0, decorated_tuple& operator=(const decorated_tuple&) = delete;
"decorated_tuple is not allowed to be empty");
public: public:
typedef util::limited_vector<size_t, sizeof...(Ts)> vector_type; typedef std::vector<size_t> vector_type;
typedef cow_ptr<abstract_tuple> cow_pointer_type; typedef cow_ptr<abstract_tuple> pointer;
static inline cow_pointer_type create(cow_pointer_type d, typedef const std::type_info* rtti;
const vector_type& v) {
return cow_pointer_type{new decorated_tuple(std::move(d), v)};
}
// creates a subtuple form @p d with an offset // creates a dynamically typed subtuple from @p d with an offset
static inline cow_pointer_type create(cow_pointer_type d, size_t offset) { static inline pointer create(pointer d, vector_type v) {
return cow_pointer_type{new decorated_tuple(std::move(d), offset)}; return pointer{new decorated_tuple(std::move(d), std::move(v))};
} }
virtual void* mutable_at(size_t pos) { // creates a statically typed subtuple from @p d with an offset
CPPA_REQUIRE(pos < size()); static inline pointer create(pointer d, rtti ti, vector_type v) {
return m_decorated->mutable_at(m_mapping[pos]); return pointer{new decorated_tuple(std::move(d), ti, std::move(v))};
} }
virtual size_t size() const { // creates a dynamically typed subtuple from @p d with an offset
return sizeof...(Ts); static inline pointer create(pointer d, size_t offset) {
return pointer{new decorated_tuple(std::move(d), offset)};
} }
virtual decorated_tuple* copy() const { // creates a statically typed subtuple from @p d with an offset
return new decorated_tuple(*this); static inline pointer create(pointer d, rtti ti, size_t offset) {
return pointer{new decorated_tuple(std::move(d), ti, offset)};
} }
virtual const void* at(size_t pos) const { virtual void* mutable_at(size_t pos) override;
CPPA_REQUIRE(pos < size());
return m_decorated->at(m_mapping[pos]);
}
virtual const uniform_type_info* type_at(size_t pos) const { virtual size_t size() const override;
CPPA_REQUIRE(pos < size());
return m_decorated->type_at(m_mapping[pos]);
}
const std::type_info* type_token() const { virtual decorated_tuple* copy() const override;
return static_type_list<Ts...>::list;
} virtual const void* at(size_t pos) const override;
virtual const uniform_type_info* type_at(size_t pos) const override;
rtti type_token() const override;
private: private:
cow_pointer_type m_decorated; pointer m_decorated;
rtti m_token;
vector_type m_mapping; vector_type m_mapping;
decorated_tuple(cow_pointer_type d, const vector_type& v) void init();
: super(false)
, m_decorated(std::move(d)), m_mapping(v) {
# ifdef CPPA_DEBUG_MODE
const cow_pointer_type& ptr = m_decorated; // prevent detaching
# endif
CPPA_REQUIRE(ptr->size() >= sizeof...(Ts));
CPPA_REQUIRE(v.size() == sizeof...(Ts));
CPPA_REQUIRE(*(std::max_element(v.begin(), v.end())) < ptr->size());
}
decorated_tuple(cow_pointer_type d, size_t offset) void init(size_t);
: super(false), m_decorated(std::move(d)) {
# ifdef CPPA_DEBUG_MODE
const cow_pointer_type& ptr = m_decorated; // prevent detaching
# endif
CPPA_REQUIRE((ptr->size() - offset) >= sizeof...(Ts));
CPPA_REQUIRE(offset > 0);
size_t i = offset;
m_mapping.resize(sizeof...(Ts));
std::generate(m_mapping.begin(), m_mapping.end(), [&]() {return i++;});
}
decorated_tuple(const decorated_tuple&) = default; decorated_tuple(pointer, size_t);
decorated_tuple& operator=(const decorated_tuple&) = delete; decorated_tuple(pointer, rtti, size_t);
}; decorated_tuple(pointer, vector_type&&);
decorated_tuple(pointer, rtti, vector_type&&);
template<typename TypeList> decorated_tuple(const decorated_tuple&) = default;
struct decorated_cow_tuple_from_type_list;
template<typename... Ts>
struct decorated_cow_tuple_from_type_list< util::type_list<Ts...> > {
typedef decorated_tuple<Ts...> type;
}; };
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#include "cppa/detail/types_array.hpp" #include "cppa/detail/types_array.hpp"
#include "cppa/detail/object_array.hpp" #include "cppa/detail/object_array.hpp"
#include "cppa/detail/abstract_tuple.hpp" #include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/decorated_tuple.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
......
...@@ -183,14 +183,32 @@ struct static_types_array_from_type_list<util::type_list<T...>> { ...@@ -183,14 +183,32 @@ struct static_types_array_from_type_list<util::type_list<T...>> {
typedef static_types_array<T...> type; typedef static_types_array<T...> type;
}; };
// utility for singleton-like access to a type_info instance of a type_list
template<typename... T> template<typename... T>
struct static_type_list { struct static_type_list;
template<typename T>
struct static_type_list<T> {
static const std::type_info* list; static const std::type_info* list;
static inline const std::type_info* by_offset(size_t offset) {
return offset == 0 ? list : &typeid(util::type_list<>);
}
}; };
template<typename... T> template<typename T>
const std::type_info* static_type_list<T...>::list = &typeid(util::type_list<T...>); const std::type_info* static_type_list<T>::list = &typeid(util::type_list<T>);
// utility for singleton-like access to a type_info instance of a type_list
template<typename T0, typename T1, typename... Ts>
struct static_type_list<T0, T1, Ts...> {
static const std::type_info* list;
static inline const std::type_info* by_offset(size_t offset) {
return offset == 0 ? list : static_type_list<T1, Ts...>::list;
}
};
template<typename T0, typename T1, typename... Ts>
const std::type_info* static_type_list<T0, T1, Ts...>::list = &typeid(util::type_list<T0, T1, Ts...>);
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -53,10 +53,6 @@ void any_tuple::reset() { ...@@ -53,10 +53,6 @@ void any_tuple::reset() {
m_vals.reset(get_empty_tuple()); m_vals.reset(get_empty_tuple());
} }
size_t any_tuple::size() const {
return m_vals->size();
}
void* any_tuple::mutable_at(size_t p) { void* any_tuple::mutable_at(size_t p) {
return m_vals->mutable_at(p); return m_vals->mutable_at(p);
} }
...@@ -73,4 +69,20 @@ bool any_tuple::equals(const any_tuple& other) const { ...@@ -73,4 +69,20 @@ bool any_tuple::equals(const any_tuple& other) const {
return m_vals->equals(*other.vals()); return m_vals->equals(*other.vals());
} }
any_tuple any_tuple::drop(size_t n) const {
if (n == 0) return *this;
if (n >= size()) return any_tuple{};
return any_tuple{detail::decorated_tuple::create(m_vals, n)};
}
any_tuple any_tuple::drop_right(size_t n) const {
using namespace std;
if (n == 0) return *this;
if (n >= size()) return any_tuple{};
vector<size_t> mapping(size() - n);
size_t i = 0;
generate(mapping.begin(), mapping.end(), [&] { return i++; });
return any_tuple{detail::decorated_tuple::create(m_vals, move(mapping))};
}
} // namespace cppa } // namespace cppa
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* 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 2.1 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/>. *
\******************************************************************************/
#include "cppa/detail/decorated_tuple.hpp"
namespace cppa { namespace detail {
void* decorated_tuple::mutable_at(size_t pos) {
CPPA_REQUIRE(pos < size());
return m_decorated->mutable_at(m_mapping[pos]);
}
size_t decorated_tuple::size() const {
return m_mapping.size();
}
decorated_tuple* decorated_tuple::copy() const {
return new decorated_tuple(*this);
}
const void* decorated_tuple::at(size_t pos) const {
CPPA_REQUIRE(pos < size());
return m_decorated->at(m_mapping[pos]);
}
const uniform_type_info* decorated_tuple::type_at(size_t pos) const {
CPPA_REQUIRE(pos < size());
return m_decorated->type_at(m_mapping[pos]);
}
auto decorated_tuple::type_token() const -> rtti {
return m_token;
}
void decorated_tuple::init() {
CPPA_REQUIRE( m_mapping.empty()
|| *(std::max_element(m_mapping.begin(), m_mapping.end()))
< static_cast<const pointer&>(m_decorated)->size());
}
void decorated_tuple::init(size_t offset) {
const pointer& dec = m_decorated;
if (offset < dec->size()) {
size_t i = offset;
m_mapping.resize(dec->size() - offset);
std::generate(m_mapping.begin(), m_mapping.end(), [&] {return i++;});
}
init();
}
decorated_tuple::decorated_tuple(pointer d, vector_type&& v)
: super(true), m_decorated(std::move(d)), m_token(&typeid(void)), m_mapping(std::move(v)) {
init();
}
decorated_tuple::decorated_tuple(pointer d, rtti ti, vector_type&& v)
: super(false), m_decorated(std::move(d)), m_token(ti), m_mapping(std::move(v)) {
init();
}
decorated_tuple::decorated_tuple(pointer d, size_t offset)
: super(true), m_decorated(std::move(d)), m_token(&typeid(void)) {
init(offset);
}
decorated_tuple::decorated_tuple(pointer d, rtti ti, size_t offset)
: super(false), m_decorated(std::move(d)), m_token(ti) {
init(offset);
}
} } // namespace cppa::detail
...@@ -395,6 +395,13 @@ void check_wildcards() { ...@@ -395,6 +395,13 @@ void check_wildcards() {
CPPA_CHECK(&get<0>(*opt3) == at1.at(0)); CPPA_CHECK(&get<0>(*opt3) == at1.at(0));
CPPA_CHECK(&get<1>(*opt3) == at1.at(3)); CPPA_CHECK(&get<1>(*opt3) == at1.at(3));
} }
auto opt4 = tuple_cast<anything, double>(at1);
CPPA_CHECK(opt4);
if (opt4) {
CPPA_CHECK((*opt4 == make_any_tuple(4.0)));
CPPA_CHECK_EQUAL(get<0>(*opt4), 4.0);
CPPA_CHECK(&get<0>(*opt4) == at1.at(3));
}
} }
} }
...@@ -409,6 +416,26 @@ void check_move_ops() { ...@@ -409,6 +416,26 @@ void check_move_ops() {
CPPA_CHECK_EQUAL(s_expensive_copies.load(), 0); CPPA_CHECK_EQUAL(s_expensive_copies.load(), 0);
} }
void check_drop() {
CPPA_PRINT(__func__);
auto t0 = make_any_tuple(0, 1, 2, 3);
auto t1 = t0.drop(2);
CPPA_CHECK_EQUAL(t1.size(), 2);
CPPA_CHECK_EQUAL(t1.get_as<int>(0), 2);
CPPA_CHECK_EQUAL(t1.get_as<int>(1), 3);
CPPA_CHECK(t1 == make_any_tuple(2, 3));
auto t2 = t0.drop_right(2);
CPPA_CHECK_EQUAL(t2.size(), 2);
CPPA_CHECK_EQUAL(t2.get_as<int>(0), 0);
CPPA_CHECK_EQUAL(t2.get_as<int>(1), 1);
CPPA_CHECK(t2 == make_any_tuple(0, 1));
CPPA_CHECK(t0.take(3) == t0.drop_right(1));
CPPA_CHECK(t0.take_right(3) == t0.drop(1));
CPPA_CHECK(t0 == t0.take(4));
CPPA_CHECK(t0.take(4) == t0.take_right(20));
CPPA_CHECK(t0.take(0).empty());
}
int main() { int main() {
CPPA_TEST(test_tuple); CPPA_TEST(test_tuple);
announce<expensive_copy_struct>(&expensive_copy_struct::value); announce<expensive_copy_struct>(&expensive_copy_struct::value);
...@@ -417,6 +444,7 @@ int main() { ...@@ -417,6 +444,7 @@ int main() {
check_guards(); check_guards();
check_wildcards(); check_wildcards();
check_move_ops(); check_move_ops();
check_drop();
await_all_others_done(); await_all_others_done();
shutdown(); shutdown();
return CPPA_TEST_RESULT(); return CPPA_TEST_RESULT();
......
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