diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 51e1d4a198..ef6f266dfd 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -1793,11 +1793,8 @@ struct controller_impl { db.modify( pso, [&]( auto& ps ) { ps.preactivated_protocol_features.clear(); - ps.activated_protocol_features.reserve( ps.activated_protocol_features.size() - + new_protocol_feature_activations.size() ); - for( const auto& feature_digest : new_protocol_feature_activations ) { - ps.activated_protocol_features.emplace_back( feature_digest, pbhs.block_num ); - } + for (const auto& digest : new_protocol_feature_activations) + ps.activated_protocol_features.emplace_back(digest, pbhs.block_num); }); } @@ -2902,7 +2899,7 @@ void controller::preactivate_feature( const digest_type& feature_digest, bool is } my->db.modify( pso, [&]( auto& ps ) { - ps.preactivated_protocol_features.push_back( feature_digest ); + ps.preactivated_protocol_features.emplace_back(feature_digest); } ); } @@ -3284,7 +3281,7 @@ int64_t controller::set_proposed_producers( vector producers my->db.modify( gpo, [&]( auto& gp ) { gp.proposed_schedule_block_num = cur_block_num; - gp.proposed_schedule = sch.to_shared(gp.proposed_schedule.producers.get_allocator()); + gp.proposed_schedule = sch; }); return version; } diff --git a/libraries/chain/include/eosio/chain/authority.hpp b/libraries/chain/include/eosio/chain/authority.hpp index a168aaa105..11ae30feb4 100644 --- a/libraries/chain/include/eosio/chain/authority.hpp +++ b/libraries/chain/include/eosio/chain/authority.hpp @@ -116,20 +116,19 @@ struct shared_key_weight { return key_weight{key.to_public_key(), weight}; } - static shared_key_weight convert(chainbase::allocator allocator, const key_weight& k) { - return std::visit(overloaded { - [&](const auto& k1r1) { - return shared_key_weight(k1r1, k.weight); + shared_key_weight(const key_weight& k) : key(fc::ecc::public_key_shim()), weight(k.weight) { + std::visit(overloaded { + [&](const T& k1r1) { + key.pubkey.emplace(k1r1); }, [&](const fc::crypto::webauthn::public_key& wa) { size_t psz = fc::raw::pack_size(wa); - shared_string wa_ss(std::move(allocator)); - wa_ss.resize_and_fill( psz, [&wa]( char* data, std::size_t sz ) { - fc::datastream ds(data, sz); - fc::raw::pack(ds, wa); - }); - - return shared_key_weight(std::move(wa_ss), k.weight); + // create a shared_string in the pubkey that we will write (using pack) directly into. + key.pubkey.emplace(psz, boost::container::default_init_t()); + auto& s = std::get(key.pubkey); + assert(s.mutable_data() && s.size() == psz); + fc::datastream ds(s.mutable_data(), psz); + fc::raw::pack(ds, wa); } }, k.key._storage); } @@ -221,18 +220,37 @@ struct authority { struct shared_authority { - explicit shared_authority( chainbase::allocator alloc ) - :keys(alloc),accounts(alloc),waits(alloc){} - - shared_authority& operator=(const authority& a) { - threshold = a.threshold; - keys.clear(); - keys.reserve(a.keys.size()); - for(const key_weight& k : a.keys) { - keys.emplace_back(shared_key_weight::convert(keys.get_allocator(), k)); - } - accounts = decltype(accounts)(a.accounts.begin(), a.accounts.end(), accounts.get_allocator()); - waits = decltype(waits)(a.waits.begin(), a.waits.end(), waits.get_allocator()); + explicit shared_authority() = default; + + shared_authority(const authority& auth) : + threshold(auth.threshold), + keys(auth.keys), + accounts(auth.accounts), + waits(auth.waits) + { + } + + shared_authority(authority&& auth) : + threshold(auth.threshold), + keys(std::move(auth.keys)), + accounts(std::move(auth.accounts)), + waits(std::move(auth.waits)) + { + } + + shared_authority& operator=(const authority& auth) { + threshold = auth.threshold; + keys = auth.keys; + accounts = auth.accounts; + waits = auth.waits; + return *this; + } + + shared_authority& operator=(authority&& auth) { + threshold = auth.threshold; + keys = std::move(auth.keys); + accounts = std::move(auth.accounts); + waits = std::move(auth.waits); return *this; } diff --git a/libraries/chain/include/eosio/chain/database_utils.hpp b/libraries/chain/include/eosio/chain/database_utils.hpp index a3d6948080..50766601c2 100644 --- a/libraries/chain/include/eosio/chain/database_utils.hpp +++ b/libraries/chain/include/eosio/chain/database_utils.hpp @@ -4,7 +4,7 @@ #include #include -namespace eosio { namespace chain { +namespace eosio::chain { template class index_set; @@ -79,19 +79,7 @@ namespace eosio { namespace chain { index_set::walk_indices(function); } }; - - template - DataStream& operator << ( DataStream& ds, const shared_blob& b ) { - fc::raw::pack(ds, static_cast(b)); - return ds; - } - - template - DataStream& operator >> ( DataStream& ds, shared_blob& b ) { - fc::raw::unpack(ds, static_cast(b)); - return ds; - } -} } +} namespace fc { @@ -172,7 +160,7 @@ namespace fc { void from_variant( const variant& v, eosio::chain::shared_string& s ) { std::string _s; from_variant(v, _s); - s = eosio::chain::shared_string(_s.begin(), _s.end(), s.get_allocator()); + s = _s; } inline @@ -183,7 +171,7 @@ namespace fc { inline void from_variant( const variant& v, eosio::chain::shared_blob& b ) { std::vector b64 = base64_decode(v.as_string()); - b = eosio::chain::shared_blob(b64.begin(), b64.end(), b.get_allocator()); + b = std::string_view(b64.data(), b64.size()); } template @@ -195,7 +183,7 @@ namespace fc { void from_variant( const variant& v, eosio::chain::shared_vector& sv ) { std::vector _v; from_variant(v, _v); - sv = eosio::chain::shared_vector(_v.begin(), _v.end(), sv.get_allocator()); + sv = v; } } @@ -212,6 +200,65 @@ namespace chainbase { fc::raw::unpack(ds, oid._id); return ds; } + + // chainbase::shared_cow_string + // ---------------------------- + template + inline Stream& operator<<(Stream& s, const chainbase::shared_cow_string& v) { + FC_ASSERT(v.size() <= MAX_NUM_ARRAY_ELEMENTS); + fc::raw::pack(s, fc::unsigned_int((uint32_t)v.size())); + if( v.size() ) + s.write((const char*)v.data(), v.size()); + return s; + } + + template + inline Stream& operator>>(Stream& s, chainbase::shared_cow_string& v) { + fc::unsigned_int sz; + fc::raw::unpack(s, sz); + FC_ASSERT(sz.value <= MAX_SIZE_OF_BYTE_ARRAYS); + if (sz) { + v.resize_and_fill(sz, [&](char* buf, std::size_t sz) { + s.read(buf, sz); + }); + } + return s; + } + + // chainbase::shared_cow_vector + // ---------------------------- + template + inline Stream& operator<<(Stream& s, const chainbase::shared_cow_vector& v) { + FC_ASSERT(v.size() <= MAX_NUM_ARRAY_ELEMENTS); + fc::raw::pack( s, fc::unsigned_int((uint32_t)v.size())); + for (const auto& el : v) + fc::raw::pack(s, el); + return s; + } + + template + inline Stream& operator>>(Stream& s, chainbase::shared_cow_vector& v) { + fc::unsigned_int size; + fc::raw::unpack( s, size ); + FC_ASSERT(size.value <= MAX_NUM_ARRAY_ELEMENTS); + FC_ASSERT(v.size() == 0); + v.clear_and_construct(size.value, 0, [&](auto* dest, std::size_t i) { + new (dest) T(); // unpack expects a constructed variable + fc::raw::unpack(s, *dest); + }); + return s; + } + + // chainbase::shared_cow_vector + // ---------------------------------- + template + inline Stream& operator<<(Stream& s, const chainbase::shared_cow_vector& v) { + FC_ASSERT(v.size() <= MAX_NUM_ARRAY_ELEMENTS); + fc::raw::pack( s, fc::unsigned_int((uint32_t)v.size())); + if( v.size() ) + s.write((const char*)v.data(), v.size()); + return s; + } } // overloads for softfloat packing diff --git a/libraries/chain/include/eosio/chain/global_property_object.hpp b/libraries/chain/include/eosio/chain/global_property_object.hpp index 7b7497e34e..24180fad6a 100644 --- a/libraries/chain/include/eosio/chain/global_property_object.hpp +++ b/libraries/chain/include/eosio/chain/global_property_object.hpp @@ -75,7 +75,7 @@ namespace eosio { namespace chain { void initalize_from( const legacy::snapshot_global_property_object_v2& legacy, const chain_id_type& chain_id_val, const kv_database_config& kv_config_val, const wasm_config& wasm_config_val ) { proposed_schedule_block_num = legacy.proposed_schedule_block_num; - proposed_schedule = producer_authority_schedule(legacy.proposed_schedule).to_shared(proposed_schedule.producers.get_allocator()); + proposed_schedule = producer_authority_schedule(legacy.proposed_schedule); configuration = legacy.configuration; chain_id = chain_id_val; kv_configuration = kv_config_val; @@ -84,7 +84,7 @@ namespace eosio { namespace chain { void initalize_from( const legacy::snapshot_global_property_object_v3& legacy, const kv_database_config& kv_config_val, const wasm_config& wasm_config_val ) { proposed_schedule_block_num = legacy.proposed_schedule_block_num; - proposed_schedule = legacy.proposed_schedule.to_shared(proposed_schedule.producers.get_allocator()); + proposed_schedule = legacy.proposed_schedule; configuration = legacy.configuration; chain_id = legacy.chain_id; kv_configuration = kv_config_val; @@ -93,7 +93,7 @@ namespace eosio { namespace chain { void initalize_from( const legacy::snapshot_global_property_object_v4& legacy ) { proposed_schedule_block_num = legacy.proposed_schedule_block_num; - proposed_schedule = legacy.proposed_schedule.to_shared(proposed_schedule.producers.get_allocator()); + proposed_schedule = legacy.proposed_schedule; configuration = legacy.configuration; chain_id = legacy.chain_id; kv_configuration = legacy.kv_configuration; @@ -132,7 +132,7 @@ namespace eosio { namespace chain { static void from_snapshot_row( snapshot_global_property_object&& row, global_property_object& value, chainbase::database& ) { value.proposed_schedule_block_num = row.proposed_schedule_block_num; - value.proposed_schedule = row.proposed_schedule.to_shared(value.proposed_schedule.producers.get_allocator()); + value.proposed_schedule = row.proposed_schedule; value.configuration = row.configuration; value.chain_id = row.chain_id; value.kv_configuration = row.kv_configuration; diff --git a/libraries/chain/include/eosio/chain/permission_object.hpp b/libraries/chain/include/eosio/chain/permission_object.hpp index d323a1ef89..5547dd2860 100644 --- a/libraries/chain/include/eosio/chain/permission_object.hpp +++ b/libraries/chain/include/eosio/chain/permission_object.hpp @@ -23,7 +23,7 @@ namespace eosio { namespace chain { class permission_object : public chainbase::object { - OBJECT_CTOR(permission_object, (auth) ) + OBJECT_CTOR(permission_object, (auth)) id_type id; permission_usage_object::id_type usage_id; diff --git a/libraries/chain/include/eosio/chain/producer_schedule.hpp b/libraries/chain/include/eosio/chain/producer_schedule.hpp index 6a12e85791..af4f513bc8 100644 --- a/libraries/chain/include/eosio/chain/producer_schedule.hpp +++ b/libraries/chain/include/eosio/chain/producer_schedule.hpp @@ -46,15 +46,16 @@ namespace eosio { namespace chain { }; } + struct block_signing_authority_v0; + struct shared_block_signing_authority_v0 { - shared_block_signing_authority_v0() = delete; + shared_block_signing_authority_v0() = default; + shared_block_signing_authority_v0( const block_signing_authority_v0& ); shared_block_signing_authority_v0( const shared_block_signing_authority_v0& ) = default; shared_block_signing_authority_v0( shared_block_signing_authority_v0&& ) = default; shared_block_signing_authority_v0& operator= ( shared_block_signing_authority_v0 && ) = default; shared_block_signing_authority_v0& operator= ( const shared_block_signing_authority_v0 & ) = default; - - explicit shared_block_signing_authority_v0( chainbase::allocator alloc ) - :keys(alloc){} + shared_block_signing_authority_v0& operator= ( const block_signing_authority_v0 & ); uint32_t threshold = 0; shared_vector keys; @@ -62,8 +63,13 @@ namespace eosio { namespace chain { using shared_block_signing_authority = std::variant; + struct producer_authority; + struct shared_producer_authority { - shared_producer_authority() = delete; + shared_producer_authority() = default; + explicit shared_producer_authority(const producer_authority& ); + shared_producer_authority& operator=(const producer_authority& ); + shared_producer_authority( const shared_producer_authority& ) = default; shared_producer_authority( shared_producer_authority&& ) = default; shared_producer_authority& operator= ( shared_producer_authority && ) = default; @@ -78,11 +84,13 @@ namespace eosio { namespace chain { shared_block_signing_authority authority; }; + struct producer_authority_schedule; + struct shared_producer_authority_schedule { - shared_producer_authority_schedule() = delete; + shared_producer_authority_schedule() = default; - explicit shared_producer_authority_schedule( chainbase::allocator alloc ) - :producers(alloc){} + shared_producer_authority_schedule( const producer_authority_schedule& ); + shared_producer_authority_schedule& operator=(const producer_authority_schedule& ); shared_producer_authority_schedule( const shared_producer_authority_schedule& ) = default; shared_producer_authority_schedule( shared_producer_authority_schedule&& ) = default; @@ -127,18 +135,6 @@ namespace eosio { namespace chain { return {total_weight >= threshold, num_relevant_keys}; } - auto to_shared(chainbase::allocator alloc) const { - shared_block_signing_authority_v0 result(alloc); - result.threshold = threshold; - result.keys.clear(); - result.keys.reserve(keys.size()); - for (const auto& k: keys) { - result.keys.emplace_back(shared_key_weight::convert(alloc, k)); - } - - return result; - } - static auto from_shared(const shared_block_signing_authority_v0& src) { block_signing_authority_v0 result; result.threshold = src.threshold; @@ -186,14 +182,6 @@ namespace eosio { namespace chain { return keys_satisfy_and_relevant(presented_keys, authority); } - auto to_shared(chainbase::allocator alloc) const { - auto shared_auth = std::visit([&alloc](const auto& a) { - return a.to_shared(alloc); - }, authority); - - return shared_producer_authority(producer_name, std::move(shared_auth)); - } - static auto from_shared( const shared_producer_authority& src ) { producer_authority result; result.producer_name = src.producer_name; @@ -247,17 +235,6 @@ namespace eosio { namespace chain { ,producers(producers) {} - auto to_shared(chainbase::allocator alloc) const { - auto result = shared_producer_authority_schedule(alloc); - result.version = version; - result.producers.clear(); - result.producers.reserve( producers.size() ); - for( const auto& p : producers ) { - result.producers.emplace_back(p.to_shared(alloc)); - } - return result; - } - static auto from_shared( const shared_producer_authority_schedule& src ) { producer_authority_schedule result; result.version = src.version; diff --git a/libraries/chain/include/eosio/chain/protocol_state_object.hpp b/libraries/chain/include/eosio/chain/protocol_state_object.hpp index dc0eabd1f1..c2ffae1b76 100644 --- a/libraries/chain/include/eosio/chain/protocol_state_object.hpp +++ b/libraries/chain/include/eosio/chain/protocol_state_object.hpp @@ -16,9 +16,14 @@ namespace eosio { namespace chain { */ class protocol_state_object : public chainbase::object { - OBJECT_CTOR(protocol_state_object, (activated_protocol_features)(preactivated_protocol_features)(whitelisted_intrinsics)) - public: + template + protocol_state_object(Constructor&& c, chainbase::constructor_tag) : + id(0), + whitelisted_intrinsics(*activated_protocol_features.get_allocator(this)) { + c(*this); + } + struct activated_protocol_feature { digest_type feature_digest; uint32_t activation_block_num = 0; diff --git a/libraries/chain/include/eosio/chain/types.hpp b/libraries/chain/include/eosio/chain/types.hpp index 99466395d7..102b9f0dd6 100644 --- a/libraries/chain/include/eosio/chain/types.hpp +++ b/libraries/chain/include/eosio/chain/types.hpp @@ -25,17 +25,15 @@ #include #define OBJECT_CTOR1(NAME) \ - NAME() = delete; \ public: \ - template \ - NAME(Constructor&& c, chainbase::allocator) \ + template \ + NAME(Constructor&& c, chainbase::constructor_tag) \ { c(*this); } -#define OBJECT_CTOR2_MACRO(x, y, field) ,field(a) +#define OBJECT_CTOR2_MACRO(x, y, field) ,field() #define OBJECT_CTOR2(NAME, FIELDS) \ - NAME() = delete; \ public: \ - template \ - NAME(Constructor&& c, chainbase::allocator a) \ + template \ + NAME(Constructor&& c, chainbase::constructor_tag) \ : id(0) BOOST_PP_SEQ_FOR_EACH(OBJECT_CTOR2_MACRO, _, FIELDS) \ { c(*this); } #define OBJECT_CTOR(...) BOOST_PP_OVERLOAD(OBJECT_CTOR, __VA_ARGS__)(__VA_ARGS__) @@ -86,10 +84,10 @@ namespace eosio::chain { using chainbase::allocator; using shared_string = chainbase::shared_string; + template - using shared_vector = boost::interprocess::vector>; - template - using shared_set = boost::interprocess::set, allocator>; + using shared_vector = chainbase::shared_vector; + template using shared_flat_multimap = boost::interprocess::flat_multimap< K, V, std::less, allocator< std::pair > >; @@ -99,25 +97,23 @@ namespace eosio::chain { * serialization and to/from variant */ class shared_blob : public shared_string { - public: - shared_blob() = delete; - shared_blob(shared_blob&&) = default; - - shared_blob(const shared_blob& s) = default; - + public: + shared_blob() = default; - shared_blob& operator=(const shared_blob& s) = default; + shared_blob(shared_blob&&) = default; + shared_blob(const shared_blob& s) = default; - shared_blob& operator=(shared_blob&& ) = default; + explicit shared_blob(std::string_view s) : shared_string(s) {} - template - shared_blob(InputIterator f, InputIterator l, const allocator_type& a) - :shared_string(f,l,a) - {} + template + shared_blob(InputIterator f, InputIterator l) : shared_string(f, l) {} - shared_blob(const allocator_type& a) - :shared_string(a) - {} + shared_blob& operator=(const shared_blob& s) = default; + shared_blob& operator=(shared_blob&& ) = default; + shared_blob& operator=(std::string_view sv) { + static_cast(*this) = sv; + return *this; + } }; using action_name = name; @@ -410,22 +406,4 @@ namespace eosio::chain { } // eosio::chain -namespace chainbase { - // chainbase::shared_cow_string - template inline DataStream& operator<<( DataStream& s, const chainbase::shared_cow_string& v ) { - FC_ASSERT( v.size() <= MAX_SIZE_OF_BYTE_ARRAYS ); - fc::raw::pack( s, fc::unsigned_int((uint32_t)v.size())); - if( v.size() ) s.write( v.data(), v.size() ); - return s; - } - - template inline DataStream& operator>>( DataStream& s, chainbase::shared_cow_string& v ) { - fc::unsigned_int size; fc::raw::unpack( s, size ); - FC_ASSERT( size.value <= MAX_SIZE_OF_BYTE_ARRAYS ); - FC_ASSERT( v.size() == 0 ); - v.resize_and_fill(size.value, [&s](char* buf, std::size_t sz) { s.read(buf, sz); }); - return s; - } -} - FC_REFLECT_EMPTY( eosio::chain::void_t ) diff --git a/libraries/chain/producer_schedule.cpp b/libraries/chain/producer_schedule.cpp index b4c13338d5..97619b588f 100644 --- a/libraries/chain/producer_schedule.cpp +++ b/libraries/chain/producer_schedule.cpp @@ -1,6 +1,6 @@ #include -namespace eosio { namespace chain { +namespace eosio::chain { fc::variant producer_authority::get_abi_variant() const { auto authority_variant = std::visit([](const auto& a){ @@ -20,4 +20,40 @@ fc::variant producer_authority::get_abi_variant() const { ("authority", std::move(authority_variant)); } -} } /// eosio::chain +shared_producer_authority::shared_producer_authority(const producer_authority& pa) : + producer_name(pa.producer_name), + authority(std::visit([](const T& a) { return T(a);}, pa.authority)) +{ +} + +shared_producer_authority& shared_producer_authority::operator=(const producer_authority& pa) { + producer_name = pa.producer_name; + authority = std::visit([](const T& a) { return T(a);}, pa.authority); + return *this; +} + +shared_block_signing_authority_v0::shared_block_signing_authority_v0(const block_signing_authority_v0& bsa) : + threshold(bsa.threshold), + keys(bsa.keys) +{ +} + +shared_block_signing_authority_v0& shared_block_signing_authority_v0::operator= (const block_signing_authority_v0 & bsa) { + threshold = bsa.threshold; + keys = bsa.keys; + return *this; +} + +shared_producer_authority_schedule::shared_producer_authority_schedule(const producer_authority_schedule& pas) : + version(pas.version), + producers(pas.producers) +{ +} + +shared_producer_authority_schedule& shared_producer_authority_schedule::operator=(const producer_authority_schedule& pas) { + version = pas.version; + producers = pas.producers; + return *this; +} + +} /// eosio::chain diff --git a/libraries/chain/protocol_state_object.cpp b/libraries/chain/protocol_state_object.cpp index 142df3b131..028b99b2b2 100644 --- a/libraries/chain/protocol_state_object.cpp +++ b/libraries/chain/protocol_state_object.cpp @@ -32,17 +32,9 @@ namespace eosio { namespace chain { protocol_state_object& value, chainbase::database& db ) { - value.activated_protocol_features.clear(); - value.activated_protocol_features.reserve( row.activated_protocol_features.size() ); - for( const auto& v : row.activated_protocol_features ) { - value.activated_protocol_features.emplace_back( v ); - } - - value.preactivated_protocol_features.clear(); - value.preactivated_protocol_features.reserve( row.preactivated_protocol_features.size() ); - for( const auto& v : row.preactivated_protocol_features ) { - value.preactivated_protocol_features.emplace_back( v ); - } + value.activated_protocol_features = row.activated_protocol_features; + + value.preactivated_protocol_features = row.preactivated_protocol_features; reset_intrinsic_whitelist( value.whitelisted_intrinsics, row.whitelisted_intrinsics ); diff --git a/libraries/chain/whitelisted_intrinsics.cpp b/libraries/chain/whitelisted_intrinsics.cpp index 021e93b19d..835f6f4d03 100644 --- a/libraries/chain/whitelisted_intrinsics.cpp +++ b/libraries/chain/whitelisted_intrinsics.cpp @@ -59,8 +59,7 @@ namespace eosio { namespace chain { whitelisted_intrinsics.emplace( std::piecewise_construct, std::forward_as_tuple( h ), - std::forward_as_tuple( name.data(), name.size(), - whitelisted_intrinsics.get_allocator() ) + std::forward_as_tuple( name.data(), name.size() ) ); } @@ -85,8 +84,7 @@ namespace eosio { namespace chain { uint64_t h = static_cast( std::hash{}( name ) ); whitelisted_intrinsics.emplace( std::piecewise_construct, std::forward_as_tuple( h ), - std::forward_as_tuple( name.data(), name.size(), - whitelisted_intrinsics.get_allocator() ) + std::forward_as_tuple( name.data(), name.size() ) ); } } diff --git a/libraries/chainbase b/libraries/chainbase index d3dba51a00..85d33aa1f1 160000 --- a/libraries/chainbase +++ b/libraries/chainbase @@ -1 +1 @@ -Subproject commit d3dba51a0026f81643de40822a3fe5f01c7434a8 +Subproject commit 85d33aa1f193f384ec3aa852bbd84ed420f71f53 diff --git a/libraries/libfc/include/fc/io/raw.hpp b/libraries/libfc/include/fc/io/raw.hpp index dd570fe1fa..b00c9da1f4 100644 --- a/libraries/libfc/include/fc/io/raw.hpp +++ b/libraries/libfc/include/fc/io/raw.hpp @@ -17,17 +17,11 @@ #include #include -#include -#include -#include #include namespace fc { namespace raw { - namespace bip = boost::interprocess; - using shared_string = bip::basic_string< char, std::char_traits< char >, bip::allocator >; - template using UInt = boost::multiprecision::number< boost::multiprecision::cpp_int_backend >; @@ -309,22 +303,6 @@ namespace fc { v = std::string(tmp.data(),tmp.data()+tmp.size()); else v = std::string(); } - - // bip::basic_string - template inline void pack( Stream& s, const shared_string& v ) { - FC_ASSERT( v.size() <= MAX_SIZE_OF_BYTE_ARRAYS ); - fc::raw::pack( s, unsigned_int((uint32_t)v.size())); - if( v.size() ) s.write( v.c_str(), v.size() ); - } - - template inline void unpack( Stream& s, shared_string& v ) { - std::vector tmp; fc::raw::unpack(s,tmp); - FC_ASSERT(v.size() == 0); - if( tmp.size() ) { - v.append(tmp.begin(), tmp.end()); - } - } - // bool template inline void pack( Stream& s, const bool& v ) { fc::raw::pack( s, uint8_t(v) ); } template inline void unpack( Stream& s, bool& v ) diff --git a/unittests/test_chainbase_types.cpp b/unittests/test_chainbase_types.cpp new file mode 100644 index 0000000000..ff4760344f --- /dev/null +++ b/unittests/test_chainbase_types.cpp @@ -0,0 +1,87 @@ +#include +#include + +#include +#include +#include + +namespace bip = boost::interprocess; +namespace fs = std::filesystem; + +using namespace chainbase; + +template +using bip_vector = bip::vector; + +using shared_string_vector = shared_vector; + +struct book { + shared_string title; + shared_string_vector authors; + + bool operator==(const book&) const = default; +}; + +FC_REFLECT(book, (title)(authors)) + +namespace fc::raw { + template + inline void pack(Stream& s, const book& b) { + fc::raw::pack(s, b.title); + fc::raw::pack(s, b.authors); + } + + template + inline void unpack(Stream& s, book& b) { + fc::raw::unpack(s, b.title); + fc::raw::unpack(s, b.authors); + } +} + +template +void check_pack_unpack(V &v, V &v2) { + v.emplace_back(shared_string("Moby Dick"), shared_string_vector{ "Herman Melville" }); + v.emplace_back(shared_string("All the President's Men"), shared_string_vector{ "Carl Bernstein", "Bob Woodward" }); + + BOOST_REQUIRE(v[1].title == "All the President's Men"); + BOOST_REQUIRE(v[1].authors[1] == "Bob Woodward"); + + // try pack/unpack + constexpr size_t buffsz = 4096; + char buf[buffsz]; + fc::datastream ds(buf, buffsz); + + fc::raw::pack(ds, v); + ds.seekp(0); + fc::raw::unpack(ds, v2); + BOOST_REQUIRE(v2[1].title == "All the President's Men"); + BOOST_REQUIRE(v2[1].authors[1] == "Bob Woodward"); + BOOST_REQUIRE(v == v2); +} + +BOOST_AUTO_TEST_CASE(chainbase_type_heap_alloc) { + std::vector v, v2; + check_pack_unpack(v, v2); + + // check that objects inside the vectors are allocated within theheap + BOOST_REQUIRE(!v[1].title.get_allocator()); + BOOST_REQUIRE(!v2[1].authors[0].get_allocator()); +} + +BOOST_AUTO_TEST_CASE(chainbase_type_segment_alloc) { + fc::temp_directory temp_dir; + fs::path temp = temp_dir.path() / "pinnable_mapped_file_101"; + + pinnable_mapped_file pmf(temp, true, 1024 * 1024, false, pinnable_mapped_file::map_mode::mapped); + chainbase::allocator alloc(pmf.get_segment_manager()); + bip_vector> v(alloc); + bip_vector> v2(alloc); + + check_pack_unpack(v, v2); + auto a = v[1].title.get_allocator(); + auto a2 = v2[1].authors[0].get_allocator(); + + // check that objects inside the vectors are allocated within the pinnable_mapped_file segment + BOOST_REQUIRE(a && (chainbase::allocator)(*a) == alloc); + BOOST_REQUIRE(a2 && (chainbase::allocator)(*a2) == alloc); +}