Skip to content

Commit

Permalink
Merge pull request #1917 from AntelopeIO/pack_fix
Browse files Browse the repository at this point in the history
Fix a couple perf issues in `fc::raw::pack` and add tuple support.
  • Loading branch information
greg7mdp authored Nov 17, 2023
2 parents 1abf709 + 9c6f10d commit c5ac2d6
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 2 deletions.
24 changes: 22 additions & 2 deletions libraries/libfc/include/fc/io/raw.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,15 @@ namespace fc {
template<typename Stream, typename T> void unpack( Stream& s, boost::multiprecision::number<T>& n );

template<typename Stream, typename Arg0, typename... Args>
inline void pack( Stream& s, const Arg0& a0, Args... args ) {
inline void pack( Stream& s, const Arg0& a0, const Args&... args ) {
pack( s, a0 );
pack( s, args... );
}
template<typename Stream, typename Arg0, typename... Args>
inline void unpack( Stream& s, Arg0& a0, Args&... args ) {
unpack( s, a0 );
unpack( s, args... );
}

template<typename Stream>
inline void pack( Stream& s, const fc::exception& e )
Expand Down Expand Up @@ -243,7 +248,12 @@ namespace fc {
FC_ASSERT( vi == tmp );
}

template<typename Stream> inline void pack( Stream& s, const char* v ) { fc::raw::pack( s, std::string(v) ); }
template<typename Stream> inline void pack( Stream& s, const char* v ) {
size_t sz = std::strlen(v);
FC_ASSERT( sz <= MAX_SIZE_OF_BYTE_ARRAYS );
fc::raw::pack( s, unsigned_int(sz));
if( sz ) s.write( v, sz );
}

template<typename Stream, typename T>
void pack( Stream& s, const safe<T>& v ) { fc::raw::pack( s, v.value ); }
Expand Down Expand Up @@ -442,6 +452,16 @@ namespace fc {
}
}

template<typename Stream, typename... Ts >
inline void pack( Stream& s, const std::tuple<Ts...>& tup ) {
auto l = [&s](const auto&... v) { fc::raw::pack( s, v... ); };
std::apply(l, tup);
}
template<typename Stream, typename... Ts >
inline void unpack( Stream& s, std::tuple<Ts...>& tup ) {
auto l = [&s](auto&... v) { fc::raw::unpack( s, v... ); };
std::apply(l, tup);
}

template<typename Stream, typename K, typename V>
inline void pack( Stream& s, const std::pair<K,V>& value ) {
Expand Down
51 changes: 51 additions & 0 deletions libraries/libfc/test/network/test_message_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,57 @@ BOOST_AUTO_TEST_CASE(message_buffer_datastream) {
}
}

BOOST_AUTO_TEST_CASE(message_buffer_datastream_tuple) {
using my_message_buffer_t = fc::message_buffer<1024>;
my_message_buffer_t mbuff;

char buf[1024];
fc::datastream<char*> ds( buf, 1024 );

using my_tuple = std::tuple<int, int, std::string>;
my_tuple t(13, 42, "hello");
fc::raw::pack( ds, t );

memcpy(mbuff.write_ptr(), buf, 1024);
mbuff.advance_write_ptr(1024);

for( int i = 0; i < 3; ++i ) {
auto ds2 = mbuff.create_peek_datastream();
my_tuple t2;
fc::raw::unpack( ds2, t2 );
BOOST_CHECK( t == t2 );
}

{
auto ds2 = mbuff.create_datastream();
my_tuple t2;
fc::raw::unpack( ds2, t2 );
BOOST_CHECK( t == t2 );
}
}

BOOST_AUTO_TEST_CASE(message_buffer_datastream_variadic_pack_unpack) {
using my_message_buffer_t = fc::message_buffer<1024>;
my_message_buffer_t mbuff;

char buf[1024];
fc::datastream<char*> ds( buf, 1024 );

using my_tuple = std::tuple<int, int, std::string>;
my_tuple t(13, 42, "hello");
fc::raw::pack( ds, std::get<0>(t), std::get<1>(t), std::get<2>(t) );

memcpy(mbuff.write_ptr(), buf, 1024);
mbuff.advance_write_ptr(1024);

for( int i = 0; i < 3; ++i ) {
auto ds2 = mbuff.create_peek_datastream();
my_tuple t2;
fc::raw::unpack( ds2, std::get<0>(t2), std::get<1>(t2), std::get<2>(t2) );
BOOST_CHECK( t == t2 );
}
}

// Make sure that the memory allocation is thread-safe.
// A previous version used boost::object_pool without synchronization.
BOOST_AUTO_TEST_CASE(test_message_buffer) {
Expand Down

0 comments on commit c5ac2d6

Please sign in to comment.