FC Updates from BitShares and myself #21

Closed
nathanielhourt wants to merge 687 commits from dapp-support into latest-fc
4 changed files with 165 additions and 51 deletions
Showing only changes of commit 1aecf3ccc8 - Show all commits

View file

@ -210,6 +210,7 @@ set( fc_sources
src/variant.cpp
src/exception.cpp
src/variant_object.cpp
src/static_variant.cpp
src/thread/thread.cpp
src/thread/thread_specific.cpp
src/thread/future.cpp

View file

@ -1,4 +1,4 @@
/** This source adapted from https://github.com/kmicklas/variadic-static_variant
/** This source adapted from https://github.com/kmicklas/variadic-static_variant. Now available at https://github.com/kmicklas/variadic-variant.
*
* Copyright (C) 2013 Kenneth Micklas
*
@ -178,6 +178,41 @@ struct type_info<> {
static const size_t size = 0;
};
template<typename TTag>
size_t size( TTag )
{
return 0;
}
template<typename TTag, typename A, typename...Ts>
size_t size( TTag tag )
{
if (tag <= 0)
{
return sizeof(A);
}
return size<TTag, Ts...>( --tag );
}
class dynamic_storage
{
char* storage;
public:
dynamic_storage();
~dynamic_storage();
void* data() const;
void alloc( size_t size );
void release();
};
} // namespace impl
template<int L,typename Visitor,typename Data>
@ -218,43 +253,61 @@ static const fc::array<typename Visitor::result_type(*)(Visitor&,Data),L>
template<typename... Types>
class static_variant {
protected:
static_assert(impl::type_info<Types...>::no_reference_types, "Reference types are not permitted in static_variant.");
static_assert(impl::type_info<Types...>::no_duplicates, "static_variant type arguments contain duplicate types.");
template<typename X>
using type_in_typelist = typename std::enable_if<impl::position<X, Types...>::pos != -1, X>::type; // type is in typelist of static_variant.
using tag_type = int64_t;
tag_type _tag;
char storage[impl::type_info<Types...>::size];
impl::dynamic_storage storage;
template<typename X>
template<typename X, typename = type_in_typelist<X>>
void init(const X& x) {
_tag = impl::position<X, Types...>::pos;
new(storage) X(x);
storage.alloc( sizeof(X) );
new(storage.data()) X(x);
}
template<typename X>
template<typename X, typename = type_in_typelist<X>>
void init(X&& x) {
_tag = impl::position<X, Types...>::pos;
new(storage) X( std::move(x) );
storage.alloc( sizeof(X) );
new(storage.data()) X( std::move(x) );
}
void init_from_tag(tag_type tag)
{
FC_ASSERT( tag >= 0 );
FC_ASSERT( tag < count() );
_tag = tag;
storage.alloc( impl::size<tag_type, Types...>( tag ) );
impl::storage_ops<0, Types...>::con(_tag, storage.data());
}
void clean()
{
impl::storage_ops<0, Types...>::del(_tag, storage.data() );
storage.release();
}
template<typename StaticVariant>
friend struct impl::copy_construct;
template<typename StaticVariant>
friend struct impl::move_construct;
public:
template<typename X>
template<typename X, typename = type_in_typelist<X>>
struct tag
{
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
static const int value = impl::position<X, Types...>::pos;
};
static_variant()
{
_tag = 0;
impl::storage_ops<0, Types...>::con(0, storage);
init_from_tag(0);
}
template<typename... Other>
@ -262,6 +315,7 @@ public:
{
cpy.visit( impl::copy_construct<static_variant>(*this) );
}
static_variant( const static_variant& cpy )
{
cpy.visit( impl::copy_construct<static_variant>(*this) );
@ -272,40 +326,32 @@ public:
mv.visit( impl::move_construct<static_variant>(*this) );
}
template<typename X>
template<typename X, typename = type_in_typelist<X>>
static_variant(const X& v) {
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
init(v);
}
~static_variant() {
impl::storage_ops<0, Types...>::del(_tag, storage);
clean();
}
template<typename X>
template<typename X, typename = type_in_typelist<X>>
static_variant& operator=(const X& v) {
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
this->~static_variant();
clean();
init(v);
return *this;
}
static_variant& operator=( const static_variant& v )
{
if( this == &v ) return *this;
this->~static_variant();
clean();
v.visit( impl::copy_construct<static_variant>(*this) );
return *this;
}
static_variant& operator=( static_variant&& v )
{
if( this == &v ) return *this;
this->~static_variant();
clean();
v.visit( impl::move_construct<static_variant>(*this) );
return *this;
}
@ -318,52 +364,40 @@ public:
return a.which() < b.which();
}
template<typename X>
template<typename X, typename = type_in_typelist<X>>
X& get() {
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
if(_tag == impl::position<X, Types...>::pos) {
void* tmp(storage);
return *reinterpret_cast<X*>(tmp);
return *reinterpret_cast<X*>(storage.data());
} else {
FC_THROW_EXCEPTION( fc::assert_exception, "static_variant does not contain a value of type ${t}", ("t",fc::get_typename<X>::name()) );
// std::string("static_variant does not contain value of type ") + typeid(X).name()
// );
}
}
template<typename X>
template<typename X, typename = type_in_typelist<X>>
const X& get() const {
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
if(_tag == impl::position<X, Types...>::pos) {
const void* tmp(storage);
return *reinterpret_cast<const X*>(tmp);
return *reinterpret_cast<const X*>(storage.data());
} else {
FC_THROW_EXCEPTION( fc::assert_exception, "static_variant does not contain a value of type ${t}", ("t",fc::get_typename<X>::name()) );
}
}
template<typename visitor>
typename visitor::result_type visit(visitor& v) {
return visit( _tag, v, (void*) storage );
return visit( _tag, v, (void*) storage.data() );
}
template<typename visitor>
typename visitor::result_type visit(const visitor& v) {
return visit( _tag, v, (void*) storage );
return visit( _tag, v, (void*) storage.data() );
}
template<typename visitor>
typename visitor::result_type visit(visitor& v)const {
return visit( _tag, v, (const void*) storage );
return visit( _tag, v, (const void*) storage.data() );
}
template<typename visitor>
typename visitor::result_type visit(const visitor& v)const {
return visit( _tag, v, (const void*) storage );
return visit( _tag, v, (const void*) storage.data() );
}
template<typename visitor>
@ -402,9 +436,8 @@ public:
void set_which( tag_type w ) {
FC_ASSERT( w >= 0 );
FC_ASSERT( w < count() );
this->~static_variant();
_tag = w;
impl::storage_ops<0, Types...>::con(_tag, storage);
clean();
init_from_tag(w);
}
tag_type which() const {return _tag;}

31
src/static_variant.cpp Normal file
View file

@ -0,0 +1,31 @@
#include <fc/static_variant.hpp>
namespace fc { namespace impl {
dynamic_storage::dynamic_storage() : storage(nullptr) {};
dynamic_storage::~dynamic_storage()
{
release();
}
void* dynamic_storage::data() const
{
FC_ASSERT( storage != nullptr );
return (void*)storage;
}
void dynamic_storage::alloc( size_t size )
{
release();
storage = new char[size];
}
void dynamic_storage::release()
{
delete [] storage;
storage = nullptr;
}
}}

View file

@ -46,6 +46,55 @@ FC_REFLECT( fc::test::item, (level)(w) );
BOOST_AUTO_TEST_SUITE(fc_variant_and_log)
BOOST_AUTO_TEST_CASE( types_edge_cases_test )
{
using namespace fc::test;
class sv : public fc::static_variant<>
{
public:
BOOST_ATTRIBUTE_UNUSED typedef fc::static_variant<>::tag_type tag_type;
};
BOOST_TEST_MESSAGE( "========== Test empty static_variant ==========" );
BOOST_CHECK_THROW( fc::static_variant<>(), fc::assert_exception );
BOOST_TEST_MESSAGE( "========== Test static_variant with tag_type ==========" );
sv::tag_type init_value = 2;
fc::static_variant< sv::tag_type, std::string, fc::variant > variant_with_tagtype(init_value);
BOOST_CHECK_EQUAL( variant_with_tagtype.count(), 3 );
BOOST_CHECK_EQUAL( variant_with_tagtype.which(), 0 );
sv::tag_type current_value = variant_with_tagtype.get<sv::tag_type>();
BOOST_CHECK_EQUAL( current_value, init_value );
BOOST_CHECK( variant_with_tagtype == init_value );
for (sv::tag_type i = variant_with_tagtype.count(); i-->0;)
{
variant_with_tagtype.set_which(i);
BOOST_CHECK_EQUAL(variant_with_tagtype.which(), i);
}
BOOST_TEST_MESSAGE( "========== Test static_variant with static_variant ==========" );
using sv_double = fc::static_variant<double>;
using sv_float = fc::static_variant<float>;
fc::static_variant< sv_float, std::string, sv_double > variant;
sv_float variant_float = 1.5f;
variant = variant_float;
BOOST_CHECK_EQUAL( variant.which(), 0 );
BOOST_CHECK_EQUAL( variant.get<sv_float>().get<float>(), 1.5f );
sv_double variant_double = 1.0;
variant = variant_double;
BOOST_CHECK_EQUAL( variant.which() , 2);
BOOST_CHECK_EQUAL( variant.get<sv_double>().get<double>(), 1.0 );
}
BOOST_AUTO_TEST_CASE( nested_objects_test )
{ try {