diff --git a/CMakeLists.txt b/CMakeLists.txt index f8fea3d..9e9b701 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,12 @@ CMAKE_MINIMUM_REQUIRED( VERSION 3.1 ) set( CMAKE_CXX_STANDARD 14 ) SET( CMAKE_CXX_STANDARD_REQUIRED ON ) -set( CMAKE_CXX_EXTENSIONS OFF ) + +if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" ) + set( CMAKE_CXX_EXTENSIONS ON ) # for __int128 support +else( GNU ) + set( CMAKE_CXX_EXTENSIONS OFF ) +endif( GNU ) MESSAGE(STATUS "Configuring project fc located in: ${CMAKE_CURRENT_SOURCE_DIR}") SET( CMAKE_AUTOMOC OFF ) @@ -194,8 +199,7 @@ set( CMAKE_FIND_LIBRARY_SUFFIXES ${ORIGINAL_LIB_SUFFIXES} ) option( UNITY_BUILD OFF ) set( fc_sources - src/uint128.cpp - src/real128.cpp + src/popcount.cpp src/variant.cpp src/exception.cpp src/variant_object.cpp @@ -211,7 +215,6 @@ set( fc_sources src/thread/non_preemptable_scope_check.cpp src/asio.cpp src/string.cpp - src/shared_ptr.cpp src/stacktrace.cpp src/time.cpp src/utf8.cpp @@ -226,7 +229,6 @@ set( fc_sources src/interprocess/signals.cpp src/interprocess/file_mapping.cpp src/rpc/cli.cpp - src/rpc/http_api.cpp src/rpc/state.cpp src/rpc/websocket_api.cpp src/log/log_message.cpp @@ -258,7 +260,6 @@ set( fc_sources src/network/tcp_socket.cpp src/network/udp_socket.cpp src/network/http/http_connection.cpp - src/network/http/http_server.cpp src/network/http/websocket.cpp src/network/ip.cpp src/network/rate_limiting.cpp @@ -379,7 +380,7 @@ target_include_directories(fc IF(NOT WIN32) set(LINK_USR_LOCAL_LIB -L/usr/local/lib) ENDIF() -target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} +target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${Boost_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${editline_libraries} secp256k1 ${CMAKE_REQUIRED_LIBRARIES} ) diff --git a/include/fc/array.hpp b/include/fc/array.hpp deleted file mode 100644 index 687b175..0000000 --- a/include/fc/array.hpp +++ /dev/null @@ -1,145 +0,0 @@ -#pragma once -#include -#include -#include - -namespace fc { - - /** - * Provides a fixed size array that is easier for templates to specialize - * against or overload than T[N]. - */ - template - class array { - public: - /** - * Checked indexing (when in debug build) that also simplifies dereferencing - * when you have an array*. - */ - ///@{ - T& at( size_t pos ) { assert( pos < N); return data[pos]; } - const T& at( size_t pos )const { assert( pos < N); return data[pos]; } - ///@} - - T& operator[]( size_t pos ) { assert( pos < N); return data[pos]; } - const T& operator[]( size_t pos )const { assert( pos < N); return data[pos]; } - - - const T* begin()const { return &data[0]; } - const T* end()const { return &data[N]; } - - T* begin() { return &data[0]; } - T* end() { return &data[N]; } - - size_t size()const { return N; } - - T data[N]; - }; - - /** provided for default 0 init */ - template - class array - { - public: - typedef unsigned char T; - array(){ memset( data, 0, sizeof(data) ); } - /** - * Checked indexing (when in debug build) that also simplifies dereferencing - * when you have an array*. - */ - ///@{ - T& at( size_t pos ) { assert( pos < N); return data[pos]; } - const T& at( size_t pos )const { assert( pos < N); return data[pos]; } - ///@} - - T* begin() { return &data[0]; } - const T* begin()const { return &data[0]; } - const T* end()const { return &data[N]; } - - size_t size()const { return N; } - - T data[N]; - }; - - /** provided for default 0 init */ - template - class array - { - public: - typedef char T; - array(){ memset( data, 0, sizeof(data) ); } - /** - * Checked indexing (when in debug build) that also simplifies dereferencing - * when you have an array*. - */ - ///@{ - T& at( size_t pos ) { assert( pos < N); return data[pos]; } - const T& at( size_t pos )const { assert( pos < N); return data[pos]; } - ///@} - - T* begin() { return &data[0]; } - const T* begin()const { return &data[0]; } - const T* end()const { return &data[N]; } - - size_t size()const { return N; } - - T data[N]; - }; - - template - bool operator == ( const array& a, const array& b ) - { return 0 == memcmp( a.data, b.data, N*sizeof(T) ); } - template - bool operator < ( const array& a, const array& b ) - { return memcmp( a.data, b.data, N*sizeof(T) ) < 0 ; } - - template - bool operator > ( const array& a, const array& b ) - { return memcmp( a.data, b.data, N*sizeof(T) ) > 0 ; } - - template - bool operator != ( const array& a, const array& b ) - { return 0 != memcmp( a.data, b.data, N*sizeof(T) ); } - - template - void to_variant( const array& bi, variant& v, uint32_t max_depth = 1 ) - { - to_variant( std::vector( (const char*)&bi, ((const char*)&bi) + sizeof(bi) ), v, 1 ); - } - template - void from_variant( const variant& v, array& bi, uint32_t max_depth = 1 ) - { - std::vector ve = v.as< std::vector >( 1 ); - if( ve.size() ) - { - memcpy(&bi, ve.data(), std::min(ve.size(),sizeof(bi)) ); - } - else - memset( &bi, char(0), sizeof(bi) ); - } - - - template struct get_typename< fc::array > - { - static const char* name() - { - static std::string _name = std::string("fc::array<")+std::string(fc::get_typename::name())+","+ fc::to_string(N) + ">"; - return _name.c_str(); - } - }; -} - -#include -#include -namespace std -{ - template - struct hash > - { - size_t operator()( const fc::array& e )const - { - return fc::city_hash_size_t( (char*)&e, sizeof(e) ); - } - }; -} - diff --git a/include/fc/asio.hpp b/include/fc/asio.hpp index 06ba2f8..4c330c4 100644 --- a/include/fc/asio.hpp +++ b/include/fc/asio.hpp @@ -122,7 +122,7 @@ namespace asio { template future read_some(AsyncReadStream& s, const MutableBufferSequence& buf) { - promise::ptr completion_promise(new promise("fc::asio::async_read_some")); + promise::ptr completion_promise = promise::create("fc::asio::async_read_some"); s.async_read_some(buf, detail::read_write_handler(completion_promise)); return completion_promise;//->wait(); } @@ -130,7 +130,7 @@ namespace asio { template future read_some(AsyncReadStream& s, char* buffer, size_t length, size_t offset = 0) { - promise::ptr completion_promise(new promise("fc::asio::async_read_some")); + promise::ptr completion_promise = promise::create("fc::asio::async_read_some"); s.async_read_some(boost::asio::buffer(buffer + offset, length), detail::read_write_handler(completion_promise)); return completion_promise;//->wait(); @@ -139,7 +139,7 @@ namespace asio { template future read_some(AsyncReadStream& s, const std::shared_ptr& buffer, size_t length, size_t offset) { - promise::ptr completion_promise(new promise("fc::asio::async_read_some")); + promise::ptr completion_promise = promise::create("fc::asio::async_read_some"); s.async_read_some(boost::asio::buffer(buffer.get() + offset, length), detail::read_write_handler_with_buffer(completion_promise, buffer)); return completion_promise;//->wait(); @@ -179,7 +179,7 @@ namespace asio { */ template size_t write( AsyncWriteStream& s, const ConstBufferSequence& buf ) { - promise::ptr p(new promise("fc::asio::write")); + promise::ptr p = promise::create("fc::asio::write"); boost::asio::async_write(s, buf, detail::read_write_handler(p)); return p->wait(); } @@ -191,7 +191,7 @@ namespace asio { */ template future write_some( AsyncWriteStream& s, const ConstBufferSequence& buf ) { - promise::ptr p(new promise("fc::asio::write_some")); + promise::ptr p = promise::create("fc::asio::write_some"); s.async_write_some( buf, detail::read_write_handler(p)); return p; //->wait(); } @@ -199,7 +199,7 @@ namespace asio { template future write_some( AsyncWriteStream& s, const char* buffer, size_t length, size_t offset = 0) { - promise::ptr p(new promise("fc::asio::write_some")); + promise::ptr p = promise::create("fc::asio::write_some"); s.async_write_some( boost::asio::buffer(buffer + offset, length), detail::read_write_handler(p)); return p; //->wait(); } @@ -207,7 +207,7 @@ namespace asio { template future write_some( AsyncWriteStream& s, const std::shared_ptr& buffer, size_t length, size_t offset ) { - promise::ptr p(new promise("fc::asio::write_some")); + promise::ptr p = promise::create("fc::asio::write_some"); s.async_write_some( boost::asio::buffer(buffer.get() + offset, length), detail::read_write_handler_with_buffer(p, buffer)); return p; //->wait(); } @@ -250,7 +250,7 @@ namespace asio { template void accept( AcceptorType& acc, SocketType& sock ) { //promise::ptr p( new promise("fc::asio::tcp::accept") ); - promise::ptr p( new promise("fc::asio::tcp::accept") ); + promise::ptr p = promise::create("fc::asio::tcp::accept"); acc.async_accept( sock, boost::bind( fc::asio::detail::error_handler, p, _1 ) ); p->wait(); //if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) ); @@ -262,7 +262,7 @@ namespace asio { */ template void connect( AsyncSocket& sock, const EndpointType& ep ) { - promise::ptr p(new promise("fc::asio::tcp::connect")); + promise::ptr p = promise::create("fc::asio::tcp::connect"); sock.async_connect( ep, boost::bind( fc::asio::detail::error_handler, p, _1 ) ); p->wait(); //if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) ); diff --git a/include/fc/bloom_filter.hpp b/include/fc/bloom_filter.hpp index a52f2da..940dfbd 100644 --- a/include/fc/bloom_filter.hpp +++ b/include/fc/bloom_filter.hpp @@ -31,7 +31,7 @@ namespace fc { -static const std::size_t bits_per_char = 0x08; // 8 bits in 1 char(unsigned) +static constexpr std::size_t bits_per_char = 0x08; // 8 bits in 1 char(unsigned) static const unsigned char bit_mask[bits_per_char] = { 0x01, //00000001 0x02, //00000010 diff --git a/include/fc/crypto/aes.hpp b/include/fc/crypto/aes.hpp index e9f26af..862c8f3 100644 --- a/include/fc/crypto/aes.hpp +++ b/include/fc/crypto/aes.hpp @@ -1,9 +1,10 @@ #pragma once -#include + #include #include -#include #include +#include + #include namespace fc { @@ -15,9 +16,8 @@ namespace fc { aes_encoder(); ~aes_encoder(); - void init( const fc::sha256& key, const fc::uint128& init_value ); + void init( const fc::sha256& key, const uint128_t& init_value ); uint32_t encode( const char* plaintxt, uint32_t len, char* ciphertxt ); - // uint32_t final_encode( char* ciphertxt ); private: struct impl; @@ -29,9 +29,8 @@ namespace fc { aes_decoder(); ~aes_decoder(); - void init( const fc::sha256& key, const fc::uint128& init_value ); + void init( const fc::sha256& key, const uint128_t& init_value ); uint32_t decode( const char* ciphertxt, uint32_t len, char* plaintext ); -// uint32_t final_decode( char* plaintext ); private: struct impl; diff --git a/include/fc/crypto/city.hpp b/include/fc/crypto/city.hpp index 7047ae8..323c4af 100644 --- a/include/fc/crypto/city.hpp +++ b/include/fc/crypto/city.hpp @@ -41,36 +41,25 @@ // doesn't hold for any hash functions in this file. #pragma once +#include + #include // for size_t. #include #include namespace fc { -template -class array; -class uint128; - // Hash function for a byte array. uint64_t city_hash64(const char *buf, size_t len); -uint32_t city_hash32(const char *buf, size_t len); - #if SIZE_MAX > UINT32_MAX inline size_t city_hash_size_t(const char *buf, size_t len) { return city_hash64(buf, len); } #else +uint32_t city_hash32(const char *buf, size_t len); inline size_t city_hash_size_t(const char *buf, size_t len) { return city_hash32(buf, len); } #endif // Hash function for a byte array. -uint128 city_hash128(const char *s, size_t len); - -// Hash function for a byte array. -uint64_t city_hash_crc_64(const char *buf, size_t len); - -// Hash function for a byte array. -uint128 city_hash_crc_128(const char *s, size_t len); -array city_hash_crc_256(const char *s, size_t len); - +uint128_t city_hash_crc_128(const char *s, size_t len); } // namespace fc diff --git a/include/fc/crypto/elliptic.hpp b/include/fc/crypto/elliptic.hpp index 7ca2ec6..3784299 100644 --- a/include/fc/crypto/elliptic.hpp +++ b/include/fc/crypto/elliptic.hpp @@ -4,9 +4,10 @@ #include #include #include -#include #include +#include + namespace fc { namespace ecc { @@ -16,15 +17,15 @@ namespace fc { class private_key_impl; } - typedef fc::sha256 blind_factor_type; - typedef fc::array commitment_type; - typedef fc::array public_key_data; - typedef fc::sha256 private_key_secret; - typedef fc::array public_key_point_data; ///< the full non-compressed version of the ECC point - typedef fc::array signature; - typedef fc::array compact_signature; - typedef std::vector range_proof_type; - typedef fc::array extended_key_data; + typedef fc::sha256 blind_factor_type; + typedef std::array commitment_type; + typedef std::array public_key_data; + typedef fc::sha256 private_key_secret; + typedef std::array public_key_point_data; ///< the full non-compressed version of the ECC point + typedef std::array signature; + typedef std::array compact_signature; + typedef std::vector range_proof_type; + typedef std::array extended_key_data; /** * @class public_key diff --git a/include/fc/crypto/ripemd160.hpp b/include/fc/crypto/ripemd160.hpp index 58d8b18..ac48d16 100644 --- a/include/fc/crypto/ripemd160.hpp +++ b/include/fc/crypto/ripemd160.hpp @@ -18,7 +18,7 @@ class ripemd160 explicit operator string()const; char* data()const; - size_t data_size()const { return 160/8; } + static constexpr size_t data_size() { return 160/8; } static ripemd160 hash( const fc::sha512& h ); static ripemd160 hash( const fc::sha256& h ); diff --git a/include/fc/crypto/sha1.hpp b/include/fc/crypto/sha1.hpp index 737eecf..0050146 100644 --- a/include/fc/crypto/sha1.hpp +++ b/include/fc/crypto/sha1.hpp @@ -17,7 +17,7 @@ class sha1 operator std::string()const; char* data()const; - size_t data_size()const { return 20; } + static constexpr size_t data_size() { return 20; } static sha1 hash( const char* d, uint32_t dlen ); static sha1 hash( const std::string& ); diff --git a/include/fc/crypto/sha224.hpp b/include/fc/crypto/sha224.hpp index 772e9f6..c35c98f 100644 --- a/include/fc/crypto/sha224.hpp +++ b/include/fc/crypto/sha224.hpp @@ -16,7 +16,7 @@ class sha224 operator string()const; char* data()const; - size_t data_size()const { return 224 / 8; } + static constexpr size_t data_size() { return 224 / 8; } static sha224 hash( const char* d, uint32_t dlen ); static sha224 hash( const string& ); diff --git a/include/fc/crypto/sha256.hpp b/include/fc/crypto/sha256.hpp index a382ad0..840d38f 100644 --- a/include/fc/crypto/sha256.hpp +++ b/include/fc/crypto/sha256.hpp @@ -18,7 +18,7 @@ class sha256 operator string()const; char* data()const; - size_t data_size()const { return 256 / 8; } + static constexpr size_t data_size() { return 256 / 8; } static sha256 hash( const char* d, uint32_t dlen ); static sha256 hash( const string& ); diff --git a/include/fc/crypto/sha512.hpp b/include/fc/crypto/sha512.hpp index 10c9ea0..521c93b 100644 --- a/include/fc/crypto/sha512.hpp +++ b/include/fc/crypto/sha512.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include namespace fc @@ -9,16 +10,16 @@ class sha512 { public: sha512(); - explicit sha512( const string& hex_str ); + explicit sha512( const std::string& hex_str ); - string str()const; - operator string()const; + std::string str()const; + operator std::string()const; char* data()const; - size_t data_size()const { return 512 / 8; } + static constexpr size_t data_size() { return 512 / 8; } static sha512 hash( const char* d, uint32_t dlen ); - static sha512 hash( const string& ); + static sha512 hash( const std::string& ); template static sha512 hash( const T& t ) diff --git a/include/fc/exception/exception.hpp b/include/fc/exception/exception.hpp index b9b6d8e..e61e92f 100644 --- a/include/fc/exception/exception.hpp +++ b/include/fc/exception/exception.hpp @@ -35,7 +35,8 @@ namespace fc aes_error_code = 18, overflow_code = 19, underflow_code = 20, - divide_by_zero_code = 21 + divide_by_zero_code = 21, + method_not_found_exception_code = 22 }; /** @@ -105,7 +106,7 @@ namespace fc * * @note does not return. */ - virtual NO_RETURN void dynamic_rethrow_exception()const; + [[noreturn]] virtual void dynamic_rethrow_exception()const; /** * This is equivalent to: @@ -154,7 +155,7 @@ namespace fc std::exception_ptr get_inner_exception()const; - virtual NO_RETURN void dynamic_rethrow_exception()const; + [[noreturn]] virtual void dynamic_rethrow_exception()const; virtual std::shared_ptr dynamic_copy_exception()const; private: std::exception_ptr _inner; @@ -165,10 +166,10 @@ namespace fc { #if defined(_MSC_VER) && (_MSC_VER < 1700) return std::make_shared( log_message(), - std::copy_exception(fc::forward(e)) ); + std::copy_exception(std::forward(e)) ); #else return std::make_shared( log_message(), - std::make_exception_ptr(fc::forward(e)) ); + std::make_exception_ptr(std::forward(e)) ); #endif } @@ -178,13 +179,13 @@ namespace fc public: struct base_exception_builder { - virtual NO_RETURN void rethrow( const exception& e )const = 0; + [[noreturn]] virtual void rethrow( const exception& e )const = 0; }; template struct exception_builder : public base_exception_builder { - virtual NO_RETURN void rethrow( const exception& e )const override + [[noreturn]] virtual void rethrow( const exception& e )const override { throw T( e ); } @@ -200,7 +201,7 @@ namespace fc _registered_exceptions[T::code_value] = &builder; } - void NO_RETURN rethrow( const exception& e )const; + [[noreturn]] void rethrow( const exception& e )const; static exception_factory& instance() { @@ -222,81 +223,98 @@ namespace fc }(); \ -#define FC_DECLARE_DERIVED_EXCEPTION( TYPE, BASE, CODE, WHAT ) \ +#define FC_DECLARE_DERIVED_EXCEPTION( TYPE, BASE, CODE ) \ class TYPE : public BASE \ { \ public: \ enum code_enum { \ code_value = CODE, \ }; \ - explicit TYPE( int64_t code, const std::string& name_value, const std::string& what_value ) \ - :BASE( code, name_value, what_value ){} \ - explicit TYPE( fc::log_message&& m, int64_t code, const std::string& name_value, const std::string& what_value ) \ - :BASE( std::move(m), code, name_value, what_value ){} \ - explicit TYPE( fc::log_messages&& m, int64_t code, const std::string& name_value, const std::string& what_value )\ - :BASE( std::move(m), code, name_value, what_value ){}\ - explicit TYPE( const fc::log_messages& m, int64_t code, const std::string& name_value, const std::string& what_value )\ - :BASE( m, code, name_value, what_value ){}\ - TYPE( const std::string& what_value, const fc::log_messages& m ) \ - :BASE( m, CODE, BOOST_PP_STRINGIZE(TYPE), what_value ){} \ - TYPE( fc::log_message&& m ) \ - :BASE( std::move(m), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ){}\ - TYPE( fc::log_messages msgs ) \ - :BASE( std::move( msgs ), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ) {} \ - TYPE( const TYPE& c ) \ - :BASE(c){} \ - TYPE( const BASE& c ) \ - :BASE(c){} \ - TYPE():BASE(CODE, BOOST_PP_STRINGIZE(TYPE), WHAT){}\ + explicit TYPE( int64_t code, const std::string& name_value, const std::string& what_value ); \ + explicit TYPE( fc::log_message&& m, int64_t code, const std::string& name_value, const std::string& what_value ); \ + explicit TYPE( fc::log_messages&& m, int64_t code, const std::string& name_value, const std::string& what_value );\ + explicit TYPE( const fc::log_messages& m, int64_t code, const std::string& name_value, const std::string& what_value );\ + explicit TYPE( const std::string& what_value, const fc::log_messages& m ); \ + explicit TYPE( fc::log_message&& m ); \ + explicit TYPE( fc::log_messages msgs ); \ + TYPE( TYPE&& c ) = default; \ + TYPE( const TYPE& c ); \ + TYPE( const BASE& c ); \ + explicit TYPE();\ \ - virtual std::shared_ptr dynamic_copy_exception()const\ - { return std::make_shared( *this ); } \ - virtual NO_RETURN void dynamic_rethrow_exception()const \ - { if( code() == CODE ) throw *this;\ - else fc::exception::dynamic_rethrow_exception(); \ - } \ + virtual std::shared_ptr dynamic_copy_exception()const;\ + [[noreturn]] virtual void dynamic_rethrow_exception()const; \ }; - #define FC_DECLARE_EXCEPTION( TYPE, CODE, WHAT ) \ - FC_DECLARE_DERIVED_EXCEPTION( TYPE, fc::exception, CODE, WHAT ) +#define FC_IMPLEMENT_DERIVED_EXCEPTION( TYPE, BASE, CODE, WHAT ) \ + TYPE::TYPE( int64_t code, const std::string& name_value, const std::string& what_value ) \ + : BASE( code, name_value, what_value ) {} \ + TYPE::TYPE( fc::log_message&& m, int64_t code, const std::string& name_value, const std::string& what_value ) \ + : BASE( std::move(m), code, name_value, what_value ) {} \ + TYPE::TYPE( fc::log_messages&& m, int64_t code, const std::string& name_value, const std::string& what_value ) \ + : BASE( std::move(m), code, name_value, what_value ) {} \ + TYPE::TYPE( const fc::log_messages& m, int64_t code, const std::string& name_value, const std::string& what_value ) \ + : BASE( m, code, name_value, what_value ) {} \ + TYPE::TYPE( const std::string& what_value, const fc::log_messages& m ) \ + : BASE( m, CODE, BOOST_PP_STRINGIZE(TYPE), what_value ) {} \ + TYPE::TYPE( fc::log_message&& m ) \ + : BASE( std::move(m), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ) {} \ + TYPE::TYPE( fc::log_messages msgs ) \ + : BASE( std::move( msgs ), CODE, BOOST_PP_STRINGIZE(TYPE), WHAT ) {} \ + TYPE::TYPE( const TYPE& c ) : BASE(c) {} \ + TYPE::TYPE( const BASE& c ) : BASE(c) {} \ + TYPE::TYPE() : BASE(CODE, BOOST_PP_STRINGIZE(TYPE), WHAT) {} \ + \ + std::shared_ptr TYPE::dynamic_copy_exception()const \ + { \ + return std::make_shared( *this ); \ + } \ + [[noreturn]] void TYPE::dynamic_rethrow_exception()const \ + { \ + if( code() == CODE ) throw *this;\ + else fc::exception::dynamic_rethrow_exception(); \ + } - FC_DECLARE_EXCEPTION( timeout_exception, timeout_exception_code, "Timeout" ); - FC_DECLARE_EXCEPTION( file_not_found_exception, file_not_found_exception_code, "File Not Found" ); +#define FC_DECLARE_EXCEPTION( TYPE, CODE ) \ + FC_DECLARE_DERIVED_EXCEPTION( TYPE, fc::exception, CODE ) + +#define FC_IMPLEMENT_EXCEPTION( TYPE, CODE, WHAT ) \ + FC_IMPLEMENT_DERIVED_EXCEPTION( TYPE, fc::exception, CODE, WHAT ) + + FC_DECLARE_EXCEPTION( timeout_exception, timeout_exception_code ); + FC_DECLARE_EXCEPTION( file_not_found_exception, file_not_found_exception_code ); /** - * @brief report's parse errors + * @brief reports parse errors */ - FC_DECLARE_EXCEPTION( parse_error_exception, parse_error_exception_code, "Parse Error" ); - FC_DECLARE_EXCEPTION( invalid_arg_exception, invalid_arg_exception_code, "Invalid Argument" ); + FC_DECLARE_EXCEPTION( parse_error_exception, parse_error_exception_code ); + FC_DECLARE_EXCEPTION( invalid_arg_exception, invalid_arg_exception_code ); /** * @brief reports when a key, guid, or other item is not found. */ - FC_DECLARE_EXCEPTION( key_not_found_exception, key_not_found_exception_code, "Key Not Found" ); - FC_DECLARE_EXCEPTION( bad_cast_exception, bad_cast_exception_code, "Bad Cast" ); - FC_DECLARE_EXCEPTION( out_of_range_exception, out_of_range_exception_code, "Out of Range" ); + FC_DECLARE_EXCEPTION( key_not_found_exception, key_not_found_exception_code ); + FC_DECLARE_EXCEPTION( bad_cast_exception, bad_cast_exception_code ); + FC_DECLARE_EXCEPTION( out_of_range_exception, out_of_range_exception_code ); + FC_DECLARE_EXCEPTION( method_not_found_exception, method_not_found_exception_code ); /** @brief if an operation is unsupported or not valid this may be thrown */ - FC_DECLARE_EXCEPTION( invalid_operation_exception, - invalid_operation_exception_code, - "Invalid Operation" ); + FC_DECLARE_EXCEPTION( invalid_operation_exception, invalid_operation_exception_code ); /** @brief if an host name can not be resolved this may be thrown */ - FC_DECLARE_EXCEPTION( unknown_host_exception, - unknown_host_exception_code, - "Unknown Host" ); + FC_DECLARE_EXCEPTION( unknown_host_exception, unknown_host_exception_code ); /** * @brief used to report a canceled Operation */ - FC_DECLARE_EXCEPTION( canceled_exception, canceled_exception_code, "Canceled" ); + FC_DECLARE_EXCEPTION( canceled_exception, canceled_exception_code ); /** * @brief used inplace of assert() to report violations of pre conditions. */ - FC_DECLARE_EXCEPTION( assert_exception, assert_exception_code, "Assert Exception" ); - FC_DECLARE_EXCEPTION( eof_exception, eof_exception_code, "End Of File" ); - FC_DECLARE_EXCEPTION( null_optional, null_optional_code, "null optional" ); - FC_DECLARE_EXCEPTION( aes_exception, aes_error_code, "AES error" ); - FC_DECLARE_EXCEPTION( overflow_exception, overflow_code, "Integer Overflow" ); - FC_DECLARE_EXCEPTION( underflow_exception, underflow_code, "Integer Underflow" ); - FC_DECLARE_EXCEPTION( divide_by_zero_exception, divide_by_zero_code, "Integer Divide By Zero" ); + FC_DECLARE_EXCEPTION( assert_exception, assert_exception_code ); + FC_DECLARE_EXCEPTION( eof_exception, eof_exception_code ); + FC_DECLARE_EXCEPTION( null_optional, null_optional_code ); + FC_DECLARE_EXCEPTION( aes_exception, aes_error_code ); + FC_DECLARE_EXCEPTION( overflow_exception, overflow_code ); + FC_DECLARE_EXCEPTION( underflow_exception, underflow_code ); + FC_DECLARE_EXCEPTION( divide_by_zero_exception, divide_by_zero_code ); std::string except_str(); diff --git a/include/fc/fwd_impl.hpp b/include/fc/fwd_impl.hpp index 53a4440..df2f0f8 100644 --- a/include/fc/fwd_impl.hpp +++ b/include/fc/fwd_impl.hpp @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include #include #include @@ -41,10 +41,10 @@ namespace fc { template - auto operator + ( const fwd& x, U&& u ) -> typename detail::add::type { return *x+fc::forward(u); } + auto operator + ( const fwd& x, U&& u ) -> typename detail::add::type { return *x+std::forward(u); } template - auto operator - ( const fwd& x, U&& u ) -> typename detail::sub::type { return *x-fc::forward(u); } + auto operator - ( const fwd& x, U&& u ) -> typename detail::sub::type { return *x-std::forward(u); } template auto operator << ( U& u, const fwd& f ) -> typename detail::insert_op::type { return u << *f; } @@ -63,20 +63,20 @@ namespace fc { template fwd::fwd( U&& u ) { check_size(); - new (this) T( fc::forward(u) ); + new (this) T( std::forward(u) ); } template template fwd::fwd( U&& u, V&& v ) { check_size(); - new (this) T( fc::forward(u), fc::forward(v) ); + new (this) T( std::forward(u), std::forward(v) ); } template template fwd::fwd( U&& u, V&& v, X&& x, Y&& y ) { check_size(); - new (this) T( fc::forward(u), fc::forward(v), fc::forward(x), fc::forward(y) ); + new (this) T( std::forward(u), std::forward(v), std::forward(x), std::forward(y) ); } @@ -121,7 +121,7 @@ namespace fc { template template T& fwd::operator = ( U&& u ) { - return **this = fc::forward(u); + return **this = std::forward(u); } template diff --git a/include/fc/io/datastream.hpp b/include/fc/io/datastream.hpp index 0bf36a1..87b432e 100644 --- a/include/fc/io/datastream.hpp +++ b/include/fc/io/datastream.hpp @@ -1,5 +1,4 @@ #pragma once -#include #include #include @@ -7,7 +6,7 @@ namespace fc { namespace detail { - NO_RETURN void throw_datastream_range_error( const char* file, size_t len, int64_t over ); + [[noreturn]] void throw_datastream_range_error( const char* file, size_t len, int64_t over ); } /** diff --git a/include/fc/io/fstream.hpp b/include/fc/io/fstream.hpp index 9a0c99d..7b5465e 100644 --- a/include/fc/io/fstream.hpp +++ b/include/fc/io/fstream.hpp @@ -1,8 +1,8 @@ #pragma once -#include #include #include #include +#include namespace fc { class path; @@ -21,7 +21,7 @@ namespace fc { private: class impl; - fc::shared_ptr my; + std::shared_ptr my; }; class ifstream : virtual public istream { @@ -44,7 +44,7 @@ namespace fc { bool eof()const; private: class impl; - fc::shared_ptr my; + std::shared_ptr my; }; /** diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 696f398..6b0371b 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -1,16 +1,14 @@ #pragma once #include + #include #include #include -#include #include #include -#include #include #include #include -#include #include #include #include @@ -27,6 +25,22 @@ namespace fc { pack( s, args..., _max_depth ); } + template + inline void pack( Stream& s, const uint128_t& v, uint32_t _max_depth ) + { + boost::endian::little_uint64_buf_at hilo[2]; + hilo[0] = uint128_hi64( v ); + hilo[1] = uint128_lo64( v ); + s.write( hilo[0].data(), sizeof(hilo) ); + } + template + inline void unpack( Stream& s, uint128_t& v, uint32_t _max_depth ) + { + boost::endian::little_uint64_buf_at hilo[2]; + s.read( (char*) hilo, sizeof(hilo) ); + v = uint128( hilo[0].value(), hilo[1].value() ); + } + template inline void pack( Stream& s, const fc::exception& e, uint32_t _max_depth ) { @@ -130,22 +144,22 @@ namespace fc { } FC_RETHROW_EXCEPTIONS( warn, "" ) } template - inline void pack( Stream& s, const fc::array& v, uint32_t _max_depth ) { - s.write( &v.data[0], N ); + inline void pack( Stream& s, const std::array& v, uint32_t _max_depth ) { + s.write( v.data(), N ); } template - inline void pack( Stream& s, const fc::array& v, uint32_t _max_depth ) { - s.write( (char*)&v.data[0], N ); + inline void pack( Stream& s, const std::array& v, uint32_t _max_depth ) { + s.write( (char*)v.data(), N ); } template - inline void unpack( Stream& s, fc::array& v, uint32_t _max_depth ) { try { - s.read( &v.data[0], N ); - } FC_RETHROW_EXCEPTIONS( warn, "fc::array", ("length",N) ) } + inline void unpack( Stream& s, std::array& v, uint32_t _max_depth ) { try { + s.read( v.data(), N ); + } FC_RETHROW_EXCEPTIONS( warn, "std::array", ("length",N) ) } template - inline void unpack( Stream& s, fc::array& v, uint32_t _max_depth ) { try { - s.read( (char*)&v.data[0], N ); - } FC_RETHROW_EXCEPTIONS( warn, "fc::array", ("length",N) ) } + inline void unpack( Stream& s, std::array& v, uint32_t _max_depth ) { try { + s.read( (char*)v.data(), N ); + } FC_RETHROW_EXCEPTIONS( warn, "std::array", ("length",N) ) } template inline void pack( Stream& s, const std::shared_ptr& v, uint32_t _max_depth ) @@ -342,17 +356,21 @@ namespace fc { const uint32_t max_depth; }; - // Default pack/unpack functions for classes (if_class) are removed due to recursion issue. + // Default pack/unpack functions for classes are removed due to recursion issue. // Classes should implement pack/unpack functions explicitly. - template + template struct if_class; - template<> - struct if_class { - template + template + struct if_class::value>> { + template static inline void pack( Stream& s, const T v, uint32_t _max_depth ) = delete; - template + template static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) = delete; + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const int64_t v, uint32_t _max_depth ) { boost::endian::little_int64_buf_t tmp; @@ -365,6 +383,10 @@ namespace fc { s.read( (char*)&tmp, sizeof(tmp) ); v = tmp.value(); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const uint64_t v, uint32_t _max_depth ) { boost::endian::little_uint64_buf_t tmp; @@ -377,6 +399,10 @@ namespace fc { s.read( (char*)&tmp, sizeof(tmp) ); v = tmp.value(); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const int32_t v, uint32_t _max_depth ) { boost::endian::little_int32_buf_t tmp; @@ -389,6 +415,10 @@ namespace fc { s.read( (char*)&tmp, sizeof(tmp) ); v = tmp.value(); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const uint32_t v, uint32_t _max_depth ) { boost::endian::little_uint32_buf_t tmp; @@ -401,6 +431,10 @@ namespace fc { s.read( (char*)&tmp, sizeof(tmp) ); v = tmp.value(); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const int16_t v, uint32_t _max_depth ) { boost::endian::little_int16_buf_t tmp; @@ -413,6 +447,10 @@ namespace fc { s.read( (char*)&tmp, sizeof(tmp) ); v = tmp.value(); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const uint16_t v, uint32_t _max_depth ) { boost::endian::little_uint16_buf_t tmp; @@ -425,6 +463,10 @@ namespace fc { s.read( (char*)&tmp, sizeof(tmp) ); v = tmp.value(); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const int8_t v, uint32_t _max_depth ) { s.write( (char*)&v, 1 ); @@ -433,6 +475,10 @@ namespace fc { static inline void unpack( Stream& s, int8_t& v, uint32_t _max_depth ) { s.read( (char*)&v, 1 ); } + }; + + template<> + struct if_class { template static inline void pack( Stream& s, const uint8_t v, uint32_t _max_depth ) { s.write( (char*)&v, 1 ); @@ -443,27 +489,29 @@ namespace fc { } }; - template - struct if_enum { - template + template + struct if_enum; + template + struct if_enum::value>> { + template static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); fc::reflector::visit( pack_object_visitor( v, s, _max_depth - 1 ) ); } - template + template static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); fc::reflector::visit( unpack_object_visitor( v, s, _max_depth - 1 ) ); } }; - template<> - struct if_enum { - template + template + struct if_enum::value>> { + template static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); fc::raw::pack( s, (int64_t)v, _max_depth - 1 ); } - template + template static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); int64_t temp; @@ -472,30 +520,30 @@ namespace fc { } }; - template + template struct if_reflected { template static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - if_class::type>::pack( s, v, _max_depth - 1 ); + if_class::pack( s, v, _max_depth - 1 ); } template static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - if_class::type>::unpack( s, v, _max_depth - 1 ); + if_class::unpack( s, v, _max_depth - 1 ); } }; template<> - struct if_reflected { + struct if_reflected { template static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - if_enum< typename fc::reflector::is_enum >::pack( s, v, _max_depth - 1 ); + if_enum::pack( s, v, _max_depth - 1 ); } template static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - if_enum< typename fc::reflector::is_enum >::unpack( s, v, _max_depth - 1 ); + if_enum::unpack( s, v, _max_depth - 1 ); } }; @@ -689,17 +737,17 @@ namespace fc { void unpack( Stream& s, boost::endian::endian_buffer& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - s.read( v.data(), sizeof(v) ); + s.read( (char*)&v, sizeof(v) ); } template - inline void pack( Stream& s, const T& v, uint32_t _max_depth ) { + void pack( Stream& s, const T& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::pack( s, v, _max_depth - 1 ); } template - inline void unpack( Stream& s, T& v, uint32_t _max_depth ) + void unpack( Stream& s, T& v, uint32_t _max_depth ) { try { FC_ASSERT( _max_depth > 0 ); fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::unpack( s, v, _max_depth - 1 ); diff --git a/include/fc/io/raw_fwd.hpp b/include/fc/io/raw_fwd.hpp index 30c67db..e82fe44 100644 --- a/include/fc/io/raw_fwd.hpp +++ b/include/fc/io/raw_fwd.hpp @@ -1,11 +1,15 @@ #pragma once #include + #include #include #include -#include #include +#include + +#include #include +#include #include #include #include @@ -41,7 +45,10 @@ namespace fc { template inline void unpack( Stream& s, fc::enum_type& tp, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - + template + inline void pack( Stream& s, const uint128_t& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template + inline void unpack( Stream& s, uint128_t& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template inline void pack( Stream& s, const std::set& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template inline void unpack( Stream& s, std::set& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); @@ -106,8 +113,8 @@ namespace fc { template inline void unpack( Stream& s, fc::ripemd160&, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template inline void pack( Stream& s, const fc::ripemd160&, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void unpack( Stream& s, T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void pack( Stream& s, const T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template void unpack( Stream& s, T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template inline void pack( Stream& s, const std::vector& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template inline void unpack( Stream& s, std::vector& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); @@ -124,22 +131,26 @@ namespace fc { inline void unpack( Stream& s, boost::endian::endian_buffer& v, uint32_t _max_depth ); template - inline void pack( Stream& s, const fc::array& v, uint32_t _max_depth ) = delete; + inline void pack( Stream& s, const std::array& v, uint32_t _max_depth ) = delete; template - inline void unpack( Stream& s, fc::array& v, uint32_t _max_depth ) = delete; - template inline void pack( Stream& s, const fc::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void unpack( Stream& s, fc::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH); - template inline void pack( Stream& s, const fc::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void unpack( Stream& s, fc::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH); + inline void unpack( Stream& s, std::array& v, uint32_t _max_depth ) = delete; + template + inline void pack( Stream& s, const std::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template + inline void unpack( Stream& s, std::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH); + template + inline void pack( Stream& s, const std::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); + template + inline void unpack( Stream& s, std::array& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH); - template inline void pack( Stream& s, const shared_ptr& v, + template inline void pack( Stream& s, const std::shared_ptr& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void unpack( Stream& s, shared_ptr& v, + template inline void unpack( Stream& s, std::shared_ptr& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const shared_ptr& v, + template inline void pack( Stream& s, const std::shared_ptr& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void unpack( Stream& s, shared_ptr& v, + template inline void unpack( Stream& s, std::shared_ptr& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template inline void pack( Stream& s, const bool& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); diff --git a/include/fc/log/appender.hpp b/include/fc/log/appender.hpp index 8f57f4c..f8f442f 100644 --- a/include/fc/log/appender.hpp +++ b/include/fc/log/appender.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #include namespace fc { @@ -7,31 +7,31 @@ namespace fc { class log_message; class variant; - class appender_factory : public fc::retainable { + class appender_factory { public: - typedef fc::shared_ptr ptr; + typedef std::shared_ptr ptr; virtual ~appender_factory(){}; - virtual fc::shared_ptr create( const variant& args ) = 0; + virtual std::shared_ptr create( const variant& args ) = 0; }; namespace detail { template class appender_factory_impl : public appender_factory { public: - virtual fc::shared_ptr create( const variant& args ) { - return fc::shared_ptr(new T(args)); + virtual std::shared_ptr create( const variant& args ) { + return std::shared_ptr(new T(args)); } }; } - class appender : public fc::retainable { + class appender { public: - typedef fc::shared_ptr ptr; + typedef std::shared_ptr ptr; template static bool register_appender(const std::string& type) { - return register_appender( type, new detail::appender_factory_impl() ); + return register_appender( type, appender_factory::ptr( new detail::appender_factory_impl() ) ); } static appender::ptr create( const std::string& name, const std::string& type, const variant& args ); diff --git a/include/fc/log/file_appender.hpp b/include/fc/log/file_appender.hpp index bd692ef..6c4accb 100644 --- a/include/fc/log/file_appender.hpp +++ b/include/fc/log/file_appender.hpp @@ -26,7 +26,7 @@ class file_appender : public appender { private: class impl; - fc::shared_ptr my; + std::unique_ptr my; }; } // namespace fc diff --git a/include/fc/log/gelf_appender.hpp b/include/fc/log/gelf_appender.hpp index 1df2b2a..f150f82 100644 --- a/include/fc/log/gelf_appender.hpp +++ b/include/fc/log/gelf_appender.hpp @@ -24,7 +24,7 @@ namespace fc private: class impl; - fc::shared_ptr my; + std::unique_ptr my; }; } // namespace fc diff --git a/include/fc/log/log_message.hpp b/include/fc/log/log_message.hpp index 7c529c0..7706714 100644 --- a/include/fc/log/log_message.hpp +++ b/include/fc/log/log_message.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include diff --git a/include/fc/log/logger.hpp b/include/fc/log/logger.hpp index 6e1a52b..2ddfebf 100644 --- a/include/fc/log/logger.hpp +++ b/include/fc/log/logger.hpp @@ -1,14 +1,13 @@ #pragma once #include #include -#include +#include #include +#include +#include namespace fc { - - class appender; - /** * * @@ -32,8 +31,8 @@ namespace fc ~logger(); logger& operator=(const logger&); logger& operator=(logger&&); - friend bool operator==( const logger&, nullptr_t ); - friend bool operator!=( const logger&, nullptr_t ); + friend bool operator==( const logger&, std::nullptr_t ); + friend bool operator!=( const logger&, std::nullptr_t ); logger& set_log_level( log_level e ); log_level get_log_level()const; @@ -43,16 +42,16 @@ namespace fc void set_name( const std::string& n ); const std::string& name()const; - void add_appender( const fc::shared_ptr& a ); - std::vector > get_appenders()const; - void remove_appender( const fc::shared_ptr& a ); + void add_appender( const appender::ptr& a ); + std::vector get_appenders()const; + void remove_appender( const appender::ptr& a ); bool is_enabled( log_level e )const; void log( log_message m ); private: class impl; - fc::shared_ptr my; + std::shared_ptr my; }; } // namespace fc diff --git a/include/fc/network/http/connection.hpp b/include/fc/network/http/connection.hpp index 466d111..fc8156b 100644 --- a/include/fc/network/http/connection.hpp +++ b/include/fc/network/http/connection.hpp @@ -25,6 +25,7 @@ namespace fc { enum status_code { OK = 200, RecordCreated = 201, + NoContent = 204, BadRequest = 400, NotAuthorized = 401, NotFound = 404, @@ -35,6 +36,7 @@ namespace fc { int status; std::vector
headers; std::vector body; + std::string body_as_string; }; struct request @@ -79,4 +81,4 @@ namespace fc { #include FC_REFLECT( fc::http::header, (key)(val) ) - +FC_REFLECT( fc::http::reply, (status)(headers)(body)(body_as_string) ) diff --git a/include/fc/network/http/server.hpp b/include/fc/network/http/server.hpp deleted file mode 100644 index a52ebcc..0000000 --- a/include/fc/network/http/server.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace fc { namespace http { - - /** - * Listens on a given port for incomming http - * connections and then calls a user provided callback - * function for every http request. - * - */ - class server - { - public: - server(); - server( uint16_t port ); - server( server&& s ); - ~server(); - - server& operator=(server&& s); - - class response - { - public: - class impl; - - response(); - response( const fc::shared_ptr& my); - response( const response& r); - response( response&& r ); - ~response(); - response& operator=(const response& ); - response& operator=( response&& ); - - void add_header( const std::string& key, const std::string& val )const; - void set_status( const http::reply::status_code& s )const; - void set_length( uint64_t s )const; - - void write( const char* data, uint64_t len )const; - - private: - fc::shared_ptr my; - }; - - void listen( const fc::ip::endpoint& p ); - fc::ip::endpoint get_local_endpoint() const; - - /** - * Set the callback to be called for every http request made. - */ - void on_request( const std::function& cb ); - - private: - class impl; - std::unique_ptr my; - }; - typedef std::shared_ptr server_ptr; - -} } diff --git a/include/fc/network/http/websocket.hpp b/include/fc/network/http/websocket.hpp index 4c6e374..9513cef 100644 --- a/include/fc/network/http/websocket.hpp +++ b/include/fc/network/http/websocket.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include namespace fc { namespace http { @@ -12,7 +13,7 @@ namespace fc { namespace http { class websocket_tls_server_impl; class websocket_client_impl; class websocket_tls_client_impl; - } // namespace detail; + } // namespace detail class websocket_connection { @@ -21,10 +22,10 @@ namespace fc { namespace http { virtual void send_message( const std::string& message ) = 0; virtual void close( int64_t code, const std::string& reason ){}; void on_message( const std::string& message ) { _on_message(message); } - string on_http( const std::string& message ) { return _on_http(message); } + fc::http::reply on_http( const std::string& message ) { return _on_http(message); } void on_message_handler( const std::function& h ) { _on_message = h; } - void on_http_handler( const std::function& h ) { _on_http = h; } + void on_http_handler( const std::function& h ) { _on_http = h; } void set_session_data( boost::any d ){ _session_data = std::move(d); } boost::any& get_session_data() { return _session_data; } @@ -36,7 +37,7 @@ namespace fc { namespace http { private: boost::any _session_data; std::function _on_message; - std::function _on_http; + std::function _on_http; }; typedef std::shared_ptr websocket_connection_ptr; diff --git a/include/fc/network/ip.hpp b/include/fc/network/ip.hpp index e183220..cbc984f 100644 --- a/include/fc/network/ip.hpp +++ b/include/fc/network/ip.hpp @@ -82,13 +82,13 @@ namespace fc { namespace raw { template - inline void pack( Stream& s, const ip::address& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) + void pack( Stream& s, const ip::address& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { FC_ASSERT( _max_depth > 0 ); fc::raw::pack( s, uint32_t(v), _max_depth - 1 ); } template - inline void unpack( Stream& s, ip::address& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) + void unpack( Stream& s, ip::address& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { FC_ASSERT( _max_depth > 0 ); uint32_t _ip; diff --git a/include/fc/network/udp_socket.hpp b/include/fc/network/udp_socket.hpp index f150178..d6354c2 100644 --- a/include/fc/network/udp_socket.hpp +++ b/include/fc/network/udp_socket.hpp @@ -1,5 +1,4 @@ #pragma once -#include #include namespace fc { @@ -35,8 +34,8 @@ namespace fc { fc::ip::endpoint local_endpoint()const; private: - class impl; - fc::shared_ptr my; + class impl; + std::shared_ptr my; }; } diff --git a/include/fc/optional.hpp b/include/fc/optional.hpp index ff6c789..04145b4 100644 --- a/include/fc/optional.hpp +++ b/include/fc/optional.hpp @@ -1,9 +1,7 @@ #pragma once -#include #include #include - namespace fc { #ifdef _MSC_VER # pragma warning(push) @@ -81,14 +79,14 @@ namespace fc { optional( U&& u ) :_valid(true) { - new ((char*)ptr()) T( fc::forward(u) ); + new ((char*)ptr()) T( std::forward(u) ); } template optional& operator=( U&& u ) { reset(); - new (ptr()) T( fc::forward(u) ); + new (ptr()) T( std::forward(u) ); _valid = true; return *this; } diff --git a/include/fc/popcount.hpp b/include/fc/popcount.hpp new file mode 100644 index 0000000..d7dfc26 --- /dev/null +++ b/include/fc/popcount.hpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019 BitShares Blockchain Foundation, and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include +#include + +namespace fc { + +#if _MSC_VER || __GNUC__ || __clang__ +inline uint8_t popcount( uint64_t v ) { return __builtin_popcountll(v); } +#else +uint8_t popcount( uint64_t v ); +#endif + +uint8_t popcount( const fc::uint128_t& v ); + +} // namespace fc diff --git a/include/fc/real128.hpp b/include/fc/real128.hpp deleted file mode 100644 index 995c006..0000000 --- a/include/fc/real128.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once -#include - -#define FC_REAL128_PRECISION (uint64_t(1000000) * uint64_t(1000000) * uint64_t(1000000)) - -namespace fc { - class variant; - - /** - * Provides fixed point math operations based on decimal fractions - * with 18 places. - * Delegates to fc::bigint for multiplication and division. - */ - class real128 - { - public: - real128( uint64_t integer = 0); - explicit real128( const std::string& str ); - operator std::string()const; - - friend real128 operator * ( real128 a, const real128& b ) { a *= b; return a; } - friend real128 operator / ( real128 a, const real128& b ) { a /= b; return a; } - friend real128 operator + ( real128 a, const real128& b ) { a += b; return a; } - friend real128 operator - ( real128 a, const real128& b ) { a -= b; return a; } - - real128& operator += ( const real128& o ); - real128& operator -= ( const real128& o ); - real128& operator /= ( const real128& o ); - real128& operator *= ( const real128& o ); - - static real128 from_fixed( const uint128& fixed ); - - uint64_t to_uint64()const; - - template - inline void pack( Stream& s, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { - pack( s, fixed, _max_depth ); - } - private: - uint128 fixed; - }; - - void to_variant( const real128& var, variant& vo, uint32_t max_depth = 1 ); - void from_variant( const variant& var, real128& vo, uint32_t max_depth = 1 ); - - namespace raw - { - template - inline void pack( Stream& s, const real128& value_to_pack, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) - { value_to_pack.pack( s, _max_depth ); } - - template - inline void unpack( Stream& s, real128& value_to_unpack, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) - { - uint128_t delegate; - unpack( s, delegate, _max_depth ); - value_to_unpack = fc::real128::from_fixed( delegate ); - } - } - -} // namespace fc diff --git a/include/fc/reflect/reflect.hpp b/include/fc/reflect/reflect.hpp index a5122d9..3bf0ef7 100644 --- a/include/fc/reflect/reflect.hpp +++ b/include/fc/reflect/reflect.hpp @@ -7,7 +7,6 @@ */ #include -#include #include #include #include @@ -16,6 +15,7 @@ #include #include #include +#include #include @@ -33,8 +33,7 @@ namespace fc { template struct reflector{ typedef T type; - typedef fc::false_type is_defined; - typedef fc::false_type is_enum; + typedef std::false_type is_defined; /** * @tparam Visitor a function object of the form: @@ -137,8 +136,7 @@ void fc::reflector::visit( const Visitor& v ) { \ #define FC_REFLECT_ENUM( ENUM, FIELDS ) \ namespace fc { \ template<> struct reflector { \ - typedef fc::true_type is_defined; \ - typedef fc::true_type is_enum; \ + typedef std::true_type is_defined; \ static const char* to_string(ENUM elem) { \ switch( elem ) { \ BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_TO_STRING, ENUM, FIELDS ) \ @@ -215,8 +213,7 @@ namespace fc { \ template<> struct get_typename { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \ template<> struct reflector {\ typedef TYPE type; \ - typedef fc::true_type is_defined; \ - typedef fc::false_type is_enum; \ + typedef std::true_type is_defined; \ enum member_count_enum { \ local_member_count = 0 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ),\ total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\ @@ -228,8 +225,7 @@ namespace fc { \ template struct get_typename { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \ template struct reflector {\ typedef TYPE type; \ - typedef fc::true_type is_defined; \ - typedef fc::false_type is_enum; \ + typedef std::true_type is_defined; \ enum member_count_enum { \ local_member_count = 0 BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_MEMBER_COUNT, +, MEMBERS ),\ total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\ @@ -266,7 +262,7 @@ namespace fc { \ template<> struct get_typename { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \ template<> struct reflector {\ typedef TYPE type; \ - typedef fc::true_type is_defined; \ + typedef std::true_type is_defined; \ enum member_count_enum { \ local_member_count = BOOST_PP_SEQ_SIZE(MEMBERS), \ total_member_count = local_member_count BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_BASE_MEMBER_COUNT, +, INHERITS )\ diff --git a/include/fc/reflect/typename.hpp b/include/fc/reflect/typename.hpp index e61f79b..3fe9a83 100644 --- a/include/fc/reflect/typename.hpp +++ b/include/fc/reflect/typename.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -7,7 +8,7 @@ #include #include - +#include #include namespace fc { @@ -92,6 +93,15 @@ namespace fc { return n.c_str(); } }; + template struct get_typename< std::array > + { + static const char* name() + { + static std::string _name = std::string("std::array<") + std::string(fc::get_typename::name()) + + "," + fc::to_string(N) + ">"; + return _name.c_str(); + } + }; struct unsigned_int; class variant_object; diff --git a/include/fc/reflect/variant.hpp b/include/fc/reflect/variant.hpp index b47de30..8f88dc9 100644 --- a/include/fc/reflect/variant.hpp +++ b/include/fc/reflect/variant.hpp @@ -63,17 +63,17 @@ namespace fc const uint32_t _max_depth; }; - template - struct if_enum + template + struct if_enum; + template + struct if_enum::value>> { - template static inline void to_variant( const T& v, fc::variant& vo, uint32_t max_depth ) { mutable_variant_object mvo; fc::reflector::visit( to_variant_visitor( mvo, v, max_depth ) ); vo = std::move(mvo); } - template static inline void from_variant( const fc::variant& v, T& o, uint32_t max_depth ) { const variant_object& vo = v.get_object(); @@ -81,15 +81,13 @@ namespace fc } }; - template<> - struct if_enum + template + struct if_enum::value>> { - template static inline void to_variant( const T& o, fc::variant& v, uint32_t max_depth = 1 ) { v = fc::reflector::to_fc_string(o); } - template static inline void from_variant( const fc::variant& v, T& o, uint32_t max_depth = 1 ) { if( v.is_string() ) @@ -103,12 +101,12 @@ namespace fc template void to_variant( const T& o, variant& v, uint32_t max_depth ) { - if_enum::is_enum>::to_variant( o, v, max_depth ); + if_enum::to_variant( o, v, max_depth ); } template void from_variant( const variant& v, T& o, uint32_t max_depth ) { - if_enum::is_enum>::from_variant( v, o, max_depth ); + if_enum::from_variant( v, o, max_depth ); } } diff --git a/include/fc/rpc/api_connection.hpp b/include/fc/rpc/api_connection.hpp index 8e1df24..71eaf80 100644 --- a/include/fc/rpc/api_connection.hpp +++ b/include/fc/rpc/api_connection.hpp @@ -112,13 +112,17 @@ namespace fc { variant call( const string& name, const variants& args ) { auto itr = _by_name.find(name); - FC_ASSERT( itr != _by_name.end(), "no method with name '${name}'", ("name",name)("api",_by_name) ); + if( itr == _by_name.end() ) + FC_THROW_EXCEPTION( method_not_found_exception, "No method with name '${name}'", + ("name",name)("api",_by_name) ); return call( itr->second, args ); } variant call( uint32_t method_id, const variants& args ) { - FC_ASSERT( method_id < _methods.size() ); + if( method_id >= _methods.size() ) + FC_THROW_EXCEPTION( method_not_found_exception, "No method with id '${id}'", + ("id",method_id)("api",_by_name) ); return _methods[method_id](args); } diff --git a/include/fc/rpc/http_api.hpp b/include/fc/rpc/http_api.hpp deleted file mode 100644 index a693655..0000000 --- a/include/fc/rpc/http_api.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -namespace fc { namespace rpc { - - class http_api_connection : public api_connection - { - public: - http_api_connection(uint32_t max_conversion_depth); - ~http_api_connection(); - - virtual variant send_call( - api_id_type api_id, - string method_name, - variants args = variants() ) override; - virtual variant send_callback( - uint64_t callback_id, - variants args = variants() ) override; - virtual void send_notice( - uint64_t callback_id, - variants args = variants() ) override; - - void on_request( - const fc::http::request& req, - const fc::http::server::response& resp ); - - fc::rpc::state _rpc_state; - }; - -} } // namespace fc::rpc diff --git a/include/fc/rpc/state.hpp b/include/fc/rpc/state.hpp index 5d6f618..32211c6 100644 --- a/include/fc/rpc/state.hpp +++ b/include/fc/rpc/state.hpp @@ -6,9 +6,10 @@ namespace fc { namespace rpc { struct request { - optional id; + optional id; std::string method; variants params; + optional jsonrpc; }; struct error_object @@ -20,13 +21,15 @@ namespace fc { namespace rpc { struct response { - response(){} - response( int64_t i, fc::variant r ):id(i),result(r){} - response( int64_t i, error_object r ):id(i),error(r){} - response( int64_t i, fc::variant r, string j ):id(i),jsonrpc(j),result(r){} - response( int64_t i, error_object r, string j ):id(i),jsonrpc(j),error(r){} - int64_t id = 0; - optional jsonrpc; + response() {} + response( const optional& _id, const variant& _result, + const optional& version = optional() ) + : id(_id), jsonrpc(version), result(_result) {} + response( const optional& _id, const error_object& error, + const optional& version = optional() ) + : id(_id), jsonrpc(version), error(error) {} + optional id; + optional jsonrpc; optional result; optional error; }; @@ -44,7 +47,7 @@ namespace fc { namespace rpc { void handle_reply( const response& response ); request start_remote_call( const string& method_name, variants args ); - variant wait_for_response( uint64_t request_id ); + variant wait_for_response( const variant& request_id ); void close(); @@ -52,12 +55,12 @@ namespace fc { namespace rpc { private: uint64_t _next_id = 1; - std::unordered_map::ptr> _awaiting; + std::map::ptr> _awaiting; std::unordered_map _methods; - std::function _unhandled; + std::function _unhandled; }; } } // namespace fc::rpc -FC_REFLECT( fc::rpc::request, (id)(method)(params) ); +FC_REFLECT( fc::rpc::request, (id)(method)(params)(jsonrpc) ); FC_REFLECT( fc::rpc::error_object, (code)(message)(data) ) FC_REFLECT( fc::rpc::response, (id)(jsonrpc)(result)(error) ) diff --git a/include/fc/rpc/websocket_api.hpp b/include/fc/rpc/websocket_api.hpp index 8f06a19..5064499 100644 --- a/include/fc/rpc/websocket_api.hpp +++ b/include/fc/rpc/websocket_api.hpp @@ -1,9 +1,7 @@ #pragma once +#include #include #include -#include -#include -#include namespace fc { namespace rpc { @@ -26,9 +24,9 @@ namespace fc { namespace rpc { variants args = variants() ) override; protected: - std::string on_message( - const std::string& message, - bool send_message = true ); + response on_message( const std::string& message ); + response on_request( const variant& message ); + void on_response( const variant& message ); std::shared_ptr _connection; fc::rpc::state _rpc_state; diff --git a/include/fc/safe.hpp b/include/fc/safe.hpp index d9290b9..42ab676 100644 --- a/include/fc/safe.hpp +++ b/include/fc/safe.hpp @@ -11,8 +11,7 @@ namespace fc { * integer overflow and default initialization. It will * throw an exception on overflow conditions. * - * It can only be used on built-in types. In particular, - * safe is buggy and should not be used. + * It can only be used on built-in types. * * Implemented using spec from: * https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow @@ -27,11 +26,11 @@ namespace fc { safe(){} safe( const safe& o ):value(o.value){} - static safe min() + static constexpr safe min() { return std::numeric_limits::min(); } - static safe max() + static constexpr safe max() { return std::numeric_limits::max(); } @@ -92,7 +91,7 @@ namespace fc { safe operator - ()const { - if( value == std::numeric_limits::min() ) FC_CAPTURE_AND_THROW( overflow_exception, (*this) ); + if( value == min() ) FC_CAPTURE_AND_THROW( overflow_exception, (*this) ); return safe( -value ); } diff --git a/include/fc/shared_ptr.hpp b/include/fc/shared_ptr.hpp deleted file mode 100644 index a07ec46..0000000 --- a/include/fc/shared_ptr.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once - -#include -#include - -namespace fc { - - /** - * @brief used to create reference counted types. - * - * Must be a virtual base class that is initialized with the - * - */ - class retainable { - public: - retainable(); - void retain(); - void release(); - int32_t retain_count()const; - - protected: - virtual ~retainable(); - private: - volatile int32_t _ref_count; - }; - - template - class shared_ptr { - public: - template - shared_ptr( const shared_ptr& o ) - :_ptr(o.get()) { - if(_ptr != nullptr ) _ptr->retain(); - } - shared_ptr( const shared_ptr& o ) - :_ptr(o.get()) { - if(_ptr != nullptr ) _ptr->retain(); - } - - shared_ptr( T* t, bool inc = false ) - :_ptr(t) { if( inc && t != nullptr) t->retain(); } - - shared_ptr():_ptr(nullptr){} - - - shared_ptr( shared_ptr&& p ) - :_ptr(p._ptr){ p._ptr = nullptr; } - - ~shared_ptr() { if( nullptr != _ptr ) { _ptr->release(); _ptr = nullptr; } } - - shared_ptr& reset( T* v = nullptr, bool inc = false ) { - if( v == _ptr ) return *this; - if( inc && nullptr != v ) v->retain(); - if( nullptr != _ptr ) _ptr->release(); - _ptr = v; - return *this; - } - - shared_ptr& operator=(const shared_ptr& p ) { - if( _ptr == p._ptr ) return *this; - if( p._ptr != nullptr ) p._ptr->retain(); - if( _ptr != nullptr ) _ptr->release(); - _ptr = p._ptr; - return *this; - } - shared_ptr& operator=(shared_ptr&& p ) { - std::swap(_ptr,p._ptr); - return *this; - } - T& operator* ()const { return *_ptr; } - T* operator-> ()const { return _ptr; } - - bool operator==( const shared_ptr& p )const { return get() == p.get(); } - bool operator<( const shared_ptr& p )const { return get() < p.get(); } - T * get() const { return _ptr; } - - bool operator!()const { return _ptr == 0; } - operator bool()const { return _ptr != 0; } - private: - T* _ptr; - }; - - template - fc::shared_ptr dynamic_pointer_cast( const fc::shared_ptr& t ) { - return fc::shared_ptr( dynamic_cast(t.get()), true ); - } - template - fc::shared_ptr static_pointer_cast( const fc::shared_ptr& t ) { - return fc::shared_ptr( static_cast(t.get()), true ); - } -} - diff --git a/include/fc/signals.hpp b/include/fc/signals.hpp index dd886a6..5fb4671 100644 --- a/include/fc/signals.hpp +++ b/include/fc/signals.hpp @@ -36,13 +36,13 @@ namespace fc { template inline T wait( boost::signals2::signal& sig, const microseconds& timeout_us=microseconds::maximum() ) { - typename promise::ptr p(new promise("fc::signal::wait")); + typename promise::ptr p = promise::create("fc::signal::wait"); boost::signals2::scoped_connection c( sig.connect( [=]( T t ) { p->set_value(t); } )); return p->wait( timeout_us ); } inline void wait( boost::signals2::signal& sig, const microseconds& timeout_us=microseconds::maximum() ) { - promise::ptr p(new promise("fc::signal::wait")); + promise::ptr p = promise::create("fc::signal::wait"); boost::signals2::scoped_connection c( sig.connect( [=]() { p->set_value(); } )); p->wait( timeout_us ); } diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 4a440a2..7ed4d90 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -11,11 +11,11 @@ **/ #pragma once +#include #include #include #include -#include #include namespace fc { @@ -141,58 +141,53 @@ struct storage_ops { template struct position { - static const int pos = -1; + static constexpr int pos = -1; }; template struct position { - static const int pos = 0; + static constexpr int pos = 0; }; template struct position { - static const int pos = position::pos != -1 ? position::pos + 1 : -1; + static constexpr int pos = position::pos != -1 ? position::pos + 1 : -1; }; template struct type_info { - static const bool no_reference_types = false; - static const bool no_duplicates = position::pos == -1 && type_info::no_duplicates; - static const size_t size = type_info::size > sizeof(T&) ? type_info::size : sizeof(T&); - static const size_t count = 1 + type_info::count; + static constexpr bool no_reference_types = false; + static constexpr bool no_duplicates = position::pos == -1 && type_info::no_duplicates; + static constexpr size_t size = type_info::size > sizeof(T&) ? type_info::size : sizeof(T&); + static constexpr size_t count = 1 + type_info::count; }; template struct type_info { - static const bool no_reference_types = type_info::no_reference_types; - static const bool no_duplicates = position::pos == -1 && type_info::no_duplicates; - static const size_t size = type_info::size > sizeof(T) ? type_info::size : sizeof(T&); - static const size_t count = 1 + type_info::count; + static constexpr bool no_reference_types = type_info::no_reference_types; + static constexpr bool no_duplicates = position::pos == -1 && type_info::no_duplicates; + static constexpr size_t size = type_info::size > sizeof(T) ? type_info::size : sizeof(T&); + static constexpr size_t count = 1 + type_info::count; }; template<> struct type_info<> { - static const bool no_reference_types = true; - static const bool no_duplicates = true; - static const size_t count = 0; - static const size_t size = 0; + static constexpr bool no_reference_types = true; + static constexpr bool no_duplicates = true; + static constexpr size_t count = 0; + static constexpr size_t size = 0; }; template -size_t size( TTag ) +constexpr size_t size( TTag ) { return 0; } template -size_t size( TTag tag ) +constexpr size_t size( TTag tag ) { - if (tag <= 0) - { - return sizeof(A); - } - - return size( --tag ); + return tag <= 0 ? sizeof(A) : size( --tag ); } @@ -216,17 +211,17 @@ public: } // namespace impl template -static const fc::array +static const std::array init_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0) { - return fc::array(); + return std::array(); } template -static const fc::array +static const std::array init_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 ) { - fc::array result{}; + std::array result{}; if( !funcs ) funcs = result.begin(); *funcs++ = [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); }; init_wrappers( v, d, funcs ); @@ -234,17 +229,17 @@ static const fc::array } template -static const fc::array +static const std::array init_const_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 ) { - return fc::array(); + return std::array(); } template -static const fc::array +static const std::array init_const_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 ) { - fc::array result{}; + std::array result{}; if( !funcs ) funcs = result.begin(); *funcs++ = [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); }; init_const_wrappers( v, d, funcs ); @@ -304,7 +299,7 @@ public: template> struct tag { - static const int value = impl::position::pos; + static constexpr int value = impl::position::pos; }; static_variant() @@ -434,7 +429,7 @@ public: return wrappers[tag]( v, data ); } - static int count() { return impl::type_info::count; } + static constexpr int count() { return impl::type_info::count; } void set_which( tag_type w ) { FC_ASSERT( w >= 0 ); FC_ASSERT( w < count() ); @@ -443,6 +438,9 @@ public: } tag_type which() const {return _tag;} + + template + bool is_type() const { return _tag == tag::value; } }; struct from_static_variant diff --git a/include/fc/thread/future.hpp b/include/fc/thread/future.hpp index f0365ea..4e98c3d 100644 --- a/include/fc/thread/future.hpp +++ b/include/fc/thread/future.hpp @@ -1,9 +1,11 @@ #pragma once #include -#include #include #include #include +#include + +#include //#define FC_TASK_NAMES_ARE_MANDATORY 1 #ifdef FC_TASK_NAMES_ARE_MANDATORY @@ -56,10 +58,10 @@ namespace fc { }; } - class promise_base : public virtual retainable{ + class promise_base : public std::enable_shared_from_this { public: - typedef fc::shared_ptr ptr; - promise_base(const char* desc FC_TASK_NAME_DEFAULT_ARG); + typedef std::shared_ptr ptr; + virtual ~promise_base(); const char* get_desc()const; @@ -71,6 +73,8 @@ namespace fc { void set_exception( const fc::exception_ptr& e ); protected: + promise_base(const char* desc FC_TASK_NAME_DEFAULT_ARG); + void _wait( const microseconds& timeout_us ); void _wait_until( const time_point& timeout_us ); void _enqueue_thread(); @@ -80,7 +84,6 @@ namespace fc { void _set_value(const void* v); void _on_complete( detail::completion_handler* c ); - ~promise_base(); private: friend class thread; @@ -99,18 +102,29 @@ namespace fc { const char* _cancellation_reason; private: #endif - const char* _desc; - detail::completion_handler* _compl; + const char* _desc; + detail::completion_handler* _compl; }; template class promise : virtual public promise_base { public: - typedef fc::shared_ptr< promise > ptr; - promise( const char* desc FC_TASK_NAME_DEFAULT_ARG):promise_base(desc){} - promise( const T& val ){ set_value(val); } - promise( T&& val ){ set_value(std::move(val) ); } - + typedef std::shared_ptr< promise > ptr; + virtual ~promise(){} + + static ptr create( const char* desc FC_TASK_NAME_DEFAULT_ARG ) + { + return ptr( new promise( desc ) ); + } + static ptr create( const T& val ) + { + return ptr( new promise( val ) ); + } + static ptr create( T&& val ) + { + return ptr( new promise( std::move(val) ) ); + } + const T& wait(const microseconds& timeout = microseconds::maximum() ){ this->_wait( timeout ); return *result; @@ -132,22 +146,32 @@ namespace fc { template void on_complete( CompletionHandler&& c ) { - _on_complete( new detail::completion_handler_impl(fc::forward(c)) ); + _on_complete( new detail::completion_handler_impl(std::forward(c)) ); } protected: + promise( const char* desc ):promise_base(desc){} + promise( const T& val ){ set_value(val); } + promise( T&& val ){ set_value(std::move(val) ); } + optional result; - ~promise(){} }; template<> class promise : virtual public promise_base { public: - typedef fc::shared_ptr< promise > ptr; - promise( const char* desc FC_TASK_NAME_DEFAULT_ARG):promise_base(desc){} - promise( bool fulfilled, const char* desc FC_TASK_NAME_DEFAULT_ARG ){ - if( fulfilled ) set_value(); - } + typedef std::shared_ptr< promise > ptr; + + virtual ~promise(){} + static ptr create( const char* desc FC_TASK_NAME_DEFAULT_ARG ) + { + return ptr( new promise( desc ) ); + } + static ptr create( bool fulfilled, const char* desc FC_TASK_NAME_DEFAULT_ARG ) + { + return ptr( new promise( fulfilled, desc ) ); + } + void wait(const microseconds& timeout = microseconds::maximum() ){ this->_wait( timeout ); } @@ -160,10 +184,13 @@ namespace fc { template void on_complete( CompletionHandler&& c ) { - _on_complete( new detail::completion_handler_impl(fc::forward(c)) ); + _on_complete( new detail::completion_handler_impl(std::forward(c)) ); } protected: - ~promise(){} + promise( const char* desc ):promise_base(desc){} + promise( bool fulfilled, const char* desc ){ + if( fulfilled ) set_value(); + } }; /** @@ -184,8 +211,8 @@ namespace fc { template class future { public: - future( const fc::shared_ptr>& p ):m_prom(p){} - future( fc::shared_ptr>&& p ):m_prom(std::move(p)){} + future( const typename promise::ptr& p ):m_prom(p){} + future( typename promise::ptr&& p ):m_prom(std::move(p)){} future(const future& f ) : m_prom(f.m_prom){} future(){} @@ -194,7 +221,6 @@ namespace fc { return *this; } - operator const T&()const { return wait(); } /// @pre valid() @@ -247,18 +273,18 @@ namespace fc { */ template void on_complete( CompletionHandler&& c ) { - m_prom->on_complete( fc::forward(c) ); + m_prom->on_complete( std::forward(c) ); } private: friend class thread; - fc::shared_ptr> m_prom; + typename promise::ptr m_prom; }; template<> class future { public: - future( const fc::shared_ptr>& p ):m_prom(p){} - future( fc::shared_ptr>&& p ):m_prom(std::move(p)){} + future( const typename promise::ptr& p ):m_prom(p){} + future( typename promise::ptr&& p ):m_prom(std::move(p)){} future(const future& f ) : m_prom(f.m_prom){} future(){} @@ -308,12 +334,12 @@ namespace fc { template void on_complete( CompletionHandler&& c ) { - m_prom->on_complete( fc::forward(c) ); + m_prom->on_complete( std::forward(c) ); } private: friend class thread; - fc::shared_ptr> m_prom; + typename promise::ptr m_prom; }; } diff --git a/include/fc/thread/parallel.hpp b/include/fc/thread/parallel.hpp index 59f9cf6..14d4bbf 100644 --- a/include/fc/thread/parallel.hpp +++ b/include/fc/thread/parallel.hpp @@ -55,8 +55,8 @@ namespace fc { ~ticket_guard(); void wait_for_my_turn(); private: - promise* my_promise; - future* ticket; + promise::ptr my_promise; + future* ticket; }; friend class ticket_guard; @@ -96,11 +96,12 @@ namespace fc { template auto do_parallel( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG ) -> fc::future { typedef decltype(f()) Result; - typedef typename fc::deduce::type FunctorType; - fc::task* tsk = - new fc::task( fc::forward(f), desc ); - fc::future r(fc::shared_ptr< fc::promise >(tsk,true) ); - detail::get_worker_pool().post( tsk ); + typedef typename std::remove_const_t< std::remove_reference_t > FunctorType; + typename task::ptr tsk = + task::create( std::forward(f), desc ); + tsk->retain(); // HERE BE DRAGONS + fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); + detail::get_worker_pool().post( tsk.get() ); return r; } } diff --git a/include/fc/thread/task.hpp b/include/fc/thread/task.hpp index 987810b..f7c2ec5 100644 --- a/include/fc/thread/task.hpp +++ b/include/fc/thread/task.hpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace fc { struct context; @@ -31,9 +32,28 @@ namespace fc { public: void run(); virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override; + virtual ~task_base(); + + /* HERE BE DRAGONS + * + * Tasks are handled by an fc::thread . To avoid concurrency issues, fc::thread keeps a reference to the + * task in the form of a simple pointer. + * At the same time, a task is also a promise that will be fulfilled with the task result, so typically the + * creator of the task also keeps a reference to the task (but not necessarily always). + * + * Because effectively neither fc::thread nor the task creator are responsible for releasing resources + * associated with a task, and neither can delete the task without knowing if the other still needs it, + * the task object is managed by a shared_ptr. + * However, fc::thread doesn't hold a shared_ptr but a native pointer. To work around this, the task can + * be made to contain a shared_ptr holding itself (by calling retain()), which happens before the task + * is handed to an fc::thread, e. g. in fc::async(). Once the thread has processed the task, it calls + * release() which deletes the self-referencing shared_ptr and deletes the task object if it's no longer + * in use anywhere. + */ + void retain(); + void release(); protected: - ~task_base(); /// Task priority looks like unsupported feature. uint64_t _posted_num; priority _prio; @@ -65,6 +85,9 @@ namespace fc { void run_impl(); void cleanup_task_specific_data(); + private: + std::shared_ptr _self; + boost::atomic _retain_count; }; namespace detail { @@ -90,41 +113,57 @@ namespace fc { template class task : virtual public task_base, virtual public promise { public: + typedef std::shared_ptr> ptr; + + virtual ~task(){} + + template + static ptr create( Functor&& f, const char* desc ) + { + return ptr( new task( std::move(f), desc ) ); + } + virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); } + private: template task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise(desc) { - typedef typename fc::deduce::type FunctorType; + typedef typename std::remove_const_t< std::remove_reference_t > FunctorType; static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" ); - new ((char*)&_functor) FunctorType( fc::forward(f) ); + new ((char*)&_functor) FunctorType( std::forward(f) ); _destroy_functor = &detail::functor_destructor::destroy; _promise_impl = static_cast*>(this); _run_functor = &detail::functor_run::run; } - virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); } - alignas(double) char _functor[FunctorSize]; - private: - ~task(){} + alignas(double) char _functor[FunctorSize]; }; template - class task : virtual public task_base, virtual public promise { + class task : public task_base, public promise { public: + typedef std::shared_ptr> ptr; + + virtual ~task(){} + + template + static ptr create( Functor&& f, const char* desc ) + { + return ptr( new task( std::move(f), desc ) ); + } + virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); } + private: template task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise(desc) { - typedef typename fc::deduce::type FunctorType; + typedef typename std::remove_const_t< std::remove_reference_t > FunctorType; static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" ); - new ((char*)&_functor) FunctorType( fc::forward(f) ); + new ((char*)&_functor) FunctorType( std::forward(f) ); _destroy_functor = &detail::functor_destructor::destroy; _promise_impl = static_cast*>(this); _run_functor = &detail::void_functor_run::run; } - virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); } - alignas(double) char _functor[FunctorSize]; - private: - ~task(){} + alignas(double) char _functor[FunctorSize]; }; } diff --git a/include/fc/thread/thread.hpp b/include/fc/thread/thread.hpp index b71c066..bd02d09 100644 --- a/include/fc/thread/thread.hpp +++ b/include/fc/thread/thread.hpp @@ -86,11 +86,12 @@ namespace fc { template auto async( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future { typedef decltype(f()) Result; - typedef typename fc::deduce::type FunctorType; - fc::task* tsk = - new fc::task( fc::forward(f), desc ); - fc::future r(fc::shared_ptr< fc::promise >(tsk,true) ); - async_task(tsk,prio); + typedef typename std::remove_const_t< std::remove_reference_t > FunctorType; + typename task::ptr tsk = + task::create( std::forward(f), desc ); + tsk->retain(); // HERE BE DRAGONS + fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); + async_task(tsk.get(),prio); return r; } void poke(); @@ -109,10 +110,11 @@ namespace fc { auto schedule( Functor&& f, const fc::time_point& when, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future { typedef decltype(f()) Result; - fc::task* tsk = - new fc::task( fc::forward(f), desc ); - fc::future r(fc::shared_ptr< fc::promise >(tsk,true) ); - async_task(tsk,prio,when); + typename task::ptr tsk = + task::create( std::forward(f), desc ); + tsk->retain(); // HERE BE DRAGONS + fc::future r( std::dynamic_pointer_cast< promise >(tsk) ); + async_task(tsk.get(),prio,when); return r; } @@ -147,8 +149,8 @@ namespace fc { template int wait_any( const fc::future& f1, const fc::future& f2, const microseconds& timeout_us = microseconds::maximum()) { std::vector proms(2); - proms[0] = fc::static_pointer_cast(f1.m_prom); - proms[1] = fc::static_pointer_cast(f2.m_prom); + proms[0] = std::static_pointer_cast(f1.m_prom); + proms[1] = std::static_pointer_cast(f2.m_prom); return wait_any_until(std::move(proms), fc::time_point::now()+timeout_us ); } private: @@ -223,11 +225,11 @@ namespace fc { template auto async( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future { - return fc::thread::current().async( fc::forward(f), desc, prio ); + return fc::thread::current().async( std::forward(f), desc, prio ); } template auto schedule( Functor&& f, const fc::time_point& t, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future { - return fc::thread::current().schedule( fc::forward(f), t, desc, prio ); + return fc::thread::current().schedule( std::forward(f), t, desc, prio ); } /** diff --git a/include/fc/uint128.hpp b/include/fc/uint128.hpp index 42c8e3d..46a18bd 100644 --- a/include/fc/uint128.hpp +++ b/include/fc/uint128.hpp @@ -1,158 +1,71 @@ +/* + * Copyright (c) 2019 BitShares Blockchain Foundation, and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + #pragma once -#include + +#ifdef __SIZEOF_INT128__ + #include -#include -#include -#include -#include -#include +namespace fc { -#ifdef _MSC_VER - #pragma warning (push) - #pragma warning (disable : 4244) -#endif //// _MSC_VER +using int128_t = __int128_t; +using uint128_t = __uint128_t; -namespace fc -{ - class bigint; - /** - * @brief an implementation of 128 bit unsigned integer - * - */ - class uint128 - { - - - public: - uint128():hi(0),lo(0){} - uint128( uint32_t l ):hi(0),lo(l){} - uint128( int32_t l ):hi( -(l<0) ),lo(l){} - uint128( int64_t l ):hi( -(l<0) ),lo(l){} - uint128( uint64_t l ):hi(0),lo(l){} - uint128( const std::string& s ); - uint128( uint64_t _h, uint64_t _l ) - :hi(_h),lo(_l){} - uint128( const fc::bigint& bi ); - - operator std::string()const; - operator fc::bigint()const; - - bool operator == ( const uint128& o )const{ return hi == o.hi && lo == o.lo; } - bool operator != ( const uint128& o )const{ return hi != o.hi || lo != o.lo; } - bool operator < ( const uint128& o )const { return (hi == o.hi) ? lo < o.lo : hi < o.hi; } - bool operator < ( const int64_t& o )const { return *this < uint128(o); } - bool operator !()const { return !(hi !=0 || lo != 0); } - uint128 operator -()const { return ++uint128( ~hi, ~lo ); } - uint128 operator ~()const { return uint128( ~hi, ~lo ); } - - uint128& operator++() { hi += (++lo == 0); return *this; } - uint128& operator--() { hi -= (lo-- == 0); return *this; } - uint128 operator++(int) { auto tmp = *this; ++(*this); return tmp; } - uint128 operator--(int) { auto tmp = *this; --(*this); return tmp; } - - uint128& operator |= ( const uint128& u ) { hi |= u.hi; lo |= u.lo; return *this; } - uint128& operator &= ( const uint128& u ) { hi &= u.hi; lo &= u.lo; return *this; } - uint128& operator ^= ( const uint128& u ) { hi ^= u.hi; lo ^= u.lo; return *this; } - uint128& operator <<= ( const uint128& u ); - uint128& operator >>= ( const uint128& u ); - - uint128& operator += ( const uint128& u ) { const uint64_t old = lo; lo += u.lo; hi += u.hi + (lo < old); return *this; } - uint128& operator -= ( const uint128& u ) { return *this += -u; } - uint128& operator *= ( const uint128& u ); - uint128& operator /= ( const uint128& u ); - uint128& operator %= ( const uint128& u ); - - - friend uint128 operator + ( const uint128& l, const uint128& r ) { return uint128(l)+=r; } - friend uint128 operator - ( const uint128& l, const uint128& r ) { return uint128(l)-=r; } - friend uint128 operator * ( const uint128& l, const uint128& r ) { return uint128(l)*=r; } - friend uint128 operator / ( const uint128& l, const uint128& r ) { return uint128(l)/=r; } - friend uint128 operator % ( const uint128& l, const uint128& r ) { return uint128(l)%=r; } - friend uint128 operator | ( const uint128& l, const uint128& r ) { return uint128(l)=(r); } - friend uint128 operator & ( const uint128& l, const uint128& r ) { return uint128(l)&=r; } - friend uint128 operator ^ ( const uint128& l, const uint128& r ) { return uint128(l)^=r; } - friend uint128 operator << ( const uint128& l, const uint128& r ) { return uint128(l)<<=r; } - friend uint128 operator >> ( const uint128& l, const uint128& r ) { return uint128(l)>>=r; } - friend bool operator > ( const uint128& l, const uint128& r ) { return r < l; } - friend bool operator > ( const uint128& l, const int64_t& r ) { return uint128(r) < l; } - friend bool operator > ( const int64_t& l, const uint128& r ) { return r < uint128(l); } - - friend bool operator >= ( const uint128& l, const uint128& r ) { return l == r || l > r; } - friend bool operator >= ( const uint128& l, const int64_t& r ) { return l >= uint128(r); } - friend bool operator >= ( const int64_t& l, const uint128& r ) { return uint128(l) >= r; } - friend bool operator <= ( const uint128& l, const uint128& r ) { return l == r || l < r; } - friend bool operator <= ( const uint128& l, const int64_t& r ) { return l <= uint128(r); } - friend bool operator <= ( const int64_t& l, const uint128& r ) { return uint128(l) <= r; } - - friend std::size_t hash_value( const uint128& v ) { return city_hash_size_t((const char*)&v, sizeof(v)); } - - uint32_t to_integer()const - { - FC_ASSERT( hi == 0 ); - uint32_t lo32 = (uint32_t) lo; - FC_ASSERT( lo == lo32 ); - return lo32; - } - uint64_t to_uint64()const - { - FC_ASSERT( hi == 0 ); - return lo; - } - uint32_t low_32_bits()const { return (uint32_t) lo; } - uint64_t low_bits()const { return lo; } - uint64_t high_bits()const { return hi; } - - static uint128 max_value() { - const uint64_t max64 = std::numeric_limits::max(); - return uint128( max64, max64 ); - } - - static void full_product( const uint128& a, const uint128& b, uint128& result_hi, uint128& result_lo ); - - uint8_t popcount() const; - - // fields must be public for serialization - uint64_t hi; - uint64_t lo; - }; - static_assert( sizeof(uint128) == 2*sizeof(uint64_t), "validate packing assumptions" ); - - typedef uint128 uint128_t; - - class variant; - - void to_variant( const uint128& var, variant& vo, uint32_t max_depth = 1 ); - void from_variant( const variant& var, uint128& vo, uint32_t max_depth = 1 ); - - namespace raw - { - template - inline void pack( Stream& s, const uint128& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { - pack( s, u.hi, _max_depth ); - pack( s, u.lo, _max_depth ); - } - template - inline void unpack( Stream& s, uint128& u, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { - unpack( s, u.hi, _max_depth ); - unpack( s, u.lo, _max_depth ); - } - } - - size_t city_hash_size_t(const char *buf, size_t len); -} // namespace fc - -namespace std -{ - template<> - struct hash - { - size_t operator()( const fc::uint128& s )const; - }; +inline uint64_t uint128_lo64(const uint128_t x) { + return static_cast(x & 0xffffffffffffffffULL); +} +inline uint64_t uint128_hi64(const uint128_t x) { + return static_cast( x >> 64 ); } -FC_REFLECT( fc::uint128_t, (hi)(lo) ) +} // namespace fc -#ifdef _MSC_VER - #pragma warning (pop) -#endif ///_MSC_VER +#else // __SIZEOF_INT128__ + +#include + +namespace fc { + +using boost::multiprecision::int128_t; +using boost::multiprecision::uint128_t; + +inline uint64_t uint128_lo64(const uint128_t& x) { + return static_cast(x & 0xffffffffffffffffULL); +} +inline uint64_t uint128_hi64(const uint128_t& x) { + return static_cast( x >> 64 ); +} + +} // namespace fc + +#endif // __SIZEOF_INT128__ + +namespace fc { + +inline uint128_t uint128( const uint64_t hi, const uint64_t lo ) { + return ( uint128_t(hi) << 64 ) + lo; +} + +} // namespace fc diff --git a/include/fc/utility.hpp b/include/fc/utility.hpp deleted file mode 100644 index e0e6371..0000000 --- a/include/fc/utility.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once -#include -#include - -#ifdef _MSC_VER -#pragma warning(disable: 4482) // nonstandard extension used enum Name::Val, standard in C++11 -#define NO_RETURN __declspec(noreturn) -#else -#define NO_RETURN __attribute__((noreturn)) -#endif - - -//namespace std { -// typedef decltype(sizeof(int)) size_t; -// typedef decltype(nullptr) nullptr_t; -//} - -namespace fc { - using std::size_t; - typedef decltype(nullptr) nullptr_t; - - template struct deduce { typedef T type; }; - template struct deduce { typedef T type; }; - template struct deduce { typedef T type; }; - template struct deduce { typedef T type; }; - template struct deduce{ typedef T type; }; - - template - inline T&& forward( U&& u ) { return static_cast(u); } - - struct true_type { enum _value { value = 1 }; }; - struct false_type { enum _value { value = 0 }; }; - - namespace detail { - template fc::true_type is_class_helper(void(T::*)()); - template fc::false_type is_class_helper(...); - } - - template - struct is_class { typedef decltype(detail::is_class_helper(0)) type; enum value_enum { value = type::value }; }; -} diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp index 8da0b2a..2098a70 100644 --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -1,5 +1,7 @@ #pragma once +#include +#include #include #include #include @@ -11,7 +13,9 @@ #include // memset #include +#include #include +#include #include #include @@ -146,6 +150,9 @@ namespace fc void to_variant( const microseconds& input_microseconds, variant& output_variant, uint32_t max_depth ); void from_variant( const variant& input_variant, microseconds& output_microseconds, uint32_t max_depth ); + void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth = 1 ); + void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth = 1 ); + #ifdef __APPLE__ void to_variant( size_t s, variant& v, uint32_t max_depth = 1 ); #elif !defined(_MSC_VER) @@ -207,7 +214,7 @@ namespace fc /// Constructs a null_type variant variant(); /// Constructs a null_type variant - variant( nullptr_t, uint32_t max_depth = 1 ); + variant( std::nullptr_t, uint32_t max_depth = 1 ); /// @param str - UTF8 string variant( const char* str, uint32_t max_depth = 1 ); @@ -345,7 +352,7 @@ namespace fc template variant& operator=( T&& v ) { - return *this = variant( fc::forward(v) ); + return *this = variant( std::forward(v) ); } template @@ -654,15 +661,45 @@ namespace fc c.insert( item.as( max_depth - 1 ) ); } + template + void to_variant( const std::array& bi, variant& v, uint32_t max_depth = 1 ) + { + v = variant( to_hex( bi.data(), N ) ); + } + template + void from_variant( const variant& v, std::array& bi, uint32_t max_depth = 1 ) + { + std::string ve = v.as_string(); + if( ve.size() ) + from_hex( ve, bi.data(), std::min( ve.size() / 2, bi.size() ) ); + else + memset( bi.data(), 0, bi.size() ); + } + + template + void to_variant( const std::array& bi, variant& v, uint32_t max_depth = 1 ) + { + v = variant( to_hex( (char*) bi.data(), N ) ); + } + template + void from_variant( const variant& v, std::array& bi, uint32_t max_depth = 1 ) + { + std::string ve = v.as_string(); + if( ve.size() ) + from_hex( ve, (char*)bi.data(), std::min( ve.size() / 2, bi.size() ) ); + else + memset( bi.data(), 0, bi.size() ); + } + variant operator + ( const variant& a, const variant& b ); variant operator - ( const variant& a, const variant& b ); variant operator * ( const variant& a, const variant& b ); variant operator / ( const variant& a, const variant& b ); - variant operator == ( const variant& a, const variant& b ); - variant operator != ( const variant& a, const variant& b ); - variant operator < ( const variant& a, const variant& b ); - variant operator > ( const variant& a, const variant& b ); - variant operator ! ( const variant& a ); + bool operator == ( const variant& a, const variant& b ); + bool operator != ( const variant& a, const variant& b ); + bool operator < ( const variant& a, const variant& b ); + bool operator > ( const variant& a, const variant& b ); + bool operator ! ( const variant& a ); } // namespace fc #include diff --git a/include/fc/variant_object.hpp b/include/fc/variant_object.hpp index 73edd26..477c1c9 100644 --- a/include/fc/variant_object.hpp +++ b/include/fc/variant_object.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include +#include namespace fc { @@ -70,7 +70,7 @@ namespace fc variant_object( string key, T&& val ) :_key_value( std::make_shared >() ) { - *this = variant_object( std::move(key), variant(forward(val)) ); + *this = variant_object( std::move(key), variant(std::forward(val)) ); } variant_object( const variant_object& ); variant_object( variant_object&& ); @@ -173,7 +173,7 @@ namespace fc mutable_variant_object& operator()( string key, T&& var, uint32_t max_depth ) { _FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" ); - set( std::move(key), variant( fc::forward(var), max_depth - 1 ) ); + set( std::move(key), variant( std::forward(var), max_depth - 1 ) ); return *this; } /** @@ -191,7 +191,7 @@ namespace fc explicit mutable_variant_object( T&& v ) :_key_value( new std::vector() ) { - *this = variant(fc::forward(v)).get_object(); + *this = variant(std::forward(v)).get_object(); } mutable_variant_object(); @@ -202,7 +202,7 @@ namespace fc mutable_variant_object( string key, T&& val ) :_key_value( new std::vector() ) { - set( std::move(key), variant(forward(val)) ); + set( std::move(key), variant(std::forward(val)) ); } mutable_variant_object( mutable_variant_object&& ); @@ -232,7 +232,7 @@ namespace fc optional v; try { - v = variant( fc::forward(var), _max_depth ); + v = variant( std::forward(var), _max_depth ); } catch( ... ) { diff --git a/src/asio.cpp b/src/asio.cpp index 35b2990..b56ec49 100644 --- a/src/asio.cpp +++ b/src/asio.cpp @@ -190,7 +190,7 @@ namespace fc { try { resolver res( fc::asio::default_io_service() ); - promise >::ptr p( new promise >("tcp::resolve completion") ); + promise >::ptr p = promise >::create("tcp::resolve completion"); res.async_resolve( boost::asio::ip::tcp::resolver::query(hostname,port), boost::bind( detail::resolve_handler, p, _1, _2 ) ); return p->wait(); @@ -204,7 +204,7 @@ namespace fc { try { resolver res( fc::asio::default_io_service() ); - promise >::ptr p( new promise >("udp::resolve completion") ); + promise >::ptr p = promise >::create("udp::resolve completion"); res.async_resolve( resolver::query(hostname,port), boost::bind( detail::resolve_handler, p, _1, _2 ) ); return p->wait(); diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp index 7bb5d20..55464a7 100644 --- a/src/crypto/aes.cpp +++ b/src/crypto/aes.cpp @@ -4,11 +4,11 @@ #include #include -#include #include #include +#include #include #include #include @@ -38,7 +38,7 @@ aes_encoder::~aes_encoder() { } -void aes_encoder::init( const fc::sha256& key, const fc::uint128& init_value ) +void aes_encoder::init( const fc::sha256& key, const uint128_t& init_value ) { my->ctx.obj = EVP_CIPHER_CTX_new(); /* Create and initialise the context */ @@ -54,8 +54,8 @@ void aes_encoder::init( const fc::sha256& key, const fc::uint128& init_value ) * IV size for *most* modes is the same as the block size. For AES this * is 128 bits */ boost::endian::little_uint64_buf_t iv[2]; - iv[0] = init_value.hi; - iv[1] = init_value.lo; + iv[0] = uint128_hi64( init_value ); + iv[1] = uint128_lo64( init_value ); if(1 != EVP_EncryptInit_ex(my->ctx, EVP_aes_256_cbc(), NULL, (unsigned char*)&key, (const unsigned char*)iv[0].data())) { FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption init", @@ -106,7 +106,7 @@ aes_decoder::aes_decoder() (void)init; } -void aes_decoder::init( const fc::sha256& key, const fc::uint128& init_value ) +void aes_decoder::init( const fc::sha256& key, const uint128_t& init_value ) { my->ctx.obj = EVP_CIPHER_CTX_new(); /* Create and initialise the context */ @@ -122,8 +122,8 @@ void aes_decoder::init( const fc::sha256& key, const fc::uint128& init_value ) * IV size for *most* modes is the same as the block size. For AES this * is 128 bits */ boost::endian::little_uint64_buf_t iv[2]; - iv[0] = init_value.hi; - iv[1] = init_value.lo; + iv[0] = uint128_hi64( init_value ); + iv[1] = uint128_lo64( init_value ); if(1 != EVP_DecryptInit_ex(my->ctx, EVP_aes_256_cbc(), NULL, (unsigned char*)&key, (const unsigned char*)iv[0].data())) { FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption init", diff --git a/src/crypto/city.cpp b/src/crypto/city.cpp index af3a91b..3ed4cd0 100644 --- a/src/crypto/city.cpp +++ b/src/crypto/city.cpp @@ -31,10 +31,9 @@ //#include #include +#include #include // for memcpy and memset #include -#include -#include #include #if defined(__SSE4_2__) && defined(__x86_64__) @@ -47,18 +46,14 @@ namespace fc { using namespace std; - -inline uint64_t Uint128Low64(const uint128& x) { return x.low_bits(); } -inline uint64_t Uint128High64(const uint128& x) { return x.high_bits(); } - // Hash 128 input bits down to 64 bits of output. // This is intended to be a reasonably good hash function. -inline uint64_t Hash128to64(const uint128& x) { +inline uint64_t Hash128to64(const uint128_t& x) { // Murmur-inspired hashing. const uint64_t kMul = 0x9ddfea08eb382d69ULL; - uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; + uint64_t a = (uint128_lo64(x) ^ uint128_hi64(x)) * kMul; a ^= (a >> 47); - uint64_t b = (Uint128High64(x) ^ a) * kMul; + uint64_t b = (uint128_hi64(x) ^ a) * kMul; b ^= (b >> 47); b *= kMul; return b; @@ -280,7 +275,7 @@ static uint64_t ShiftMix(uint64_t val) { } static uint64_t HashLen16(uint64_t u, uint64_t v) { - return Hash128to64(uint128(u, v)); + return Hash128to64( uint128( u, v) ); } static uint64_t HashLen16(uint64_t u, uint64_t v, uint64_t mul) { @@ -425,9 +420,9 @@ uint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed) { // A subroutine for CityHash128(). Returns a decent 128-bit hash for strings // of any length representable in signed long. Based on City and Murmur. -static uint128 CityMurmur(const char *s, size_t len, uint128 seed) { - uint64_t a = Uint128Low64(seed); - uint64_t b = Uint128High64(seed); +uint128_t CityMurmur(const char *s, size_t len, uint128_t seed) { + uint64_t a = uint128_lo64(seed); + uint64_t b = uint128_hi64(seed); uint64_t c = 0; uint64_t d = 0; signed long l = len - 16; @@ -452,10 +447,10 @@ static uint128 CityMurmur(const char *s, size_t len, uint128 seed) { } a = HashLen16(a, c); b = HashLen16(d, b); - return uint128(a ^ b, HashLen16(b, a)); + return uint128( a ^ b, HashLen16(b, a) ); } -uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { +uint128_t CityHash128WithSeed(const char *s, size_t len, uint128_t seed) { if (len < 128) { return CityMurmur(s, len, seed); } @@ -463,8 +458,8 @@ uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { // We expect len >= 128 to be the common case. Keep 56 bytes of state: // v, w, x, y, and z. pair v, w; - uint64_t x = Uint128Low64(seed); - uint64_t y = Uint128High64(seed); + uint64_t x = uint128_lo64(seed); + uint64_t y = uint128_hi64(seed); uint64_t z = len * k1; v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s); v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8); @@ -514,15 +509,13 @@ uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { // different 56-byte-to-8-byte hashes to get a 16-byte final result. x = HashLen16(x, v.first); y = HashLen16(y + z, w.first); - return uint128(HashLen16(x + v.second, w.second) + y, - HashLen16(x + w.second, y + v.second)); + return uint128( HashLen16(x + v.second, w.second) + y, HashLen16(x + w.second, y + v.second) ); } -uint128 city_hash128(const char *s, size_t len) { +uint128_t city_hash128(const char *s, size_t len) { return len >= 16 ? - CityHash128WithSeed(s + 16, len - 16, - uint128(Fetch64(s), Fetch64(s + 8) + k0)) : - CityHash128WithSeed(s, len, uint128(k0, k1)); + CityHash128WithSeed( s + 16, len - 16, uint128( Fetch64(s), Fetch64(s + 8) + k0 ) ) : + CityHash128WithSeed( s, len, uint128( k0, k1 ) ); } //#ifdef __SSE4_2__ @@ -640,26 +633,25 @@ array city_hash_crc_256(const char *s, size_t len) return buf; } -uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) { +uint128_t CityHashCrc128WithSeed(const char *s, size_t len, uint128_t seed) { if (len <= 900) { return CityHash128WithSeed(s, len, seed); } else { uint64_t result[4]; CityHashCrc256(s, len, result); - uint64_t u = Uint128High64(seed) + result[0]; - uint64_t v = Uint128Low64(seed) + result[1]; - return uint128(HashLen16(u, v + result[2]), - HashLen16(Rotate(v, 32), u * k0 + result[3])); + uint64_t u = uint128_hi64(seed) + result[0]; + uint64_t v = uint128_lo64(seed) + result[1]; + return uint128( HashLen16(u, v + result[2]), HashLen16(Rotate(v, 32), u * k0 + result[3]) ); } } -uint128 city_hash_crc_128(const char *s, size_t len) { +uint128_t city_hash_crc_128(const char *s, size_t len) { if (len <= 900) { return city_hash128(s, len); } else { uint64_t result[4]; CityHashCrc256(s, len, result); - return uint128(result[2], result[3]); + return uint128( result[2], result[3] ); } } diff --git a/src/crypto/elliptic_common.cpp b/src/crypto/elliptic_common.cpp index 13bf256..56eeebc 100644 --- a/src/crypto/elliptic_common.cpp +++ b/src/crypto/elliptic_common.cpp @@ -19,7 +19,7 @@ namespace fc { namespace ecc { namespace detail { - typedef fc::array chr37; + typedef std::array chr37; fc::sha256 _left( const fc::sha512& v ) { @@ -52,10 +52,10 @@ namespace fc { namespace ecc { return result; } - static chr37 _derive_message( char first, const char* key32, int i ) + static chr37 _derive_message( unsigned char first, const unsigned char* key32, int i ) { chr37 result; - unsigned char* dest = (unsigned char*) result.begin(); + unsigned char* dest = result.begin(); *dest++ = first; memcpy( dest, key32, 32 ); dest += 32; _put( &dest, i ); @@ -69,7 +69,7 @@ namespace fc { namespace ecc { static chr37 _derive_message( const private_key_secret& key, int i ) { - return _derive_message( 0, key.data(), i ); + return _derive_message( 0, (unsigned char*) key.data(), i ); } const ec_group& get_curve() @@ -139,40 +139,40 @@ namespace fc { namespace ecc { std::string public_key::to_base58( const public_key_data &key ) { - sha256 check = sha256::hash(key.data, sizeof(key)); + sha256 check = sha256::hash((char*) key.data(), sizeof(key)); static_assert(sizeof(key) + 4 == 37, "Elliptic public key size (or its hash) is incorrect"); - array data; - memcpy(data.data, key.begin(), key.size()); + detail::chr37 data; + memcpy(data.data(), key.begin(), key.size()); memcpy(data.begin() + key.size(), (const char*)check._hash, 4); - return fc::to_base58(data.begin(), data.size()); + return fc::to_base58((char*) data.begin(), data.size()); } public_key public_key::from_base58( const std::string& b58 ) { - array data; + detail::chr37 data; size_t s = fc::from_base58(b58, (char*)&data, sizeof(data) ); FC_ASSERT( s == sizeof(data) ); public_key_data key; - sha256 check = sha256::hash(data.data, sizeof(key)); - FC_ASSERT( memcmp( (char*)check._hash, data.data + sizeof(key), 4 ) == 0 ); - memcpy( (char*)key.data, data.data, sizeof(key) ); + sha256 check = sha256::hash((char*) data.data(), sizeof(key)); + FC_ASSERT( memcmp( (char*)check._hash, data.data() + key.size(), 4 ) == 0 ); + memcpy( (char*)key.data(), data.data(), key.size() ); return from_key_data(key); } unsigned int public_key::fingerprint() const { public_key_data key = serialize(); - ripemd160 hash = ripemd160::hash( sha256::hash( key.begin(), key.size() ) ); + ripemd160 hash = ripemd160::hash( sha256::hash( (char*) key.begin(), key.size() ) ); unsigned char* fp = (unsigned char*) hash._hash; return (fp[0] << 24) | (fp[1] << 16) | (fp[2] << 8) | fp[3]; } bool public_key::is_canonical( const compact_signature& c ) { - return !(c.data[1] & 0x80) - && !(c.data[1] == 0 && !(c.data[2] & 0x80)) - && !(c.data[33] & 0x80) - && !(c.data[33] == 0 && !(c.data[34] & 0x80)); + return !(c[1] & 0x80) + && !(c[1] == 0 && !(c[2] & 0x80)) + && !(c[33] & 0x80) + && !(c[33] == 0 && !(c[34] & 0x80)); } private_key private_key::generate_from_seed( const fc::sha256& seed, const fc::sha256& offset ) @@ -234,7 +234,7 @@ namespace fc { namespace ecc { size_t buf_len = key.size() + 4; char *buffer = (char*)alloca(buf_len); memcpy( buffer, key.begin(), key.size() ); - fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( key.begin(), key.size() )); + fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( (char*) key.begin(), key.size() )); memcpy( buffer + key.size(), double_hash.data(), 4 ); return fc::to_base58( buffer, buf_len ); } @@ -311,7 +311,7 @@ namespace fc { namespace ecc { { const detail::chr37 data = detail::_derive_message( get_public_key().serialize(), i ); hmac_sha512 mac; - fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() ); + fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.begin(), data.size() ); return private_derive_rest( l, i ); } @@ -320,7 +320,7 @@ namespace fc { namespace ecc { hmac_sha512 mac; private_key_secret key = get_secret(); const detail::chr37 data = detail::_derive_message( key, i ); - fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() ); + fc::sha512 l = mac.digest( c.data(), c.data_size(), (char*) data.begin(), data.size() ); return private_derive_rest( l, i ); } diff --git a/src/crypto/elliptic_secp256k1.cpp b/src/crypto/elliptic_secp256k1.cpp index b80ace3..7f8d841 100644 --- a/src/crypto/elliptic_secp256k1.cpp +++ b/src/crypto/elliptic_secp256k1.cpp @@ -41,6 +41,7 @@ namespace fc { namespace ecc { public_key_impl() BOOST_NOEXCEPT { _init_lib(); + memset( _key.data(), 0, _key.size() ); } public_key_impl( const public_key_impl& cpy ) BOOST_NOEXCEPT @@ -52,16 +53,16 @@ namespace fc { namespace ecc { public_key_data _key; }; - typedef fc::array chr37; + typedef std::array chr37; chr37 _derive_message( const public_key_data& key, int i ); fc::sha256 _left( const fc::sha512& v ); fc::sha256 _right( const fc::sha512& v ); const ec_group& get_curve(); const private_key_secret& get_curve_order(); const private_key_secret& get_half_curve_order(); - } + } // detail - static const public_key_data empty_pub; + static const public_key_data empty_pub = detail::public_key_impl()._key; static const private_key_secret empty_priv; fc::sha512 private_key::get_shared_secret( const public_key& other )const @@ -69,8 +70,8 @@ namespace fc { namespace ecc { FC_ASSERT( my->_key != empty_priv ); FC_ASSERT( other.my->_key != empty_pub ); public_key_data pub(other.my->_key); - FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) pub.begin(), pub.size(), (unsigned char*) my->_key.data() ) ); - return fc::sha512::hash( pub.begin() + 1, pub.size() - 1 ); + FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), pub.begin(), pub.size(), (unsigned char*) my->_key.data() ) ); + return fc::sha512::hash( (char*) pub.begin() + 1, pub.size() - 1 ); } @@ -104,7 +105,7 @@ namespace fc { namespace ecc { FC_ASSERT( my->_key != empty_pub ); public_key_data new_key; memcpy( new_key.begin(), my->_key.begin(), new_key.size() ); - FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) new_key.begin(), new_key.size(), (unsigned char*) digest.data() ) ); + FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), new_key.begin(), new_key.size(), (unsigned char*) digest.data() ) ); return public_key( new_key ); } @@ -126,22 +127,22 @@ namespace fc { namespace ecc { public_key_point_data dat; unsigned int pk_len = my->_key.size(); memcpy( dat.begin(), my->_key.begin(), pk_len ); - FC_ASSERT( secp256k1_ec_pubkey_decompress( detail::_get_context(), (unsigned char *) dat.begin(), (int*) &pk_len ) ); + FC_ASSERT( secp256k1_ec_pubkey_decompress( detail::_get_context(), dat.begin(), (int*) &pk_len ) ); FC_ASSERT( pk_len == dat.size() ); return dat; } public_key::public_key( const public_key_point_data& dat ) { - const char* front = &dat.data[0]; + const unsigned char* front = dat.data(); if( *front == 0 ){} else { EC_KEY *key = EC_KEY_new_by_curve_name( NID_secp256k1 ); - key = o2i_ECPublicKey( &key, (const unsigned char**)&front, sizeof(dat) ); + key = o2i_ECPublicKey( &key, &front, sizeof(dat) ); FC_ASSERT( key ); EC_KEY_set_conv_form( key, POINT_CONVERSION_COMPRESSED ); - unsigned char* buffer = (unsigned char*) my->_key.begin(); + unsigned char* buffer = my->_key.begin(); i2o_ECPublicKey( key, &buffer ); // FIXME: questionable memory handling EC_KEY_free( key ); } @@ -154,7 +155,7 @@ namespace fc { namespace ecc { public_key::public_key( const compact_signature& c, const fc::sha256& digest, bool check_canonical ) { - int nV = c.data[0]; + int nV = c[0]; if (nV<27 || nV>=35) FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" ); @@ -164,7 +165,7 @@ namespace fc { namespace ecc { } unsigned int pk_len; - FC_ASSERT( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) digest.data(), (unsigned char*) c.begin() + 1, (unsigned char*) my->_key.begin(), (int*) &pk_len, 1, (*c.begin() - 27) & 3 ) ); + FC_ASSERT( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) digest.data(), c.begin() + 1, my->_key.begin(), (int*) &pk_len, 1, (*c.begin() - 27) & 3 ) ); FC_ASSERT( pk_len == my->_key.size() ); } @@ -180,7 +181,7 @@ namespace fc { namespace ecc { fc::sha512 l = mac.digest( c.data(), c.data_size(), data.begin(), data.size() ); fc::sha256 left = detail::_left(l); FC_ASSERT( left < detail::get_curve_order() ); - FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) key.begin(), key.size(), (unsigned char*) left.data() ) > 0 ); + FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), key.begin(), key.size(), (unsigned char*) left.data() ) > 0 ); // FIXME: check validity - if left + key == infinity then invalid extended_public_key result( key, detail::_right(l), i, fingerprint(), depth + 1 ); return result; @@ -204,7 +205,7 @@ namespace fc { namespace ecc { commitment_type blind( const blind_factor_type& blind, uint64_t value ) { commitment_type result; - FC_ASSERT( secp256k1_pedersen_commit( detail::_get_context(), (unsigned char*)&result, (unsigned char*)&blind, value ) ); + FC_ASSERT( secp256k1_pedersen_commit( detail::_get_context(), result.data(), (unsigned char*) blind.data(), value ) ); return result; } @@ -212,8 +213,8 @@ namespace fc { namespace ecc { { blind_factor_type result; std::vector blinds(blinds_in.size()); - for( uint32_t i = 0; i < blinds_in.size(); ++i ) blinds[i] = (const unsigned char*)&blinds_in[i]; - FC_ASSERT( secp256k1_pedersen_blind_sum( detail::_get_context(), (unsigned char*)&result, blinds.data(), blinds_in.size(), non_neg ) ); + for( uint32_t i = 0; i < blinds_in.size(); ++i ) blinds[i] = (unsigned char*) blinds_in[i].data(); + FC_ASSERT( secp256k1_pedersen_blind_sum( detail::_get_context(), (unsigned char*) result.data(), blinds.data(), blinds_in.size(), non_neg ) ); return result; } @@ -221,16 +222,16 @@ namespace fc { namespace ecc { bool verify_sum( const std::vector& commits_in, const std::vector& neg_commits_in, int64_t excess ) { std::vector commits(commits_in.size()); - for( uint32_t i = 0; i < commits_in.size(); ++i ) commits[i] = (const unsigned char*)&commits_in[i]; + for( uint32_t i = 0; i < commits_in.size(); ++i ) commits[i] = commits_in[i].data(); std::vector neg_commits(neg_commits_in.size()); - for( uint32_t i = 0; i < neg_commits_in.size(); ++i ) neg_commits[i] = (const unsigned char*)&neg_commits_in[i]; + for( uint32_t i = 0; i < neg_commits_in.size(); ++i ) neg_commits[i] = neg_commits_in[i].data(); return secp256k1_pedersen_verify_tally( detail::_get_context(), commits.data(), commits.size(), neg_commits.data(), neg_commits.size(), excess ); } bool verify_range( uint64_t& min_val, uint64_t& max_val, const commitment_type& commit, const std::vector& proof ) { - return secp256k1_rangeproof_verify( detail::_get_context(), &min_val, &max_val, (const unsigned char*)&commit, (const unsigned char*)proof.data(), proof.size() ); + return secp256k1_rangeproof_verify( detail::_get_context(), &min_val, &max_val, commit.data(), (const unsigned char*)proof.data(), proof.size() ); } std::vector range_proof_sign( uint64_t min_value, @@ -245,12 +246,12 @@ namespace fc { namespace ecc { int proof_len = 5134; std::vector proof(proof_len); - FC_ASSERT( secp256k1_rangeproof_sign( detail::_get_context(), - (unsigned char*)proof.data(), - &proof_len, min_value, - (const unsigned char*)&commit, - (const unsigned char*)&commit_blind, - (const unsigned char*)&nonce, + FC_ASSERT( secp256k1_rangeproof_sign( detail::_get_context(), + (unsigned char*)proof.data(), + &proof_len, min_value, + commit.data(), + (unsigned char*) commit_blind.data(), + (unsigned char*) nonce.data(), base10_exp, min_bits, actual_value ) ); proof.resize(proof_len); return proof; @@ -269,14 +270,14 @@ namespace fc { namespace ecc { char msg[4096]; int mlen = 0; FC_ASSERT( secp256k1_rangeproof_rewind( detail::_get_context(), - (unsigned char*)&blind_out, + (unsigned char*) blind_out.data(), &value_out, - (unsigned char*)msg, + (unsigned char*) msg, &mlen, - (const unsigned char*)&nonce, + (unsigned char*) nonce.data(), &min_val, &max_val, - (const unsigned char*)&commit, + commit.data(), (const unsigned char*)proof.data(), proof.size() ) ); diff --git a/src/exception.cpp b/src/exception.cpp index b957f2f..d3fadbb 100644 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -8,6 +8,25 @@ namespace fc { + FC_IMPLEMENT_EXCEPTION( timeout_exception, timeout_exception_code, "Timeout" ) + FC_IMPLEMENT_EXCEPTION( file_not_found_exception, file_not_found_exception_code, "File Not Found" ) + FC_IMPLEMENT_EXCEPTION( parse_error_exception, parse_error_exception_code, "Parse Error" ) + FC_IMPLEMENT_EXCEPTION( invalid_arg_exception, invalid_arg_exception_code, "Invalid Argument" ) + FC_IMPLEMENT_EXCEPTION( key_not_found_exception, key_not_found_exception_code, "Key Not Found" ) + FC_IMPLEMENT_EXCEPTION( bad_cast_exception, bad_cast_exception_code, "Bad Cast" ) + FC_IMPLEMENT_EXCEPTION( out_of_range_exception, out_of_range_exception_code, "Out of Range" ) + FC_IMPLEMENT_EXCEPTION( method_not_found_exception, method_not_found_exception_code, "Method Not Found" ); + FC_IMPLEMENT_EXCEPTION( invalid_operation_exception, invalid_operation_exception_code, "Invalid Operation" ) + FC_IMPLEMENT_EXCEPTION( unknown_host_exception, unknown_host_exception_code, "Unknown Host" ) + FC_IMPLEMENT_EXCEPTION( canceled_exception, canceled_exception_code, "Canceled" ) + FC_IMPLEMENT_EXCEPTION( assert_exception, assert_exception_code, "Assert Exception" ) + FC_IMPLEMENT_EXCEPTION( eof_exception, eof_exception_code, "End Of File" ) + FC_IMPLEMENT_EXCEPTION( null_optional, null_optional_code, "null optional" ) + FC_IMPLEMENT_EXCEPTION( aes_exception, aes_error_code, "AES error" ) + FC_IMPLEMENT_EXCEPTION( overflow_exception, overflow_code, "Integer Overflow" ) + FC_IMPLEMENT_EXCEPTION( underflow_exception, underflow_code, "Integer Underflow" ) + FC_IMPLEMENT_EXCEPTION( divide_by_zero_exception, divide_by_zero_code, "Integer Divide By Zero" ) + FC_REGISTER_EXCEPTIONS( (timeout_exception) (file_not_found_exception) (parse_error_exception) @@ -77,7 +96,7 @@ namespace fc std::exception_ptr unhandled_exception::get_inner_exception()const { return _inner; } - NO_RETURN void unhandled_exception::dynamic_rethrow_exception()const + [[noreturn]] void unhandled_exception::dynamic_rethrow_exception()const { if( !(_inner == std::exception_ptr()) ) std::rethrow_exception( _inner ); else { fc::exception::dynamic_rethrow_exception(); } @@ -198,7 +217,7 @@ namespace fc return ss.str(); } - void NO_RETURN exception_factory::rethrow( const exception& e )const + [[noreturn]] void exception_factory::rethrow( const exception& e )const { auto itr = _registered_exceptions.find( e.code() ); if( itr != _registered_exceptions.end() ) @@ -210,7 +229,7 @@ namespace fc * the error code. This is used to propagate exception types * across conversions to/from JSON */ - NO_RETURN void exception::dynamic_rethrow_exception()const + [[noreturn]] void exception::dynamic_rethrow_exception()const { exception_factory::instance().rethrow( *this ); } diff --git a/src/io/datastream.cpp b/src/io/datastream.cpp index 69fda0d..5ece65f 100644 --- a/src/io/datastream.cpp +++ b/src/io/datastream.cpp @@ -1,7 +1,7 @@ #include #include -NO_RETURN void fc::detail::throw_datastream_range_error(char const* method, size_t len, int64_t over) +[[noreturn]] void fc::detail::throw_datastream_range_error(char const* method, size_t len, int64_t over) { FC_THROW_EXCEPTION( out_of_range_exception, "${method} datastream of length ${len} over by ${over}", ("method",std::string(method))("len",len)("over",over) ); } diff --git a/src/io/fstream.cpp b/src/io/fstream.cpp index 5ebf790..1e6fffe 100644 --- a/src/io/fstream.cpp +++ b/src/io/fstream.cpp @@ -13,11 +13,11 @@ using namespace std; namespace fc { - class ofstream::impl : public fc::retainable { + class ofstream::impl { public: boost::filesystem::ofstream ofs; }; - class ifstream::impl : public fc::retainable { + class ifstream::impl { public: boost::filesystem::ifstream ifs; }; diff --git a/src/io/iostream.cpp b/src/io/iostream.cpp index c44fc83..c7d364c 100644 --- a/src/io/iostream.cpp +++ b/src/io/iostream.cpp @@ -24,7 +24,7 @@ namespace fc { std::cin.read(&c,1); while( !std::cin.eof() ) { while( write_pos - read_pos > 0xfffff ) { - fc::promise::ptr wr( new fc::promise("cin_buffer::write_ready") ); + fc::promise::ptr wr = fc::promise::create("cin_buffer::write_ready"); write_ready = wr; if( write_pos - read_pos <= 0xfffff ) { wr->wait(); @@ -138,7 +138,7 @@ namespace fc { do { while( !b.eof && (b.write_pos - b.read_pos)==0 ){ // wait for more... - fc::promise::ptr rr( new fc::promise("cin_buffer::read_ready") ); + fc::promise::ptr rr = fc::promise::create("cin_buffer::read_ready"); { // copy read_ready because it is accessed from multiple threads fc::scoped_lock lock( b.read_ready_mutex ); b.read_ready = rr; diff --git a/src/log/file_appender.cpp b/src/log/file_appender.cpp index 6cc1d7e..c2efebf 100644 --- a/src/log/file_appender.cpp +++ b/src/log/file_appender.cpp @@ -13,7 +13,7 @@ namespace fc { - class file_appender::impl : public fc::retainable + class file_appender::impl { public: config cfg; diff --git a/src/log/gelf_appender.cpp b/src/log/gelf_appender.cpp index 2d7f78a..c1828e5 100644 --- a/src/log/gelf_appender.cpp +++ b/src/log/gelf_appender.cpp @@ -20,7 +20,7 @@ namespace fc { - class gelf_appender::impl : public retainable + class gelf_appender::impl { public: config cfg; diff --git a/src/log/logger.cpp b/src/log/logger.cpp index bd31afe..ee2776d 100644 --- a/src/log/logger.cpp +++ b/src/log/logger.cpp @@ -11,7 +11,7 @@ namespace fc { - class logger::impl : public fc::retainable { + class logger::impl { public: impl() :_parent(nullptr),_enabled(true),_additivity(false),_level(log_level::warn){} @@ -28,7 +28,7 @@ namespace fc { logger::logger() :my( new impl() ){} - logger::logger(nullptr_t){} + logger::logger(std::nullptr_t){} logger::logger( const string& name, const logger& parent ) :my( new impl() ) @@ -54,8 +54,8 @@ namespace fc { std::swap(my,l.my); return *this; } - bool operator==( const logger& l, std::nullptr_t ) { return !l.my; } - bool operator!=( const logger& l, std::nullptr_t ) { return l.my; } + bool operator==( const logger& l, std::nullptr_t ) { return !(bool)l.my; } + bool operator!=( const logger& l, std::nullptr_t ) { return (bool)l.my; } bool logger::is_enabled( log_level e )const { return e >= my->_level; @@ -96,7 +96,7 @@ namespace fc { log_level logger::get_log_level()const { return my->_level; } logger& logger::set_log_level(log_level ll) { my->_level = ll; return *this; } - void logger::add_appender( const fc::shared_ptr& a ) + void logger::add_appender( const appender::ptr& a ) { my->_appenders.push_back(a); } void logger::remove_appender( const fc::shared_ptr& a ) @@ -106,7 +106,7 @@ namespace fc { my->_appenders.erase(item); } - std::vector > logger::get_appenders()const + std::vector logger::get_appenders()const { return my->_appenders; } diff --git a/src/network/http/http_server.cpp b/src/network/http/http_server.cpp deleted file mode 100644 index 8a63734..0000000 --- a/src/network/http/http_server.cpp +++ /dev/null @@ -1,207 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - - -namespace fc { namespace http { - - class server::response::impl : public fc::retainable - { - public: - impl( const fc::http::connection_ptr& c, const std::function& cont = std::function() ) - :body_bytes_sent(0),body_length(0),con(c),handle_next_req(cont) - {} - - void send_header() { - //ilog( "sending header..." ); - fc::stringstream ss; - ss << "HTTP/1.1 " << rep.status << " "; - switch( rep.status ) { - case fc::http::reply::OK: ss << "OK\r\n"; break; - case fc::http::reply::RecordCreated: ss << "Record Created\r\n"; break; - case fc::http::reply::NotFound: ss << "Not Found\r\n"; break; - case fc::http::reply::Found: ss << "Found\r\n"; break; - default: ss << "Internal Server Error\r\n"; break; - } - for( uint32_t i = 0; i < rep.headers.size(); ++i ) { - ss << rep.headers[i].key <<": "<get_socket().write( s.c_str(), s.size() ); - } - - http::reply rep; - int64_t body_bytes_sent; - uint64_t body_length; - http::connection_ptr con; - std::function handle_next_req; - }; - - - class server::impl - { - public: - impl(){} - - impl(const fc::ip::endpoint& p ) - { - tcp_serv.set_reuse_address(); - tcp_serv.listen(p); - accept_complete = fc::async([this](){ this->accept_loop(); }, "http_server accept_loop"); - } - - ~impl() - { - try - { - tcp_serv.close(); - if (accept_complete.valid()) - accept_complete.wait(); - } - catch (...) - { - } - - for (fc::future& request_in_progress : requests_in_progress) - { - try - { - request_in_progress.cancel_and_wait(); - } - catch (const fc::exception& e) - { - wlog("Caught exception while canceling http request task: ${error}", ("error", e)); - } - catch (const std::exception& e) - { - wlog("Caught exception while canceling http request task: ${error}", ("error", e.what())); - } - catch (...) - { - wlog("Caught unknown exception while canceling http request task"); - } - } - requests_in_progress.clear(); - } - - void accept_loop() - { - while( !accept_complete.canceled() ) - { - http::connection_ptr con = std::make_shared(); - tcp_serv.accept( con->get_socket() ); - //ilog( "Accept Connection" ); - // clean up futures for any completed requests - for (auto iter = requests_in_progress.begin(); iter != requests_in_progress.end();) - if (!iter->valid() || iter->ready()) - iter = requests_in_progress.erase(iter); - else - ++iter; - requests_in_progress.emplace_back(fc::async([=](){ handle_connection(con, on_req); }, "http_server handle_connection")); - } - } - - void handle_connection( const http::connection_ptr& c, - std::function do_on_req ) - { - try - { - http::server::response rep( fc::shared_ptr( new response::impl(c) ) ); - request req = c->read_request(); - if( do_on_req ) - do_on_req( req, rep ); - c->get_socket().close(); - } - catch ( fc::exception& e ) - { - wlog( "unable to read request ${1}", ("1", e.to_detail_string() ) );//fc::except_str().c_str()); - } - //wlog( "done handle connection" ); - } - - fc::future accept_complete; - std::function on_req; - std::vector > requests_in_progress; - fc::tcp_server tcp_serv; - }; - - - - server::server():my( new impl() ){} - server::server( uint16_t port ) :my( new impl(fc::ip::endpoint( fc::ip::address(),port)) ){} - server::server( server&& s ):my(std::move(s.my)){} - - server& server::operator=(server&& s) { std::swap(my,s.my); return *this; } - - server::~server(){} - - void server::listen( const fc::ip::endpoint& p ) - { - my.reset( new impl(p) ); - } - - fc::ip::endpoint server::get_local_endpoint() const - { - return my->tcp_serv.get_local_endpoint(); - } - - - server::response::response(){} - server::response::response( const server::response& s ):my(s.my){} - server::response::response( server::response&& s ):my(std::move(s.my)){} - server::response::response( const fc::shared_ptr& m ):my(m){} - - server::response& server::response::operator=(const server::response& s) { my = s.my; return *this; } - server::response& server::response::operator=(server::response&& s) { std::swap(my,s.my); return *this; } - - void server::response::add_header( const std::string& key, const std::string& val )const { - my->rep.headers.push_back( fc::http::header( key, val ) ); - } - void server::response::set_status( const http::reply::status_code& s )const { - if( my->body_bytes_sent != 0 ) { - wlog( "Attempt to set status after sending headers" ); - } - my->rep.status = s; - } - void server::response::set_length( uint64_t s )const { - if( my->body_bytes_sent != 0 ) { - wlog( "Attempt to set length after sending headers" ); - } - my->body_length = s; - } - void server::response::write( const char* data, uint64_t len )const { - if( my->body_bytes_sent + len > my->body_length ) { - wlog( "Attempt to send to many bytes.." ); - len = my->body_bytes_sent + len - my->body_length; - } - if( my->body_bytes_sent == 0 ) { - my->send_header(); - } - my->body_bytes_sent += len; - my->con->get_socket().write( data, static_cast(len) ); - if( my->body_bytes_sent == int64_t(my->body_length) ) { - if( false || my->handle_next_req ) { - ilog( "handle next request..." ); - //fc::async( std::function(my->handle_next_req) ); - fc::async( my->handle_next_req, "http_server handle_next_req" ); - } - } - } - - server::response::~response(){} - - void server::on_request( const std::function& cb ) - { - my->on_req = cb; - } - - - - -} } diff --git a/src/network/http/websocket.cpp b/src/network/http/websocket.cpp index 4ffbaec..24ea499 100644 --- a/src/network/http/websocket.cpp +++ b/src/network/http/websocket.cpp @@ -12,7 +12,10 @@ #include #endif +#include #include +#include +#include #include #include #include @@ -145,7 +148,7 @@ namespace fc { namespace http { :_ws_connection(con){ } - ~websocket_connection_impl() + virtual ~websocket_connection_impl() { } @@ -240,10 +243,10 @@ namespace fc { namespace http { wdump(("server")(request_body)); fc::async([current_con, request_body, con] { - std::string response = current_con->on_http(request_body); - idump((response)); - con->set_body( response ); - con->set_status( websocketpp::http::status_code::ok ); + fc::http::reply response = current_con->on_http(request_body); + idump( (response) ); + con->set_body( std::move( response.body_as_string ) ); + con->set_status( websocketpp::http::status_code::value(response.status) ); con->send_http_response(); current_con->closed(); }, "call on_http"); @@ -290,8 +293,8 @@ namespace fc { namespace http { if( _server.is_listening() ) _server.stop_listening(); - if ( _connections.size() ) - _closed = new fc::promise(); + if( _connections.size() ) + _closed = promise::create(); auto cpy_con = _connections; for( auto item : cpy_con ) @@ -369,8 +372,8 @@ namespace fc { namespace http { wdump(("server")(con->get_request_body())); auto response = current_con->on_http( con->get_request_body() ); idump((response)); - con->set_body( response ); - con->set_status( websocketpp::http::status_code::ok ); + con->set_body( std::move( response.body_as_string ) ); + con->set_status( websocketpp::http::status_code::value( response.status ) ); } catch ( const fc::exception& e ) { edump((e.to_detail_string())); @@ -429,16 +432,16 @@ namespace fc { namespace http { typedef websocket_tls_client_type::connection_ptr websocket_tls_client_connection_type; using websocketpp::connection_hdl; - class websocket_client_impl + template + class generic_websocket_client_impl { public: - typedef websocket_client_type::message_ptr message_ptr; - - websocket_client_impl() + generic_websocket_client_impl() :_client_thread( fc::thread::current() ) { _client.clear_access_channels( websocketpp::log::alevel::all ); - _client.set_message_handler( [&]( connection_hdl hdl, message_ptr msg ){ + _client.set_message_handler( [&]( connection_hdl hdl, + typename websocketpp::client::message_ptr msg ){ _client_thread.async( [&](){ wdump((msg->get_payload())); auto received = msg->get_payload(); @@ -465,74 +468,38 @@ namespace fc { namespace http { _client.init_asio( &fc::asio::default_io_service() ); } - ~websocket_client_impl() + virtual ~generic_websocket_client_impl() { - if(_connection ) + if( _connection ) { _connection->close(0, "client closed"); _connection.reset(); - _closed->wait(); } + if( _closed ) + _closed->wait(); } fc::promise::ptr _connected; fc::promise::ptr _closed; fc::thread& _client_thread; - websocket_client_type _client; + websocketpp::client _client; websocket_connection_ptr _connection; std::string _uri; fc::optional _hdl; }; + class websocket_client_impl : public generic_websocket_client_impl + {}; - - class websocket_tls_client_impl + class websocket_tls_client_impl : public generic_websocket_client_impl { public: - typedef websocket_tls_client_type::message_ptr message_ptr; - websocket_tls_client_impl( const std::string& ca_filename ) - :_client_thread( fc::thread::current() ) + : generic_websocket_client_impl() { // ca_filename has special values: // "_none" disables cert checking (potentially insecure!) // "_default" uses default CA's provided by OS - _client.clear_access_channels( websocketpp::log::alevel::all ); - _client.set_message_handler( [&]( connection_hdl hdl, message_ptr msg ){ - _client_thread.async( [&](){ - wdump((msg->get_payload())); - _connection->on_message( msg->get_payload() ); - }).wait(); - }); - _client.set_close_handler( [=]( connection_hdl hdl ){ - if( _connection ) - { - try { - _client_thread.async( [&](){ - wlog(". ${p}", ("p",uint64_t(_connection.get()))); - if( !_shutting_down && !_closed && _connection ) - _connection->closed(); - _connection.reset(); - } ).wait(); - } catch ( const fc::exception& e ) - { - if( _closed ) _closed->set_exception( e.dynamic_copy_exception() ); - } - if( _closed ) _closed->set_value(); - } - }); - _client.set_fail_handler( [=]( connection_hdl hdl ){ - elog( "." ); - auto con = _client.get_con_from_hdl(hdl); - auto message = con->get_ec().message(); - if( _connection ) - _client_thread.async( [&](){ if( _connection ) _connection->closed(); _connection.reset(); } ).wait(); - if( _connected && !_connected->ready() ) - _connected->set_exception( exception_ptr( new FC_EXCEPTION( exception, "${message}", ("message",message)) ) ); - if( _closed ) - _closed->set_value(); - }); - // // We need ca_filename to be copied into the closure, as the referenced object might be destroyed by the caller by the time // tls_init_handler() is called. According to [1], capture-by-value results in the desired behavior (i.e. creation of @@ -565,18 +532,8 @@ namespace fc { namespace http { return ctx; }); - _client.init_asio( &fc::asio::default_io_service() ); - } - ~websocket_tls_client_impl() - { - if(_connection ) - { - wlog("."); - _shutting_down = true; - _connection->close(0, "client closed"); - _closed->wait(); - } } + virtual ~websocket_tls_client_impl() {} std::string get_host()const { @@ -596,13 +553,6 @@ namespace fc { namespace http { ctx->set_verify_callback( boost::asio::ssl::rfc2818_verification( get_host() ) ); } - bool _shutting_down = false; - fc::promise::ptr _connected; - fc::promise::ptr _closed; - fc::thread& _client_thread; - websocket_tls_client_type _client; - websocket_connection_ptr _connection; - std::string _uri; }; @@ -691,13 +641,13 @@ namespace fc { namespace http { websocketpp::lib::error_code ec; my->_uri = uri; - my->_connected = fc::promise::ptr( new fc::promise("websocket::connect") ); + my->_connected = promise::create("websocket::connect"); my->_client.set_open_handler( [=]( websocketpp::connection_hdl hdl ){ my->_hdl = hdl; auto con = my->_client.get_con_from_hdl(hdl); my->_connection = std::make_shared>( con ); - my->_closed = fc::promise::ptr( new fc::promise("websocket::closed") ); + my->_closed = promise::create("websocket::closed"); my->_connected->set_value(); }); @@ -721,12 +671,12 @@ namespace fc { namespace http { websocketpp::lib::error_code ec; smy->_uri = uri; - smy->_connected = fc::promise::ptr( new fc::promise("websocket::connect") ); + smy->_connected = promise::create("websocket::connect"); smy->_client.set_open_handler( [=]( websocketpp::connection_hdl hdl ){ auto con = smy->_client.get_con_from_hdl(hdl); smy->_connection = std::make_shared>( con ); - smy->_closed = fc::promise::ptr( new fc::promise("websocket::closed") ); + smy->_closed = promise::create("websocket::closed"); smy->_connected->set_value(); }); @@ -761,12 +711,12 @@ namespace fc { namespace http { // wlog( "connecting to ${uri}", ("uri",uri)); websocketpp::lib::error_code ec; - my->_connected = fc::promise::ptr( new fc::promise("websocket::connect") ); + my->_connected = promise::create("websocket::connect"); my->_client.set_open_handler( [=]( websocketpp::connection_hdl hdl ){ auto con = my->_client.get_con_from_hdl(hdl); my->_connection = std::make_shared>( con ); - my->_closed = fc::promise::ptr( new fc::promise("websocket::closed") ); + my->_closed = promise::create("websocket::closed"); my->_connected->set_value(); }); diff --git a/src/network/rate_limiting.cpp b/src/network/rate_limiting.cpp index ab7464e..38b8618 100644 --- a/src/network/rate_limiting.cpp +++ b/src/network/rate_limiting.cpp @@ -284,7 +284,7 @@ namespace fc size_t bytes_read; if (_download_bytes_per_second) { - promise::ptr completion_promise(new promise("rate_limiting_group_impl::readsome")); + promise::ptr completion_promise = promise::create("rate_limiting_group_impl::readsome"); rate_limited_tcp_read_operation read_operation(socket, buffer, length, offset, completion_promise); _read_operations_for_next_iteration.push_back(&read_operation); @@ -330,7 +330,7 @@ namespace fc size_t bytes_written; if (_upload_bytes_per_second) { - promise::ptr completion_promise(new promise("rate_limiting_group_impl::writesome")); + promise::ptr completion_promise = promise::create("rate_limiting_group_impl::writesome"); rate_limited_tcp_write_operation write_operation(socket, buffer, length, offset, completion_promise); _write_operations_for_next_iteration.push_back(&write_operation); @@ -367,7 +367,7 @@ namespace fc process_pending_operations(_last_read_iteration_time, _download_bytes_per_second, _read_operations_in_progress, _read_operations_for_next_iteration, _read_tokens, _unused_read_tokens); - _new_read_operation_available_promise = new promise("rate_limiting_group_impl::process_pending_reads"); + _new_read_operation_available_promise = promise::create("rate_limiting_group_impl::process_pending_reads"); try { if (_read_operations_in_progress.empty()) @@ -388,7 +388,7 @@ namespace fc process_pending_operations(_last_write_iteration_time, _upload_bytes_per_second, _write_operations_in_progress, _write_operations_for_next_iteration, _write_tokens, _unused_write_tokens); - _new_write_operation_available_promise = new promise("rate_limiting_group_impl::process_pending_writes"); + _new_write_operation_available_promise = promise::create("rate_limiting_group_impl::process_pending_writes"); try { if (_write_operations_in_progress.empty()) diff --git a/src/network/udp_socket.cpp b/src/network/udp_socket.cpp index 514e148..66eb96d 100644 --- a/src/network/udp_socket.cpp +++ b/src/network/udp_socket.cpp @@ -6,7 +6,7 @@ namespace fc { - class udp_socket::impl : public fc::retainable { + class udp_socket::impl { public: impl():_sock( fc::asio::default_io_service() ){} ~impl(){ @@ -56,7 +56,7 @@ namespace fc { throw; } - promise::ptr completion_promise(new promise("udp_socket::send_to")); + promise::ptr completion_promise = promise::create("udp_socket::send_to"); my->_sock.async_send_to( boost::asio::buffer(buffer, length), to_asio_ep(to), asio::detail::read_write_handler(completion_promise) ); @@ -76,7 +76,7 @@ namespace fc { throw; } - promise::ptr completion_promise(new promise("udp_socket::send_to")); + promise::ptr completion_promise = promise::create("udp_socket::send_to"); my->_sock.async_send_to( boost::asio::buffer(buffer.get(), length), to_asio_ep(to), asio::detail::read_write_handler_with_buffer(completion_promise, buffer) ); @@ -111,7 +111,7 @@ namespace fc { } boost::asio::ip::udp::endpoint boost_from_endpoint; - promise::ptr completion_promise(new promise("udp_socket::receive_from")); + promise::ptr completion_promise = promise::create("udp_socket::receive_from"); my->_sock.async_receive_from( boost::asio::buffer(receive_buffer.get(), receive_buffer_length), boost_from_endpoint, asio::detail::read_write_handler_with_buffer(completion_promise, receive_buffer) ); @@ -137,7 +137,7 @@ namespace fc { } boost::asio::ip::udp::endpoint boost_from_endpoint; - promise::ptr completion_promise(new promise("udp_socket::receive_from")); + promise::ptr completion_promise = promise::create("udp_socket::receive_from"); my->_sock.async_receive_from( boost::asio::buffer(receive_buffer, receive_buffer_length), boost_from_endpoint, asio::detail::read_write_handler(completion_promise) ); size_t bytes_read = completion_promise->wait(); diff --git a/src/popcount.cpp b/src/popcount.cpp new file mode 100644 index 0000000..d4b5bc7 --- /dev/null +++ b/src/popcount.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019 BitShares Blockchain Foundation, and contributors. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +namespace fc { + +#if _MSC_VER || __GNUC__ || __clang__ +#else +uint8_t popcount( uint64_t v ) +{ + // Public Domain code taken from http://graphics.stanford.edu/~seander/bithacks.html + uint8_t c; + static const int S[] = {1, 2, 4, 8, 16, 32}; + static const uint64_t B[] = {0x5555555555555555, 0x3333333333333333, 0x0F0F0F0F0F0F0F0F, + 0x00FF00FF00FF00FF, 0x0000FFFF0000FFFF, 0x00000000FFFFFFFF }; + + c = v - ((v >> 1) & B[0]); + c = ((c >> S[1]) & B[1]) + (c & B[1]); + c = ((c >> S[2]) + c) & B[2]; + c = ((c >> S[3]) + c) & B[3]; + c = ((c >> S[4]) + c) & B[4]; + return ((c >> S[5]) + c) & B[5]; +} +#endif + +uint8_t popcount( const uint128_t& v ) +{ + return popcount( static_cast(v >> 64) ) + + popcount( static_cast(v & 0xffffffffffffffffULL) ); +} + +} // namespace fc diff --git a/src/real128.cpp b/src/real128.cpp deleted file mode 100644 index f941359..0000000 --- a/src/real128.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include -#include -#include -#include -#include - -namespace fc -{ - uint64_t real128::to_uint64()const - { - return (fixed/ FC_REAL128_PRECISION).to_uint64(); - } - - real128::real128( uint64_t integer ) - { - fixed = uint128(integer) * FC_REAL128_PRECISION; - } - real128& real128::operator += ( const real128& o ) - { - fixed += o.fixed; - return *this; - } - real128& real128::operator -= ( const real128& o ) - { - fixed -= o.fixed; - return *this; - } - - real128& real128::operator /= ( const real128& o ) - { try { - FC_ASSERT( o.fixed > uint128(0), "Divide by Zero" ); - - fc::bigint self(fixed); - fc::bigint other(o.fixed); - self *= FC_REAL128_PRECISION; - self /= other; - fixed = self; - - return *this; - } FC_CAPTURE_AND_RETHROW( (*this)(o) ) } - - real128& real128::operator *= ( const real128& o ) - { try { - fc::bigint self(fixed); - fc::bigint other(o.fixed); - self *= other; - self /= FC_REAL128_PRECISION; - fixed = self; - return *this; - } FC_CAPTURE_AND_RETHROW( (*this)(o) ) } - - - real128::real128( const std::string& ratio_str ) - { - const char* c = ratio_str.c_str(); - int digit = *c - '0'; - if (digit >= 0 && digit <= 9) - { - uint64_t int_part = digit; - ++c; - digit = *c - '0'; - while (digit >= 0 && digit <= 9) - { - int_part = int_part * 10 + digit; - ++c; - digit = *c - '0'; - } - *this = real128(int_part); - } - else - { - // if the string doesn't look like "123.45" or ".45", this code isn't designed to parse it correctly - // in particular, we don't try to handle leading whitespace or '+'/'-' indicators at the beginning - assert(*c == '.'); - fixed = fc::uint128(); - } - - - if (*c == '.') - { - c++; - digit = *c - '0'; - if (digit >= 0 && digit <= 9) - { - int64_t frac_part = digit; - int64_t frac_magnitude = 10; - ++c; - digit = *c - '0'; - while (digit >= 0 && digit <= 9) - { - frac_part = frac_part * 10 + digit; - frac_magnitude *= 10; - ++c; - digit = *c - '0'; - } - *this += real128( frac_part ) / real128( frac_magnitude ); - } - } - } - real128::operator std::string()const - { - std::stringstream ss; - ss << std::string(fixed / FC_REAL128_PRECISION); - ss << '.'; - auto frac = (fixed % FC_REAL128_PRECISION) + FC_REAL128_PRECISION; - ss << std::string( frac ).substr(1); - - auto number = ss.str(); - while( number.back() == '0' ) number.pop_back(); - - return number; - } - - real128 real128::from_fixed( const uint128& fixed ) - { - real128 result; - result.fixed = fixed; - return result; - } - - void to_variant( const real128& var, variant& vo, uint32_t max_depth ) - { - vo = std::string(var); - } - void from_variant( const variant& var, real128& vo, uint32_t max_depth ) - { - vo = real128(var.as_string()); - } - -} // namespace fc diff --git a/src/rpc/cli.cpp b/src/rpc/cli.cpp index 7f324dc..7694e2f 100644 --- a/src/rpc/cli.cpp +++ b/src/rpc/cli.cpp @@ -326,6 +326,15 @@ void cli::getline( const std::string& prompt, std::string& line) FC_THROW_EXCEPTION( fc::eof_exception, "" ); line = line_read; // we don't need here to add line in editline's history, cause it will be doubled + if (cli_check_secret(line_read)) { + free(line_read); + el_no_echo = 1; + line_read = readline("Enter password: "); + el_no_echo = 0; + if( line_read == nullptr ) + FC_THROW_EXCEPTION( fc::eof_exception, "" ); + line = line + ' ' + line_read; + } free(line_read); }).wait(); } diff --git a/src/rpc/http_api.cpp b/src/rpc/http_api.cpp deleted file mode 100644 index b8a299a..0000000 --- a/src/rpc/http_api.cpp +++ /dev/null @@ -1,141 +0,0 @@ - -#include - -namespace fc { namespace rpc { - -http_api_connection::~http_api_connection() -{ -} - -http_api_connection::http_api_connection(uint32_t max_depth) -:api_connection(max_depth) -{ - _rpc_state.add_method( "call", [this]( const variants& args ) -> variant - { - // TODO: This logic is duplicated between http_api_connection and websocket_api_connection - // it should be consolidated into one place instead of copy-pasted - FC_ASSERT( args.size() == 3 && args[2].is_array() ); - api_id_type api_id; - if( args[0].is_string() ) - { - variant subresult = this->receive_call( 1, args[0].as_string() ); - api_id = subresult.as_uint64(); - } - else - api_id = args[0].as_uint64(); - - return this->receive_call( - api_id, - args[1].as_string(), - args[2].get_array() ); - } ); - - _rpc_state.add_method( "notice", [this]( const variants& args ) -> variant - { - FC_ASSERT( args.size() == 2 && args[1].is_array() ); - this->receive_notice( - args[0].as_uint64(), - args[1].get_array() ); - return variant(); - } ); - - _rpc_state.add_method( "callback", [this]( const variants& args ) -> variant - { - FC_ASSERT( args.size() == 2 && args[1].is_array() ); - this->receive_callback( - args[0].as_uint64(), - args[1].get_array() ); - return variant(); - } ); - - _rpc_state.on_unhandled( [&]( const std::string& method_name, const variants& args ) - { - return this->receive_call( 0, method_name, args ); - } ); -} - -variant http_api_connection::send_call( - api_id_type api_id, - string method_name, - variants args /* = variants() */ ) -{ - // HTTP has no way to do this, so do nothing - return variant(); -} - -variant http_api_connection::send_callback( - uint64_t callback_id, - variants args /* = variants() */ ) -{ - // HTTP has no way to do this, so do nothing - return variant(); -} - -void http_api_connection::send_notice( - uint64_t callback_id, - variants args /* = variants() */ ) -{ - // HTTP has no way to do this, so do nothing - return; -} - -void http_api_connection::on_request( const fc::http::request& req, const fc::http::server::response& resp ) -{ - // this must be called by outside HTTP server's on_request method - std::string resp_body; - http::reply::status_code resp_status; - - try - { - resp.add_header( "Content-Type", "application/json" ); - std::string req_body( req.body.begin(), req.body.end() ); - auto var = fc::json::from_string( req_body, fc::json::legacy_parser, _max_conversion_depth ); - const auto& var_obj = var.get_object(); - - if( var_obj.contains( "method" ) ) - { - auto call = var.as(_max_conversion_depth); - try - { - try - { - fc::variant result( _rpc_state.local_call( call.method, call.params ), _max_conversion_depth ); - resp_body = fc::json::to_string( fc::variant( fc::rpc::response( *call.id, result ), _max_conversion_depth), - fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ); - resp_status = http::reply::OK; - } - FC_CAPTURE_AND_RETHROW( (call.method)(call.params) ); - } - catch ( const fc::exception& e ) - { - resp_body = fc::json::to_string( fc::variant( fc::rpc::response( *call.id, error_object{ 1, e.to_detail_string(), fc::variant(e, _max_conversion_depth)} ), _max_conversion_depth), - fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ); - resp_status = http::reply::InternalServerError; - } - } - else - { - resp_status = http::reply::BadRequest; - resp_body = ""; - } - } - catch ( const fc::exception& e ) - { - resp_status = http::reply::InternalServerError; - resp_body = ""; - wdump((e.to_detail_string())); - } - try - { - resp.set_status( resp_status ); - resp.set_length( resp_body.length() ); - resp.write( resp_body.c_str(), resp_body.length() ); - } - catch( const fc::exception& e ) - { - wdump((e.to_detail_string())); - } - return; -} - -} } // namespace fc::rpc diff --git a/src/rpc/state.cpp b/src/rpc/state.cpp index 20823e3..fe2879b 100644 --- a/src/rpc/state.cpp +++ b/src/rpc/state.cpp @@ -29,7 +29,8 @@ variant state::local_call( const string& method_name, const variants& args ) void state::handle_reply( const response& response ) { - auto await = _awaiting.find( response.id ); + FC_ASSERT( response.id, "Response without ID: ${response}", ("response",response) ); + auto await = _awaiting.find( *response.id ); FC_ASSERT( await != _awaiting.end(), "Unknown Response ID: ${id}", ("id",response.id)("response",response) ); if( response.result ) await->second->set_value( *response.result ); @@ -45,10 +46,10 @@ void state::handle_reply( const response& response ) request state::start_remote_call( const string& method_name, variants args ) { request request{ _next_id++, method_name, std::move(args) }; - _awaiting[*request.id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); + _awaiting[*request.id] = fc::promise::create("json_connection::async_call"); return request; } -variant state::wait_for_response( uint64_t request_id ) +variant state::wait_for_response( const variant& request_id ) { auto itr = _awaiting.find(request_id); FC_ASSERT( itr != _awaiting.end() ); diff --git a/src/rpc/websocket_api.cpp b/src/rpc/websocket_api.cpp index d1dd997..0798f8f 100644 --- a/src/rpc/websocket_api.cpp +++ b/src/rpc/websocket_api.cpp @@ -1,5 +1,6 @@ - +#include #include +#include namespace fc { namespace rpc { @@ -49,8 +50,30 @@ websocket_api_connection::websocket_api_connection( const std::shared_ptrreceive_call( 0, method_name, args ); } ); - _connection->on_message_handler( [this]( const std::string& msg ){ on_message(msg,true); } ); - _connection->on_http_handler( [this]( const std::string& msg ){ return on_message(msg,false); } ); + _connection->on_message_handler( [this]( const std::string& msg ){ + response reply = on_message(msg); + if( _connection && ( reply.id || reply.result || reply.error || reply.jsonrpc ) ) + _connection->send_message( fc::json::to_string( reply, fc::json::stringify_large_ints_and_doubles, + _max_conversion_depth ) ); + } ); + _connection->on_http_handler( [this]( const std::string& msg ){ + response reply = on_message(msg); + fc::http::reply result; + if( reply.error ) + { + if( reply.error->code == -32603 ) + result.status = fc::http::reply::InternalServerError; + else if( reply.error->code <= -32600 ) + result.status = fc::http::reply::BadRequest; + } + if( reply.id || reply.result || reply.error || reply.jsonrpc ) + result.body_as_string = fc::json::to_string( reply, fc::json::stringify_large_ints_and_doubles, + _max_conversion_depth ); + else + result.status = fc::http::reply::NoContent; + + return result; + } ); _connection->closed.connect( [this](){ closed(); } ); } @@ -96,81 +119,120 @@ void websocket_api_connection::send_notice( _max_conversion_depth ) ); } -std::string websocket_api_connection::on_message( - const std::string& message, - bool send_message /* = true */ ) +response websocket_api_connection::on_message( const std::string& message ) { + variant var; try { - auto var = fc::json::from_string(message, fc::json::legacy_parser, _max_conversion_depth); - const auto& var_obj = var.get_object(); + var = fc::json::from_string( message, fc::json::legacy_parser, _max_conversion_depth ); + } + catch( const fc::exception& e ) + { + return response( variant(), { -32700, "Invalid JSON message", variant( e, _max_conversion_depth ) }, "2.0" ); + } - if( var_obj.contains( "method" ) ) - { - auto call = var.as(_max_conversion_depth); - exception_ptr optexcept; - try - { - try - { + if( var.is_array() ) + return response( variant(), { -32600, "Batch requests not supported" }, "2.0" ); + + if( !var.is_object() ) + return response( variant(), { -32600, "Invalid JSON request" }, "2.0" ); + + variant_object var_obj = var.get_object(); + + if( var_obj.contains( "id" ) + && !var_obj["id"].is_string() && !var_obj["id"].is_numeric() && !var_obj["id"].is_null() ) + return response( variant(), { -32600, "Invalid id" }, "2.0" ); + + if( var_obj.contains( "method" ) && ( !var_obj["method"].is_string() || var_obj["method"].get_string() == "" ) ) + return response( variant(), { -32600, "Missing or invalid method" }, "2.0" ); + + if( var_obj.contains( "jsonrpc" ) && ( !var_obj["jsonrpc"].is_string() || var_obj["jsonrpc"] != "2.0" ) ) + return response( variant(), { -32600, "Unsupported JSON-RPC version" }, "2.0" ); + + if( var_obj.contains( "method" ) ) + { + if( var_obj.contains( "params" ) && var_obj["params"].is_object() ) + return response( variant(), { -32602, "Named parameters not supported" }, "2.0" ); + + if( var_obj.contains( "params" ) && !var_obj["params"].is_array() ) + return response( variant(), { -32600, "Invalid parameters" }, "2.0" ); + + return on_request( std::move( var ) ); + } + + if( var_obj.contains( "result" ) || var_obj.contains("error") ) + { + if( !var_obj.contains( "id" ) || ( var_obj["id"].is_null() && !var_obj.contains( "jsonrpc" ) ) ) + return response( variant(), { -32600, "Missing or invalid id" }, "2.0" ); + + on_response( std::move( var ) ); + + return response(); + } + + return response( variant(), { -32600, "Missing method or result or error" }, "2.0" ); +} + +void websocket_api_connection::on_response( const variant& var ) +{ + _rpc_state.handle_reply( var.as(_max_conversion_depth) ); +} + +response websocket_api_connection::on_request( const variant& var ) +{ + request call = var.as( _max_conversion_depth ); + if( var.get_object().contains( "id" ) ) + call.id = var.get_object()["id"]; // special handling for null id + + // null ID is valid in JSONRPC-2.0 but signals "no id" in JSONRPC-1.0 + bool has_id = call.id.valid() && ( call.jsonrpc.valid() || !call.id->is_null() ); + + try + { #ifdef LOG_LONG_API - auto start = time_point::now(); + auto start = time_point::now(); #endif - auto result = _rpc_state.local_call( call.method, call.params ); + auto result = _rpc_state.local_call( call.method, call.params ); #ifdef LOG_LONG_API - auto end = time_point::now(); + auto end = time_point::now(); - if( end - start > fc::milliseconds( LOG_LONG_API_MAX_MS ) ) - elog( "API call execution time limit exceeded. method: ${m} params: ${p} time: ${t}", - ("m",call.method)("p",call.params)("t", end - start) ); - else if( end - start > fc::milliseconds( LOG_LONG_API_WARN_MS ) ) - wlog( "API call execution time nearing limit. method: ${m} params: ${p} time: ${t}", - ("m",call.method)("p",call.params)("t", end - start) ); + if( end - start > fc::milliseconds( LOG_LONG_API_MAX_MS ) ) + elog( "API call execution time limit exceeded. method: ${m} params: ${p} time: ${t}", + ("m",call.method)("p",call.params)("t", end - start) ); + else if( end - start > fc::milliseconds( LOG_LONG_API_WARN_MS ) ) + wlog( "API call execution time nearing limit. method: ${m} params: ${p} time: ${t}", + ("m",call.method)("p",call.params)("t", end - start) ); #endif - if( call.id ) - { - auto reply = fc::json::to_string( response( *call.id, result, "2.0" ), - fc::json::stringify_large_ints_and_doubles, - _max_conversion_depth ); - if( send_message && _connection ) - _connection->send_message( reply ); - return reply; - } - } - FC_CAPTURE_AND_RETHROW( (call.method)(call.params) ) - } - catch ( const fc::exception& e ) - { - if( call.id ) - { - optexcept = e.dynamic_copy_exception(); - } - } - if( optexcept ) { - - auto reply = fc::json::to_string( variant(response( *call.id, error_object{ 1, optexcept->to_string(), fc::variant(*optexcept, _max_conversion_depth)}, "2.0" ), _max_conversion_depth ), - fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ); - if( send_message && _connection ) - _connection->send_message( reply ); - - return reply; - } - } - else - { - auto reply = var.as(_max_conversion_depth); - _rpc_state.handle_reply( reply ); - } + if( has_id ) + return response( call.id, result, call.jsonrpc ); + } + catch ( const fc::method_not_found_exception& e ) + { + if( has_id ) + return response( call.id, error_object{ -32601, "Method not found", + variant( (fc::exception) e, _max_conversion_depth ) }, call.jsonrpc ); } catch ( const fc::exception& e ) { - wdump((e.to_detail_string())); - return e.to_detail_string(); + if( has_id ) + return response( call.id, error_object{ e.code(), "Execution error", variant( e, _max_conversion_depth ) }, + call.jsonrpc ); } - return string(); + catch ( const std::exception& e ) + { + elog( "Internal error - ${e}", ("e",e.what()) ); + return response( call.id, error_object{ -32603, "Internal error", variant( e.what(), _max_conversion_depth ) }, + call.jsonrpc ); + } + catch ( ... ) + { + elog( "Internal error while processing RPC request" ); + throw; + } + return response(); } } } // namespace fc::rpc diff --git a/src/shared_ptr.cpp b/src/shared_ptr.cpp deleted file mode 100644 index 9e3a144..0000000 --- a/src/shared_ptr.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include -#include - -namespace fc { - retainable::retainable() - :_ref_count(1) { - static_assert( sizeof(_ref_count) == sizeof(boost::atomic), "failed to reserve enough space" ); - } - - retainable::~retainable() { - assert( _ref_count <= 0 ); - assert( _ref_count == 0 ); - } - void retainable::retain() { - ((boost::atomic*)&_ref_count)->fetch_add(1, boost::memory_order_relaxed ); - } - - void retainable::release() { - boost::atomic_thread_fence(boost::memory_order_acquire); - if( 1 == ((boost::atomic*)&_ref_count)->fetch_sub(1, boost::memory_order_release ) ) { - delete this; - } - } - - int32_t retainable::retain_count()const { - return _ref_count; - } -} diff --git a/src/thread/future.cpp b/src/thread/future.cpp index 2111584..c9dbffa 100644 --- a/src/thread/future.cpp +++ b/src/thread/future.cpp @@ -72,7 +72,7 @@ namespace fc { // See https://github.com/cryptonomex/graphene/issues/597 // - ptr p_this = ptr( this, true ); + ptr p_this = shared_from_this(); try { @@ -123,7 +123,7 @@ namespace fc { blocked_thread = _blocked_thread; } if( blocked_thread ) - blocked_thread->notify(ptr(this,true)); + blocked_thread->notify( shared_from_this() ); } promise_base::~promise_base() { } void promise_base::_set_timeout(){ diff --git a/src/thread/parallel.cpp b/src/thread/parallel.cpp index 10b709e..10ef63b 100644 --- a/src/thread/parallel.cpp +++ b/src/thread/parallel.cpp @@ -158,8 +158,8 @@ namespace fc { serial_valve::ticket_guard::ticket_guard( boost::atomic*>& latch ) { - my_promise = new promise(); - future* my_future = new future( promise::ptr( my_promise, true ) ); + my_promise = promise::create(); + future* my_future = new future( my_promise ); try { do @@ -171,7 +171,7 @@ namespace fc { } catch (...) { - delete my_future; // this takes care of my_promise as well + delete my_future; throw; } } @@ -190,7 +190,7 @@ namespace fc { serial_valve::serial_valve() { - latch.store( new future( promise::ptr( new promise( true ), true ) ) ); + latch.store( new future( promise::create( true ) ) ); } serial_valve::~serial_valve() diff --git a/src/thread/task.cpp b/src/thread/task.cpp index b081872..23027e0 100644 --- a/src/thread/task.cpp +++ b/src/thread/task.cpp @@ -22,7 +22,8 @@ namespace fc { _next(nullptr), _task_specific_data(nullptr), _promise_impl(nullptr), - _functor(func){ + _functor(func), + _retain_count(0){ } void task_base::run() { @@ -101,4 +102,12 @@ namespace fc { } } + void task_base::retain() { + if( _retain_count.fetch_add(1, boost::memory_order_relaxed) == 0 ) + _self = shared_from_this(); + } + void task_base::release() { + if( _retain_count.fetch_sub(1, boost::memory_order_release) == 1 ) + _self.reset(); + } } diff --git a/src/thread/thread.cpp b/src/thread/thread.cpp index 267ac62..00cd1d1 100644 --- a/src/thread/thread.cpp +++ b/src/thread/thread.cpp @@ -72,7 +72,7 @@ namespace fc { } thread::thread( const std::string& name, thread_idle_notifier* notifier ) { - promise::ptr p(new promise("thread start")); + promise::ptr p = promise::create("thread start"); boost::thread* t = new boost::thread( [this,p,name,notifier]() { try { set_thread_name(name.c_str()); // set thread's name for the debugger to display diff --git a/src/thread/thread_d.hpp b/src/thread/thread_d.hpp index b0b6916..77e8fb7 100644 --- a/src/thread/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -335,7 +335,7 @@ namespace fc { if( (*task_itr)->canceled() ) { (*task_itr)->run(); - (*task_itr)->release(); + (*task_itr)->release(); // HERE BE DRAGONS task_itr = task_sch_queue.erase(task_itr); canceled_task = true; continue; @@ -531,10 +531,10 @@ namespace fc { next->_set_active_context( current ); current->cur_task = next; - fc::shared_ptr next_ptr(next); - next_ptr->run(); - current->cur_task = 0; - next_ptr->_set_active_context(0); + next->run(); + current->cur_task = nullptr; + next->_set_active_context(nullptr); + next->release(); // HERE BE DRAGONS current->reinitialize(); } diff --git a/src/uint128.cpp b/src/uint128.cpp deleted file mode 100644 index fa5b795..0000000 --- a/src/uint128.cpp +++ /dev/null @@ -1,398 +0,0 @@ -#include -#include -#include -#include -#include - -#include - -namespace fc -{ - typedef boost::multiprecision::uint128_t m128; - - template - static void divide(const T &numerator, const T &denominator, T "ient, T &remainder) - { - static const int bits = sizeof(T) * 8; - - if(denominator == 0) { - throw std::domain_error("divide by zero"); - } else { - T n = numerator; - T d = denominator; - T x = 1; - T answer = 0; - - - while((n >= d) && (((d >> (bits - 1)) & 1) == 0)) { - x <<= 1; - d <<= 1; - } - - while(x != 0) { - if(n >= d) { - n -= d; - answer |= x; - } - - x >>= 1; - d >>= 1; - } - - quotient = answer; - remainder = n; - } - } - - uint128::uint128(const std::string &sz) - :hi(0), lo(0) - { - // do we have at least one character? - if(!sz.empty()) { - // make some reasonable assumptions - int radix = 10; - bool minus = false; - - std::string::const_iterator i = sz.begin(); - - // check for minus sign, i suppose technically this should only apply - // to base 10, but who says that -0x1 should be invalid? - if(*i == '-') { - ++i; - minus = true; - } - - // check if there is radix changing prefix (0 or 0x) - if(i != sz.end()) { - if(*i == '0') { - radix = 8; - ++i; - if(i != sz.end()) { - if(*i == 'x') { - radix = 16; - ++i; - } - } - } - - while(i != sz.end()) { - unsigned int n = 0; - const char ch = *i; - - if(ch >= 'A' && ch <= 'Z') { - if(((ch - 'A') + 10) < radix) { - n = (ch - 'A') + 10; - } else { - break; - } - } else if(ch >= 'a' && ch <= 'z') { - if(((ch - 'a') + 10) < radix) { - n = (ch - 'a') + 10; - } else { - break; - } - } else if(ch >= '0' && ch <= '9') { - if((ch - '0') < radix) { - n = (ch - '0'); - } else { - break; - } - } else { - /* completely invalid character */ - break; - } - - (*this) *= radix; - (*this) += n; - - ++i; - } - } - - // if this was a negative number, do that two's compliment madness :-P - if(minus) { - *this = -*this; - } - } - } - - - uint128::operator bigint()const - { - boost::endian::big_uint64_buf_t tmp[2]; - tmp[0] = hi; - tmp[1] = lo; - bigint bi( (char*)&tmp, sizeof(tmp) ); - return bi; - } - uint128::uint128( const fc::bigint& bi ) - { - *this = uint128( std::string(bi) ); // TODO: optimize this... - } - - uint128::operator std::string ()const - { - if(*this == 0) { return "0"; } - - // at worst it will be size digits (base 2) so make our buffer - // that plus room for null terminator - static char sz [128 + 1]; - sz[sizeof(sz) - 1] = '\0'; - - uint128 ii(*this); - int i = 128 - 1; - - while (ii != 0 && i) { - - uint128 remainder; - divide(ii, uint128(10), ii, remainder); - sz [--i] = "0123456789abcdefghijklmnopqrstuvwxyz"[remainder.to_integer()]; - } - - return &sz[i]; - } - - - uint128& uint128::operator<<=(const uint128& rhs) - { - if(rhs >= 128) - { - hi = 0; - lo = 0; - } - else - { - unsigned int n = rhs.to_integer(); - const unsigned int halfsize = 128 / 2; - - if(n >= halfsize){ - n -= halfsize; - hi = lo; - lo = 0; - } - - if(n != 0) { - // shift high half - hi <<= n; - - const uint64_t mask(~(uint64_t(-1) >> n)); - - // and add them to high half - hi |= (lo & mask) >> (halfsize - n); - - // and finally shift also low half - lo <<= n; - } - } - - return *this; - } - - uint128 & uint128::operator>>=(const uint128& rhs) - { - if(rhs >= 128) - { - hi = 0; - lo = 0; - } - else - { - unsigned int n = rhs.to_integer(); - const unsigned int halfsize = 128 / 2; - - if(n >= halfsize) { - n -= halfsize; - lo = hi; - hi = 0; - } - - if(n != 0) { - // shift low half - lo >>= n; - - // get lower N bits of high half - const uint64_t mask(~(uint64_t(-1) << n)); - - // and add them to low qword - lo |= (hi & mask) << (halfsize - n); - - // and finally shift also high half - hi >>= n; - } - } - return *this; - } - - uint128& uint128::operator/=(const uint128 &b) - { - auto self = (m128(hi) << 64) + m128(lo); - auto other = (m128(b.hi) << 64) + m128(b.lo); - self /= other; - hi = static_cast(self >> 64); - lo = static_cast((self << 64 ) >> 64); - return *this; - } - - uint128& uint128::operator%=(const uint128 &b) - { - uint128 quotient; - divide(*this, b, quotient, *this); - return *this; - } - - uint128& uint128::operator*=(const uint128 &b) - { - uint64_t a0 = (uint32_t) (this->lo ); - uint64_t a1 = (uint32_t) (this->lo >> 0x20); - uint64_t a2 = (uint32_t) (this->hi ); - uint64_t a3 = (uint32_t) (this->hi >> 0x20); - - uint64_t b0 = (uint32_t) (b.lo ); - uint64_t b1 = (uint32_t) (b.lo >> 0x20); - uint64_t b2 = (uint32_t) (b.hi ); - uint64_t b3 = (uint32_t) (b.hi >> 0x20); - - // (a0 + (a1 << 0x20) + (a2 << 0x40) + (a3 << 0x60)) * - // (b0 + (b1 << 0x20) + (b2 << 0x40) + (b3 << 0x60)) = - // a0 * b0 - // - // (a1 * b0 + a0 * b1) << 0x20 - // (a2 * b0 + a1 * b1 + a0 * b2) << 0x40 - // (a3 * b0 + a2 * b1 + a1 * b2 + a0 * b3) << 0x60 - // - // all other cross terms are << 0x80 or higher, thus do not appear in result - - this->hi = 0; - this->lo = a3*b0; - (*this) += a2*b1; - (*this) += a1*b2; - (*this) += a0*b3; - (*this) <<= 0x20; - (*this) += a2*b0; - (*this) += a1*b1; - (*this) += a0*b2; - (*this) <<= 0x20; - (*this) += a1*b0; - (*this) += a0*b1; - (*this) <<= 0x20; - (*this) += a0*b0; - - return *this; - } - - void uint128::full_product( const uint128& a, const uint128& b, uint128& result_hi, uint128& result_lo ) - { - // (ah * 2**64 + al) * (bh * 2**64 + bl) - // = (ah * bh * 2**128 + al * bh * 2**64 + ah * bl * 2**64 + al * bl - // = P * 2**128 + (Q + R) * 2**64 + S - // = Ph * 2**192 + Pl * 2**128 - // + Qh * 2**128 + Ql * 2**64 - // + Rh * 2**128 + Rl * 2**64 - // + Sh * 2**64 + Sl - // - - uint64_t ah = a.hi; - uint64_t al = a.lo; - uint64_t bh = b.hi; - uint64_t bl = b.lo; - - uint128 s = al; - s *= bl; - uint128 r = ah; - r *= bl; - uint128 q = al; - q *= bh; - uint128 p = ah; - p *= bh; - - uint64_t sl = s.lo; - uint64_t sh = s.hi; - uint64_t rl = r.lo; - uint64_t rh = r.hi; - uint64_t ql = q.lo; - uint64_t qh = q.hi; - uint64_t pl = p.lo; - uint64_t ph = p.hi; - - uint64_t y[4]; // final result - y[0] = sl; - - uint128_t acc = sh; - acc += ql; - acc += rl; - y[1] = acc.lo; - acc = acc.hi; - acc += qh; - acc += rh; - acc += pl; - y[2] = acc.lo; - y[3] = acc.hi + ph; - - result_hi = uint128( y[3], y[2] ); - result_lo = uint128( y[1], y[0] ); - } - - static uint8_t _popcount_64( uint64_t x ) - { - static const uint64_t m[] = { - 0x5555555555555555ULL, - 0x3333333333333333ULL, - 0x0F0F0F0F0F0F0F0FULL, - 0x00FF00FF00FF00FFULL, - 0x0000FFFF0000FFFFULL, - 0x00000000FFFFFFFFULL - }; - // TODO future optimization: replace slow, portable version - // with fast, non-portable __builtin_popcountll intrinsic - // (when available) - - for( int i=0, w=1; i<6; i++, w+=w ) - { - x = (x & m[i]) + ((x >> w) & m[i]); - } - return uint8_t(x); - } - - uint8_t uint128::popcount()const - { - return _popcount_64( lo ) + _popcount_64( hi ); - } - - void to_variant( const uint128& var, variant& vo, uint32_t max_depth ) - { - vo = std::string(var); - } - void from_variant( const variant& var, uint128& vo, uint32_t max_depth ) - { - vo = uint128(var.as_string()); - } - -} // namespace fc - -namespace std { - size_t hash::operator()( const fc::uint128& s )const - { - boost::endian::little_uint64_buf_t tmp[2]; - tmp[0] = s.hi; - tmp[1] = s.lo; - return fc::city_hash_size_t((char*)&tmp, sizeof(tmp)); - } -} - -/* - * Portions of the above code were adapted from the work of Evan Teran. - * - * Copyright (c) 2008 - * Evan Teran - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, provided - * that the above copyright notice appears in all copies and that both the - * copyright notice and this permission notice appear in supporting - * documentation, and that the same name not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. We make no representations about the - * suitability this software for any purpose. It is provided "as is" - * without express or implied warranty. - */ - diff --git a/src/variant.cpp b/src/variant.cpp index 74afb1d..a472ddf 100644 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -13,6 +13,7 @@ namespace fc { + /** * The TypeID is stored in the 'last byte' of the variant. */ @@ -27,7 +28,7 @@ variant::variant() set_variant_type( this, null_type ); } -variant::variant( fc::nullptr_t, uint32_t max_depth ) +variant::variant( std::nullptr_t, uint32_t max_depth ) { set_variant_type( this, null_type ); } @@ -672,13 +673,23 @@ void from_variant( const variant& var, std::vector& vo, uint32_t max_depth } } +void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth ) +{ + vo = boost::lexical_cast( var ); +} + +void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth ) +{ + vo = boost::lexical_cast( var.as_string() ); +} + #ifdef __APPLE__ #elif !defined(_MSC_VER) void to_variant( long long int s, variant& v, uint32_t max_depth ) { v = variant( int64_t(s) ); } void to_variant( unsigned long long int s, variant& v, uint32_t max_depth ) { v = variant( uint64_t(s)); } #endif - variant operator == ( const variant& a, const variant& b ) + bool operator == ( const variant& a, const variant& b ) { if( a.is_string() || b.is_string() ) return a.as_string() == b.as_string(); if( a.is_double() || b.is_double() ) return a.as_double() == b.as_double(); @@ -687,7 +698,7 @@ void from_variant( const variant& var, std::vector& vo, uint32_t max_depth return false; } - variant operator != ( const variant& a, const variant& b ) + bool operator != ( const variant& a, const variant& b ) { if( a.is_string() || b.is_string() ) return a.as_string() != b.as_string(); if( a.is_double() || b.is_double() ) return a.as_double() != b.as_double(); @@ -696,12 +707,12 @@ void from_variant( const variant& var, std::vector& vo, uint32_t max_depth return false; } - variant operator ! ( const variant& a ) + bool operator ! ( const variant& a ) { return !a.as_bool(); } - variant operator < ( const variant& a, const variant& b ) + bool operator < ( const variant& a, const variant& b ) { if( a.is_string() || b.is_string() ) return a.as_string() < b.as_string(); if( a.is_double() || b.is_double() ) return a.as_double() < b.as_double(); @@ -710,7 +721,7 @@ void from_variant( const variant& var, std::vector& vo, uint32_t max_depth FC_ASSERT( false, "Invalid operation" ); } - variant operator > ( const variant& a, const variant& b ) + bool operator > ( const variant& a, const variant& b ) { if( a.is_string() || b.is_string() ) return a.as_string() > b.as_string(); if( a.is_double() || b.is_double() ) return a.as_double() > b.as_double(); @@ -719,7 +730,7 @@ void from_variant( const variant& var, std::vector& vo, uint32_t max_depth FC_ASSERT( false, "Invalid operation" ); } - variant operator <= ( const variant& a, const variant& b ) + bool operator <= ( const variant& a, const variant& b ) { if( a.is_string() || b.is_string() ) return a.as_string() <= b.as_string(); if( a.is_double() || b.is_double() ) return a.as_double() <= b.as_double(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e7af90a..c384e40 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,9 +10,6 @@ target_link_libraries( task_cancel_test fc ) add_executable( bloom_test all_tests.cpp bloom_test.cpp ) target_link_libraries( bloom_test fc ) -add_executable( real128_test all_tests.cpp real128_test.cpp ) -target_link_libraries( real128_test fc ) - add_executable( hmac_test hmac_test.cpp ) target_link_libraries( hmac_test fc ) @@ -50,7 +47,6 @@ add_executable( all_tests all_tests.cpp thread/thread_tests.cpp thread/parallel_tests.cpp bloom_test.cpp - real128_test.cpp serialization_test.cpp stacktrace_test.cpp time_test.cpp diff --git a/tests/api_tests.cpp b/tests/api_tests.cpp index 0902492..dff5350 100644 --- a/tests/api_tests.cpp +++ b/tests/api_tests.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include diff --git a/tests/crypto/ecc_test.cpp b/tests/crypto/ecc_test.cpp index df809ee..94028ae 100644 --- a/tests/crypto/ecc_test.cpp +++ b/tests/crypto/ecc_test.cpp @@ -23,7 +23,7 @@ static void interop_do(const char * const data, size_t len) { } static void interop_do(const fc::ecc::public_key_data &data) { - interop_do(data.begin(), data.size()); + interop_do((char*) data.begin(), data.size()); } static void interop_do(const fc::ecc::private_key_secret &data) { @@ -31,7 +31,7 @@ static void interop_do(const fc::ecc::private_key_secret &data) { } static void interop_do(const fc::ecc::public_key_point_data &data) { - interop_do(data.begin(), data.size()); + interop_do((char*) data.begin(), data.size()); } static void interop_do(const std::string &data) { diff --git a/tests/hmac_test.cpp b/tests/hmac_test.cpp index ea3e54b..82079be 100644 --- a/tests/hmac_test.cpp +++ b/tests/hmac_test.cpp @@ -1,12 +1,13 @@ #define BOOST_TEST_MODULE HmacTest #include -#include #include #include #include #include #include +#include + // See http://tools.ietf.org/html/rfc4231 static const std::string TEST1_KEY = "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"; @@ -77,9 +78,9 @@ static void run_test( const std::string& key, const std::string& data, const std const std::string& expect_256, const std::string& expect_512 ) { - fc::array key_arr; + std::array key_arr; BOOST_CHECK_EQUAL( fc::from_hex( key, key_arr.begin(), key_arr.size() ), N ); - fc::array data_arr; + std::array data_arr; BOOST_CHECK_EQUAL( fc::from_hex( data, data_arr.begin(), data_arr.size() ), M ); BOOST_CHECK_EQUAL( mac_224.digest( key_arr.begin(), N, data_arr.begin(), M ).str(), expect_224 ); diff --git a/tests/real128_test.cpp b/tests/real128_test.cpp deleted file mode 100644 index 5020af9..0000000 --- a/tests/real128_test.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include -#include - -BOOST_AUTO_TEST_SUITE(fc) - -using fc::real128; -using std::string; - -BOOST_AUTO_TEST_CASE(real128_test) -{ - BOOST_CHECK_EQUAL(string(real128()), string("0.")); - BOOST_CHECK_EQUAL(string(real128(0)), string("0.")); - BOOST_CHECK_EQUAL(real128(8).to_uint64(), 8u); - BOOST_CHECK_EQUAL(real128(6789).to_uint64(), 6789u); - BOOST_CHECK_EQUAL(real128(10000).to_uint64(), 10000u); - BOOST_CHECK_EQUAL(string(real128(1)), string("1.")); - BOOST_CHECK_EQUAL(string(real128(5)), string("5.")); - BOOST_CHECK_EQUAL(string(real128(12345)), string("12345.")); - BOOST_CHECK_EQUAL(string(real128(0)), string(real128("0"))); - - real128 ten(10); - real128 two(2); - real128 twenty(20); - real128 pi(31415926535); - pi /= 10000000000; - - BOOST_CHECK_EQUAL( string(ten), "10." ); - BOOST_CHECK_EQUAL( string(two), "2." ); - BOOST_CHECK_EQUAL( string(ten+two), "12." ); - BOOST_CHECK_EQUAL( string(ten-two), "8." ); - BOOST_CHECK_EQUAL( string(ten*two), "20." ); - BOOST_CHECK_EQUAL( string(ten/two), "5." ); - BOOST_CHECK_EQUAL( string(ten/two/two/two*two*two*two), "10." ); - BOOST_CHECK_EQUAL( string(ten/two/two/two*two*two*two), string(ten) ); - BOOST_CHECK_EQUAL( string(twenty/ten), string(two) ); - BOOST_CHECK_EQUAL( string(pi), "3.1415926535" ); - BOOST_CHECK_EQUAL( string(pi*10), "31.415926535" ); - BOOST_CHECK_EQUAL( string(pi*20), "62.83185307" ); - BOOST_CHECK_EQUAL( string(real128("62.83185307")/twenty), string(pi) ); - BOOST_CHECK_EQUAL( string(pi*1), "3.1415926535" ); - BOOST_CHECK_EQUAL( string(pi*0), "0." ); - - BOOST_CHECK_EQUAL(real128("12345.6789").to_uint64(), 12345u); - BOOST_CHECK_EQUAL((real128("12345.6789")*10000).to_uint64(), 123456789u); - BOOST_CHECK_EQUAL(string(real128("12345.6789")), string("12345.6789")); - - BOOST_CHECK_EQUAL( real128(uint64_t(-1)).to_uint64(), uint64_t(-1) ); - - wdump( (ten)(two)(twenty) ); - wdump((real128("12345.6789")) ); - wdump( (ten/3*3) ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/thread/parallel_tests.cpp b/tests/thread/parallel_tests.cpp index 6e91da4..14dcb4d 100644 --- a/tests/thread/parallel_tests.cpp +++ b/tests/thread/parallel_tests.cpp @@ -200,25 +200,25 @@ BOOST_AUTO_TEST_CASE( serial_valve ) fc::serial_valve valve; { // Simple test, f2 finishes before f1 - fc::promise* syncer = new fc::promise(); - fc::promise* waiter = new fc::promise(); + fc::promise::ptr syncer = fc::promise::create(); + fc::promise::ptr waiter = fc::promise::create(); auto p1 = fc::async([&counter,&valve,syncer,waiter] () { valve.do_serial( [syncer,waiter](){ syncer->set_value(); - fc::future( fc::shared_ptr>( waiter, true ) ).wait(); }, + fc::future( waiter ).wait(); }, [&counter](){ BOOST_CHECK_EQUAL( 0u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); // at this point, p1.f1 has started executing and is waiting on waiter - syncer = new fc::promise(); + syncer = fc::promise::create(); auto p2 = fc::async([&counter,&valve,syncer] () { valve.do_serial( [syncer](){ syncer->set_value(); }, [&counter](){ BOOST_CHECK_EQUAL( 1u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); fc::usleep( fc::milliseconds(10) ); @@ -237,37 +237,37 @@ BOOST_AUTO_TEST_CASE( serial_valve ) } { // Triple test, f3 finishes first, then f1, finally f2 - fc::promise* syncer = new fc::promise(); - fc::promise* waiter = new fc::promise(); + fc::promise::ptr syncer = fc::promise::create(); + fc::promise::ptr waiter = fc::promise::create(); counter.store(0); auto p1 = fc::async([&counter,&valve,syncer,waiter] () { valve.do_serial( [&syncer,waiter](){ syncer->set_value(); - fc::future( fc::shared_ptr>( waiter, true ) ).wait(); }, + fc::future( waiter ).wait(); }, [&counter](){ BOOST_CHECK_EQUAL( 0u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); // at this point, p1.f1 has started executing and is waiting on waiter - syncer = new fc::promise(); + syncer = fc::promise::create(); auto p2 = fc::async([&counter,&valve,syncer] () { valve.do_serial( [&syncer](){ syncer->set_value(); fc::usleep( fc::milliseconds(100) ); }, [&counter](){ BOOST_CHECK_EQUAL( 1u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); // at this point, p2.f1 has started executing and is sleeping - syncer = new fc::promise(); + syncer = fc::promise::create(); auto p3 = fc::async([&counter,&valve,syncer] () { valve.do_serial( [syncer](){ syncer->set_value(); }, [&counter](){ BOOST_CHECK_EQUAL( 2u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); fc::usleep( fc::milliseconds(10) ); @@ -288,37 +288,37 @@ BOOST_AUTO_TEST_CASE( serial_valve ) } { // Triple test again but with invocations from different threads - fc::promise* syncer = new fc::promise(); - fc::promise* waiter = new fc::promise(); + fc::promise::ptr syncer = fc::promise::create(); + fc::promise::ptr waiter = fc::promise::create(); counter.store(0); auto p1 = fc::do_parallel([&counter,&valve,syncer,waiter] () { valve.do_serial( [&syncer,waiter](){ syncer->set_value(); - fc::future( fc::shared_ptr>( waiter, true ) ).wait(); }, + fc::future( waiter ).wait(); }, [&counter](){ BOOST_CHECK_EQUAL( 0u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); // at this point, p1.f1 has started executing and is waiting on waiter - syncer = new fc::promise(); + syncer = fc::promise::create(); auto p2 = fc::do_parallel([&counter,&valve,syncer] () { valve.do_serial( [&syncer](){ syncer->set_value(); fc::usleep( fc::milliseconds(100) ); }, [&counter](){ BOOST_CHECK_EQUAL( 1u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); // at this point, p2.f1 has started executing and is sleeping - syncer = new fc::promise(); + syncer = fc::promise::create(); auto p3 = fc::do_parallel([&counter,&valve,syncer] () { valve.do_serial( [syncer](){ syncer->set_value(); }, [&counter](){ BOOST_CHECK_EQUAL( 2u, counter.load() ); counter.fetch_add(1); } ); }); - fc::future( fc::shared_ptr>( syncer, true ) ).wait(); + fc::future( syncer ).wait(); fc::usleep( fc::milliseconds(10) ); diff --git a/tests/thread/task_cancel.cpp b/tests/thread/task_cancel.cpp index 3435f39..2909ca7 100644 --- a/tests/thread/task_cancel.cpp +++ b/tests/thread/task_cancel.cpp @@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE( cancel_a_task_waiting_on_promise ) { enum task_result{task_completed, task_aborted}; - fc::promise::ptr promise_to_wait_on(new fc::promise()); + fc::promise::ptr promise_to_wait_on = fc::promise::create(); fc::future task = fc::async([promise_to_wait_on]() { BOOST_TEST_MESSAGE("Starting async task");