Merge pull request #137 from pmconrad/1584_more_simplification

More simplifications
This commit is contained in:
Peter Conrad 2019-06-19 18:34:59 +02:00 committed by GitHub
commit 6ed94317ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
78 changed files with 767 additions and 2004 deletions

View file

@ -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

View file

@ -1,145 +0,0 @@
#pragma once
#include <fc/crypto/base64.hpp>
#include <fc/variant.hpp>
#include <fc/reflect/reflect.hpp>
namespace fc {
/**
* Provides a fixed size array that is easier for templates to specialize
* against or overload than T[N].
*/
template<typename T, size_t N>
class array {
public:
/**
* Checked indexing (when in debug build) that also simplifies dereferencing
* when you have an array<T,N>*.
*/
///@{
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<size_t N>
class array<unsigned char,N>
{
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,N>*.
*/
///@{
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<size_t N>
class array<char,N>
{
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,N>*.
*/
///@{
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<typename T, size_t N>
bool operator == ( const array<T,N>& a, const array<T,N>& b )
{ return 0 == memcmp( a.data, b.data, N*sizeof(T) ); }
template<typename T, size_t N>
bool operator < ( const array<T,N>& a, const array<T,N>& b )
{ return memcmp( a.data, b.data, N*sizeof(T) ) < 0 ; }
template<typename T, size_t N>
bool operator > ( const array<T,N>& a, const array<T,N>& b )
{ return memcmp( a.data, b.data, N*sizeof(T) ) > 0 ; }
template<typename T, size_t N>
bool operator != ( const array<T,N>& a, const array<T,N>& b )
{ return 0 != memcmp( a.data, b.data, N*sizeof(T) ); }
template<typename T, size_t N>
void to_variant( const array<T,N>& bi, variant& v, uint32_t max_depth = 1 )
{
to_variant( std::vector<char>( (const char*)&bi, ((const char*)&bi) + sizeof(bi) ), v, 1 );
}
template<typename T, size_t N>
void from_variant( const variant& v, array<T,N>& bi, uint32_t max_depth = 1 )
{
std::vector<char> ve = v.as< std::vector<char> >( 1 );
if( ve.size() )
{
memcpy(&bi, ve.data(), std::min<size_t>(ve.size(),sizeof(bi)) );
}
else
memset( &bi, char(0), sizeof(bi) );
}
template<typename T,size_t N> struct get_typename< fc::array<T,N> >
{
static const char* name()
{
static std::string _name = std::string("fc::array<")+std::string(fc::get_typename<T>::name())+","+ fc::to_string(N) + ">";
return _name.c_str();
}
};
}
#include <unordered_map>
#include <fc/crypto/city.hpp>
namespace std
{
template<typename T, size_t N>
struct hash<fc::array<T,N> >
{
size_t operator()( const fc::array<T,N>& e )const
{
return fc::city_hash_size_t( (char*)&e, sizeof(e) );
}
};
}

View file

@ -122,7 +122,7 @@ namespace asio {
template<typename AsyncReadStream, typename MutableBufferSequence>
future<size_t> read_some(AsyncReadStream& s, const MutableBufferSequence& buf)
{
promise<size_t>::ptr completion_promise(new promise<size_t>("fc::asio::async_read_some"));
promise<size_t>::ptr completion_promise = promise<size_t>::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<typename AsyncReadStream>
future<size_t> read_some(AsyncReadStream& s, char* buffer, size_t length, size_t offset = 0)
{
promise<size_t>::ptr completion_promise(new promise<size_t>("fc::asio::async_read_some"));
promise<size_t>::ptr completion_promise = promise<size_t>::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<typename AsyncReadStream>
future<size_t> read_some(AsyncReadStream& s, const std::shared_ptr<char>& buffer, size_t length, size_t offset)
{
promise<size_t>::ptr completion_promise(new promise<size_t>("fc::asio::async_read_some"));
promise<size_t>::ptr completion_promise = promise<size_t>::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<typename AsyncWriteStream, typename ConstBufferSequence>
size_t write( AsyncWriteStream& s, const ConstBufferSequence& buf ) {
promise<size_t>::ptr p(new promise<size_t>("fc::asio::write"));
promise<size_t>::ptr p = promise<size_t>::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<typename AsyncWriteStream, typename ConstBufferSequence>
future<size_t> write_some( AsyncWriteStream& s, const ConstBufferSequence& buf ) {
promise<size_t>::ptr p(new promise<size_t>("fc::asio::write_some"));
promise<size_t>::ptr p = promise<size_t>::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<typename AsyncWriteStream>
future<size_t> write_some( AsyncWriteStream& s, const char* buffer,
size_t length, size_t offset = 0) {
promise<size_t>::ptr p(new promise<size_t>("fc::asio::write_some"));
promise<size_t>::ptr p = promise<size_t>::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<typename AsyncWriteStream>
future<size_t> write_some( AsyncWriteStream& s, const std::shared_ptr<const char>& buffer,
size_t length, size_t offset ) {
promise<size_t>::ptr p(new promise<size_t>("fc::asio::write_some"));
promise<size_t>::ptr p = promise<size_t>::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<typename SocketType, typename AcceptorType>
void accept( AcceptorType& acc, SocketType& sock ) {
//promise<boost::system::error_code>::ptr p( new promise<boost::system::error_code>("fc::asio::tcp::accept") );
promise<void>::ptr p( new promise<void>("fc::asio::tcp::accept") );
promise<void>::ptr p = promise<void>::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<typename AsyncSocket, typename EndpointType>
void connect( AsyncSocket& sock, const EndpointType& ep ) {
promise<void>::ptr p(new promise<void>("fc::asio::tcp::connect"));
promise<void>::ptr p = promise<void>::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) );

View file

@ -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

View file

@ -1,9 +1,10 @@
#pragma once
#include <fc/io/raw_fwd.hpp>
#include <fc/crypto/sha512.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/uint128.hpp>
#include <fc/fwd.hpp>
#include <fc/uint128.hpp>
#include <vector>
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;

View file

@ -41,36 +41,25 @@
// doesn't hold for any hash functions in this file.
#pragma once
#include <fc/uint128.hpp>
#include <stdlib.h> // for size_t.
#include <stdint.h>
#include <utility>
namespace fc {
template<typename T, size_t N>
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<uint64_t,4> city_hash_crc_256(const char *s, size_t len);
uint128_t city_hash_crc_128(const char *s, size_t len);
} // namespace fc

View file

@ -4,9 +4,10 @@
#include <fc/crypto/sha256.hpp>
#include <fc/crypto/sha512.hpp>
#include <fc/fwd.hpp>
#include <fc/array.hpp>
#include <fc/io/raw_fwd.hpp>
#include <array>
namespace fc {
namespace ecc {
@ -16,15 +17,15 @@ namespace fc {
class private_key_impl;
}
typedef fc::sha256 blind_factor_type;
typedef fc::array<char,33> commitment_type;
typedef fc::array<char,33> public_key_data;
typedef fc::sha256 private_key_secret;
typedef fc::array<char,65> public_key_point_data; ///< the full non-compressed version of the ECC point
typedef fc::array<char,72> signature;
typedef fc::array<unsigned char,65> compact_signature;
typedef std::vector<char> range_proof_type;
typedef fc::array<char,78> extended_key_data;
typedef fc::sha256 blind_factor_type;
typedef std::array<unsigned char,33> commitment_type;
typedef std::array<unsigned char,33> public_key_data;
typedef fc::sha256 private_key_secret;
typedef std::array<unsigned char,65> public_key_point_data; ///< the full non-compressed version of the ECC point
typedef std::array<unsigned char,72> signature;
typedef std::array<unsigned char,65> compact_signature;
typedef std::vector<char> range_proof_type;
typedef std::array<unsigned char,78> extended_key_data;
/**
* @class public_key

View file

@ -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 );

View file

@ -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& );

View file

@ -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& );

View file

@ -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& );

View file

@ -1,5 +1,6 @@
#pragma once
#include <boost/endian/buffers.hpp>
#include <fc/io/raw_fwd.hpp>
#include <fc/fwd.hpp>
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<typename T>
static sha512 hash( const T& t )

View file

@ -5,7 +5,6 @@
*/
#include <fc/log/logger.hpp>
#include <fc/optional.hpp>
#include <fc/utility.hpp>
#include <exception>
#include <functional>
#include <unordered_map>
@ -107,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:
@ -156,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<exception> dynamic_copy_exception()const;
private:
std::exception_ptr _inner;
@ -167,10 +166,10 @@ namespace fc
{
#if defined(_MSC_VER) && (_MSC_VER < 1700)
return std::make_shared<unhandled_exception>( log_message(),
std::copy_exception(fc::forward<T>(e)) );
std::copy_exception(std::forward<T>(e)) );
#else
return std::make_shared<unhandled_exception>( log_message(),
std::make_exception_ptr(fc::forward<T>(e)) );
std::make_exception_ptr(std::forward<T>(e)) );
#endif
}
@ -180,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<typename T>
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 );
}
@ -202,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()
{
@ -244,7 +243,7 @@ namespace fc
explicit TYPE();\
\
virtual std::shared_ptr<fc::exception> dynamic_copy_exception()const;\
virtual NO_RETURN void dynamic_rethrow_exception()const; \
[[noreturn]] virtual void dynamic_rethrow_exception()const; \
};
#define FC_IMPLEMENT_DERIVED_EXCEPTION( TYPE, BASE, CODE, WHAT ) \
@ -270,7 +269,7 @@ namespace fc
{ \
return std::make_shared<TYPE>( *this ); \
} \
NO_RETURN void TYPE::dynamic_rethrow_exception()const \
[[noreturn]] void TYPE::dynamic_rethrow_exception()const \
{ \
if( code() == CODE ) throw *this;\
else fc::exception::dynamic_rethrow_exception(); \

View file

@ -1,7 +1,7 @@
#pragma once
#include <fc/utility.hpp>
#include <fc/fwd.hpp>
#include <cstdint>
#include <new>
#include <type_traits>
#include <utility>
@ -41,10 +41,10 @@ namespace fc {
template<typename T, unsigned int S, typename U, typename A>
auto operator + ( const fwd<T,S,A>& x, U&& u ) -> typename detail::add<T,U>::type { return *x+fc::forward<U>(u); }
auto operator + ( const fwd<T,S,A>& x, U&& u ) -> typename detail::add<T,U>::type { return *x+std::forward<U>(u); }
template<typename T, unsigned int S, typename U, typename A>
auto operator - ( const fwd<T,S,A>& x, U&& u ) -> typename detail::sub<T,U>::type { return *x-fc::forward<U>(u); }
auto operator - ( const fwd<T,S,A>& x, U&& u ) -> typename detail::sub<T,U>::type { return *x-std::forward<U>(u); }
template<typename T, unsigned int S, typename U, typename A>
auto operator << ( U& u, const fwd<T,S,A>& f ) -> typename detail::insert_op<U,T>::type { return u << *f; }
@ -63,20 +63,20 @@ namespace fc {
template<typename U>
fwd<T,S,A>::fwd( U&& u ) {
check_size<sizeof(T),sizeof(_store)>();
new (this) T( fc::forward<U>(u) );
new (this) T( std::forward<U>(u) );
}
template<typename T,unsigned int S,typename A>
template<typename U,typename V>
fwd<T,S,A>::fwd( U&& u, V&& v ) {
check_size<sizeof(T),sizeof(_store)>();
new (this) T( fc::forward<U>(u), fc::forward<V>(v) );
new (this) T( std::forward<U>(u), std::forward<V>(v) );
}
template<typename T,unsigned int S,typename A>
template<typename U,typename V,typename X,typename Y>
fwd<T,S,A>::fwd( U&& u, V&& v, X&& x, Y&& y ) {
check_size<sizeof(T),sizeof(_store)>();
new (this) T( fc::forward<U>(u), fc::forward<V>(v), fc::forward<X>(x), fc::forward<Y>(y) );
new (this) T( std::forward<U>(u), std::forward<V>(v), std::forward<X>(x), std::forward<Y>(y) );
}
@ -121,7 +121,7 @@ namespace fc {
template<typename T,unsigned int S, typename A>
template<typename U>
T& fwd<T,S,A>::operator = ( U&& u ) {
return **this = fc::forward<U>(u);
return **this = std::forward<U>(u);
}
template<typename T,unsigned int S, typename A>

View file

@ -1,5 +1,4 @@
#pragma once
#include <fc/utility.hpp>
#include <string.h>
#include <stdint.h>
@ -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 );
}
/**

View file

@ -1,8 +1,8 @@
#pragma once
#include <fc/shared_ptr.hpp>
#include <fc/filesystem.hpp>
#include <fc/io/iostream.hpp>
#include <fstream>
#include <memory>
namespace fc {
class path;
@ -21,7 +21,7 @@ namespace fc {
private:
class impl;
fc::shared_ptr<impl> my;
std::shared_ptr<impl> my;
};
class ifstream : virtual public istream {
@ -44,7 +44,7 @@ namespace fc {
bool eof()const;
private:
class impl;
fc::shared_ptr<impl> my;
std::shared_ptr<impl> my;
};
/**

View file

@ -1,16 +1,14 @@
#pragma once
#include <boost/endian/buffers.hpp>
#include <fc/io/raw_variant.hpp>
#include <fc/reflect/reflect.hpp>
#include <fc/io/datastream.hpp>
#include <fc/io/varint.hpp>
#include <fc/optional.hpp>
#include <fc/fwd.hpp>
#include <fc/array.hpp>
#include <fc/time.hpp>
#include <fc/filesystem.hpp>
#include <fc/exception/exception.hpp>
#include <fc/safe.hpp>
#include <fc/io/raw_fwd.hpp>
#include <algorithm>
#include <map>
@ -27,6 +25,22 @@ namespace fc {
pack( s, args..., _max_depth );
}
template<typename Stream>
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<typename Stream>
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<typename Stream>
inline void pack( Stream& s, const fc::exception& e, uint32_t _max_depth )
{
@ -130,22 +144,22 @@ namespace fc {
} FC_RETHROW_EXCEPTIONS( warn, "" ) }
template<typename Stream, size_t N>
inline void pack( Stream& s, const fc::array<char,N>& v, uint32_t _max_depth ) {
s.write( &v.data[0], N );
inline void pack( Stream& s, const std::array<char,N>& v, uint32_t _max_depth ) {
s.write( v.data(), N );
}
template<typename Stream, size_t N>
inline void pack( Stream& s, const fc::array<unsigned char,N>& v, uint32_t _max_depth ) {
s.write( (char*)&v.data[0], N );
inline void pack( Stream& s, const std::array<unsigned char,N>& v, uint32_t _max_depth ) {
s.write( (char*)v.data(), N );
}
template<typename Stream, size_t N>
inline void unpack( Stream& s, fc::array<char,N>& v, uint32_t _max_depth ) { try {
s.read( &v.data[0], N );
} FC_RETHROW_EXCEPTIONS( warn, "fc::array<char,${length}>", ("length",N) ) }
inline void unpack( Stream& s, std::array<char,N>& v, uint32_t _max_depth ) { try {
s.read( v.data(), N );
} FC_RETHROW_EXCEPTIONS( warn, "std::array<char,${length}>", ("length",N) ) }
template<typename Stream, size_t N>
inline void unpack( Stream& s, fc::array<unsigned char,N>& v, uint32_t _max_depth ) { try {
s.read( (char*)&v.data[0], N );
} FC_RETHROW_EXCEPTIONS( warn, "fc::array<unsigned char,${length}>", ("length",N) ) }
inline void unpack( Stream& s, std::array<unsigned char,N>& v, uint32_t _max_depth ) { try {
s.read( (char*)v.data(), N );
} FC_RETHROW_EXCEPTIONS( warn, "std::array<unsigned char,${length}>", ("length",N) ) }
template<typename Stream, typename T>
inline void pack( Stream& s, const std::shared_ptr<T>& v, uint32_t _max_depth )
@ -342,17 +356,21 @@ namespace fc {
const uint32_t max_depth;
};
// Default pack/unpack functions for classes (if_class<fc::true_type>) 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<typename IsClass=fc::true_type>
template<typename T, typename Dummy = void>
struct if_class;
template<>
struct if_class<fc::false_type> {
template<typename Stream, typename T>
template<typename T>
struct if_class<T, std::enable_if_t<!std::is_class<T>::value>> {
template<typename Stream>
static inline void pack( Stream& s, const T v, uint32_t _max_depth ) = delete;
template<typename Stream, typename T>
template<typename Stream>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) = delete;
};
template<>
struct if_class<int64_t, void> {
template<typename Stream>
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<uint64_t, void> {
template<typename Stream>
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<int32_t, void> {
template<typename Stream>
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<uint32_t, void> {
template<typename Stream>
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<int16_t, void> {
template<typename Stream>
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<uint16_t, void> {
template<typename Stream>
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<int8_t, void> {
template<typename Stream>
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<uint8_t, void> {
template<typename Stream>
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<typename IsEnum=fc::false_type>
struct if_enum {
template<typename Stream, typename T>
template<typename T, typename Dummy=void>
struct if_enum;
template<typename T>
struct if_enum<T, std::enable_if_t<!std::is_enum<T>::value>> {
template<typename Stream>
static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
fc::reflector<T>::visit( pack_object_visitor<Stream,T>( v, s, _max_depth - 1 ) );
}
template<typename Stream, typename T>
template<typename Stream>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
fc::reflector<T>::visit( unpack_object_visitor<Stream,T>( v, s, _max_depth - 1 ) );
}
};
template<>
struct if_enum<fc::true_type> {
template<typename Stream, typename T>
template<typename T>
struct if_enum<T, std::enable_if_t<std::is_enum<T>::value>> {
template<typename Stream>
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<typename Stream, typename T>
template<typename Stream>
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<typename IsReflected=fc::false_type>
template<typename IsReflected=std::false_type>
struct if_reflected {
template<typename Stream, typename T>
static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
if_class<typename fc::is_class<T>::type>::pack( s, v, _max_depth - 1 );
if_class<T>::pack( s, v, _max_depth - 1 );
}
template<typename Stream, typename T>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
if_class<typename fc::is_class<T>::type>::unpack( s, v, _max_depth - 1 );
if_class<T>::unpack( s, v, _max_depth - 1 );
}
};
template<>
struct if_reflected<fc::true_type> {
struct if_reflected<std::true_type> {
template<typename Stream, typename T>
static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
if_enum< typename fc::reflector<T>::is_enum >::pack( s, v, _max_depth - 1 );
if_enum<T>::pack( s, v, _max_depth - 1 );
}
template<typename Stream, typename T>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
if_enum< typename fc::reflector<T>::is_enum >::unpack( s, v, _max_depth - 1 );
if_enum<T>::unpack( s, v, _max_depth - 1 );
}
};

View file

@ -1,11 +1,15 @@
#pragma once
#include <boost/endian/buffers.hpp>
#include <fc/config.hpp>
#include <fc/container/flat_fwd.hpp>
#include <fc/io/varint.hpp>
#include <fc/array.hpp>
#include <fc/safe.hpp>
#include <fc/uint128.hpp>
#include <array>
#include <deque>
#include <memory>
#include <vector>
#include <string>
#include <unordered_set>
@ -41,7 +45,10 @@ namespace fc {
template<typename Stream, typename IntType, typename EnumType>
inline void unpack( Stream& s, fc::enum_type<IntType,EnumType>& tp, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream>
inline void pack( Stream& s, const uint128_t& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream>
inline void unpack( Stream& s, uint128_t& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void pack( Stream& s, const std::set<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void unpack( Stream& s, std::set<T>& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
@ -124,22 +131,26 @@ namespace fc {
inline void unpack( Stream& s, boost::endian::endian_buffer<O,T,N,A>& v, uint32_t _max_depth );
template<typename Stream, typename T, size_t N>
inline void pack( Stream& s, const fc::array<T,N>& v, uint32_t _max_depth ) = delete;
inline void pack( Stream& s, const std::array<T,N>& v, uint32_t _max_depth ) = delete;
template<typename Stream, typename T, size_t N>
inline void unpack( Stream& s, fc::array<T,N>& v, uint32_t _max_depth ) = delete;
template<typename Stream, size_t N> inline void pack( Stream& s, const fc::array<char,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, size_t N> inline void unpack( Stream& s, fc::array<char,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH);
template<typename Stream, size_t N> inline void pack( Stream& s, const fc::array<unsigned char,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, size_t N> inline void unpack( Stream& s, fc::array<unsigned char,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH);
inline void unpack( Stream& s, std::array<T,N>& v, uint32_t _max_depth ) = delete;
template<typename Stream, size_t N>
inline void pack( Stream& s, const std::array<char,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, size_t N>
inline void unpack( Stream& s, std::array<char,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH);
template<typename Stream, size_t N>
inline void pack( Stream& s, const std::array<unsigned char,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, size_t N>
inline void unpack( Stream& s, std::array<unsigned char,N>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH);
template<typename Stream, typename T> inline void pack( Stream& s, const shared_ptr<T>& v,
template<typename Stream, typename T> inline void pack( Stream& s, const std::shared_ptr<T>& v,
uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void unpack( Stream& s, shared_ptr<T>& v,
template<typename Stream, typename T> inline void unpack( Stream& s, std::shared_ptr<T>& v,
uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void pack( Stream& s, const shared_ptr<const T>& v,
template<typename Stream, typename T> inline void pack( Stream& s, const std::shared_ptr<const T>& v,
uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> inline void unpack( Stream& s, shared_ptr<const T>& v,
template<typename Stream, typename T> inline void unpack( Stream& s, std::shared_ptr<const T>& v,
uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream> inline void pack( Stream& s, const bool& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );

View file

@ -1,5 +1,5 @@
#pragma once
#include <fc/shared_ptr.hpp>
#include <memory>
#include <string>
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<appender_factory> ptr;
typedef std::shared_ptr<appender_factory> ptr;
virtual ~appender_factory(){};
virtual fc::shared_ptr<appender> create( const variant& args ) = 0;
virtual std::shared_ptr<appender> create( const variant& args ) = 0;
};
namespace detail {
template<typename T>
class appender_factory_impl : public appender_factory {
public:
virtual fc::shared_ptr<appender> create( const variant& args ) {
return fc::shared_ptr<appender>(new T(args));
virtual std::shared_ptr<appender> create( const variant& args ) {
return std::shared_ptr<appender>(new T(args));
}
};
}
class appender : public fc::retainable {
class appender {
public:
typedef fc::shared_ptr<appender> ptr;
typedef std::shared_ptr<appender> ptr;
template<typename T>
static bool register_appender(const std::string& type) {
return register_appender( type, new detail::appender_factory_impl<T>() );
return register_appender( type, appender_factory::ptr( new detail::appender_factory_impl<T>() ) );
}
static appender::ptr create( const std::string& name, const std::string& type, const variant& args );

View file

@ -26,7 +26,7 @@ class file_appender : public appender {
private:
class impl;
fc::shared_ptr<impl> my;
std::unique_ptr<impl> my;
};
} // namespace fc

View file

@ -24,7 +24,7 @@ namespace fc
private:
class impl;
fc::shared_ptr<impl> my;
std::unique_ptr<impl> my;
};
} // namespace fc

View file

@ -6,7 +6,6 @@
#include <fc/config.hpp>
#include <fc/time.hpp>
#include <fc/variant_object.hpp>
#include <fc/shared_ptr.hpp>
#include <memory>
#include <string>

View file

@ -1,14 +1,13 @@
#pragma once
#include <fc/config.hpp>
#include <fc/time.hpp>
#include <fc/shared_ptr.hpp>
#include <fc/log/appender.hpp>
#include <fc/log/log_message.hpp>
#include <cstddef>
#include <memory>
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<appender>& a );
std::vector<fc::shared_ptr<appender> > get_appenders()const;
void remove_appender( const fc::shared_ptr<appender>& a );
void add_appender( const appender::ptr& a );
std::vector<appender::ptr> 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<impl> my;
std::shared_ptr<impl> my;
};
} // namespace fc

View file

@ -1,62 +0,0 @@
#pragma once
#include <fc/network/http/connection.hpp>
#include <fc/shared_ptr.hpp>
#include <functional>
#include <memory>
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<impl>& 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<impl> 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<void(const http::request&, const server::response& s )>& cb );
private:
class impl;
std::unique_ptr<impl> my;
};
typedef std::shared_ptr<server> server_ptr;
} }

View file

@ -1,5 +1,4 @@
#pragma once
#include <fc/shared_ptr.hpp>
#include <memory>
namespace fc {
@ -35,8 +34,8 @@ namespace fc {
fc::ip::endpoint local_endpoint()const;
private:
class impl;
fc::shared_ptr<impl> my;
class impl;
std::shared_ptr<impl> my;
};
}

View file

@ -1,9 +1,7 @@
#pragma once
#include <fc/utility.hpp>
#include <assert.h>
#include <utility>
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>(u) );
new ((char*)ptr()) T( std::forward<U>(u) );
}
template<typename U>
optional& operator=( U&& u )
{
reset();
new (ptr()) T( fc::forward<U>(u) );
new (ptr()) T( std::forward<U>(u) );
_valid = true;
return *this;
}

40
include/fc/popcount.hpp Normal file
View file

@ -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 <fc/platform_independence.hpp>
#include <fc/uint128.hpp>
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

View file

@ -1,61 +0,0 @@
#pragma once
#include <fc/uint128.hpp>
#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<typename Stream>
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<typename Stream>
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<typename Stream>
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

View file

@ -7,7 +7,6 @@
*/
#include <fc/string.hpp>
#include <fc/utility.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/enum.hpp>
@ -16,6 +15,7 @@
#include <boost/preprocessor/stringize.hpp>
#include <stdint.h>
#include <string.h>
#include <type_traits>
#include <fc/reflect/typename.hpp>
@ -33,8 +33,7 @@ namespace fc {
template<typename T>
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<TYPE>::visit( const Visitor& v ) { \
#define FC_REFLECT_ENUM( ENUM, FIELDS ) \
namespace fc { \
template<> struct reflector<ENUM> { \
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<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \
template<> struct reflector<TYPE> {\
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<BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct get_typename<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \
template<BOOST_PP_SEQ_ENUM(TEMPLATE_ARGS)> struct reflector<TYPE> {\
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<TYPE> { static const char* name() { return BOOST_PP_STRINGIZE(TYPE); } }; \
template<> struct reflector<TYPE> {\
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 )\

View file

@ -1,5 +1,6 @@
#pragma once
#include <array>
#include <deque>
#include <map>
#include <set>
@ -7,7 +8,7 @@
#include <vector>
#include <fc/optional.hpp>
#include <fc/string.hpp>
#include <fc/container/flat_fwd.hpp>
namespace fc {
@ -92,6 +93,15 @@ namespace fc {
return n.c_str();
}
};
template<typename T,size_t N> struct get_typename< std::array<T,N> >
{
static const char* name()
{
static std::string _name = std::string("std::array<") + std::string(fc::get_typename<T>::name())
+ "," + fc::to_string(N) + ">";
return _name.c_str();
}
};
struct unsigned_int;
class variant_object;

View file

@ -63,17 +63,17 @@ namespace fc
const uint32_t _max_depth;
};
template<typename IsEnum=fc::false_type>
struct if_enum
template<typename T, typename Dummy = void>
struct if_enum;
template<typename T>
struct if_enum<T, std::enable_if_t<!std::is_enum<T>::value>>
{
template<typename T>
static inline void to_variant( const T& v, fc::variant& vo, uint32_t max_depth )
{
mutable_variant_object mvo;
fc::reflector<T>::visit( to_variant_visitor<T>( mvo, v, max_depth ) );
vo = std::move(mvo);
}
template<typename T>
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<fc::true_type>
template<typename T>
struct if_enum<T, std::enable_if_t<std::is_enum<T>::value>>
{
template<typename T>
static inline void to_variant( const T& o, fc::variant& v, uint32_t max_depth = 1 )
{
v = fc::reflector<T>::to_fc_string(o);
}
template<typename T>
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<typename T>
void to_variant( const T& o, variant& v, uint32_t max_depth )
{
if_enum<typename fc::reflector<T>::is_enum>::to_variant( o, v, max_depth );
if_enum<T>::to_variant( o, v, max_depth );
}
template<typename T>
void from_variant( const variant& v, T& o, uint32_t max_depth )
{
if_enum<typename fc::reflector<T>::is_enum>::from_variant( v, o, max_depth );
if_enum<T>::from_variant( v, o, max_depth );
}
}

View file

@ -1,35 +0,0 @@
#pragma once
#include <fc/io/json.hpp>
#include <fc/network/http/connection.hpp>
#include <fc/network/http/server.hpp>
#include <fc/reflect/variant.hpp>
#include <fc/rpc/api_connection.hpp>
#include <fc/rpc/state.hpp>
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

View file

@ -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<uint128_t> 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<T>::min();
}
static safe max()
static constexpr safe max()
{
return std::numeric_limits<T>::max();
}
@ -92,7 +91,7 @@ namespace fc {
safe operator - ()const
{
if( value == std::numeric_limits<T>::min() ) FC_CAPTURE_AND_THROW( overflow_exception, (*this) );
if( value == min() ) FC_CAPTURE_AND_THROW( overflow_exception, (*this) );
return safe( -value );
}

View file

@ -1,92 +0,0 @@
#pragma once
#include <cstdint>
#include <utility>
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<typename T>
class shared_ptr {
public:
template<typename Other>
shared_ptr( const shared_ptr<Other>& 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<typename T, typename O>
fc::shared_ptr<T> dynamic_pointer_cast( const fc::shared_ptr<O>& t ) {
return fc::shared_ptr<T>( dynamic_cast<T*>(t.get()), true );
}
template<typename T, typename O>
fc::shared_ptr<T> static_pointer_cast( const fc::shared_ptr<O>& t ) {
return fc::shared_ptr<T>( static_cast<T*>(t.get()), true );
}
}

View file

@ -36,13 +36,13 @@ namespace fc {
template<typename T>
inline T wait( boost::signals2::signal<void(T)>& sig, const microseconds& timeout_us=microseconds::maximum() ) {
typename promise<T>::ptr p(new promise<T>("fc::signal::wait"));
typename promise<T>::ptr p = promise<T>::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<void()>& sig, const microseconds& timeout_us=microseconds::maximum() ) {
promise<void>::ptr p(new promise<void>("fc::signal::wait"));
promise<void>::ptr p = promise<void>::create("fc::signal::wait");
boost::signals2::scoped_connection c( sig.connect( [=]() { p->set_value(); } ));
p->wait( timeout_us );
}

View file

@ -11,11 +11,11 @@
**/
#pragma once
#include <array>
#include <functional>
#include <stdexcept>
#include <typeinfo>
#include <fc/array.hpp>
#include <fc/exception/exception.hpp>
namespace fc {
@ -141,58 +141,53 @@ struct storage_ops<N> {
template<typename X>
struct position<X> {
static const int pos = -1;
static constexpr int pos = -1;
};
template<typename X, typename... Ts>
struct position<X, X, Ts...> {
static const int pos = 0;
static constexpr int pos = 0;
};
template<typename X, typename T, typename... Ts>
struct position<X, T, Ts...> {
static const int pos = position<X, Ts...>::pos != -1 ? position<X, Ts...>::pos + 1 : -1;
static constexpr int pos = position<X, Ts...>::pos != -1 ? position<X, Ts...>::pos + 1 : -1;
};
template<typename T, typename... Ts>
struct type_info<T&, Ts...> {
static const bool no_reference_types = false;
static const bool no_duplicates = position<T, Ts...>::pos == -1 && type_info<Ts...>::no_duplicates;
static const size_t size = type_info<Ts...>::size > sizeof(T&) ? type_info<Ts...>::size : sizeof(T&);
static const size_t count = 1 + type_info<Ts...>::count;
static constexpr bool no_reference_types = false;
static constexpr bool no_duplicates = position<T, Ts...>::pos == -1 && type_info<Ts...>::no_duplicates;
static constexpr size_t size = type_info<Ts...>::size > sizeof(T&) ? type_info<Ts...>::size : sizeof(T&);
static constexpr size_t count = 1 + type_info<Ts...>::count;
};
template<typename T, typename... Ts>
struct type_info<T, Ts...> {
static const bool no_reference_types = type_info<Ts...>::no_reference_types;
static const bool no_duplicates = position<T, Ts...>::pos == -1 && type_info<Ts...>::no_duplicates;
static const size_t size = type_info<Ts...>::size > sizeof(T) ? type_info<Ts...>::size : sizeof(T&);
static const size_t count = 1 + type_info<Ts...>::count;
static constexpr bool no_reference_types = type_info<Ts...>::no_reference_types;
static constexpr bool no_duplicates = position<T, Ts...>::pos == -1 && type_info<Ts...>::no_duplicates;
static constexpr size_t size = type_info<Ts...>::size > sizeof(T) ? type_info<Ts...>::size : sizeof(T&);
static constexpr size_t count = 1 + type_info<Ts...>::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<typename TTag>
size_t size( TTag )
constexpr size_t size( TTag )
{
return 0;
}
template<typename TTag, typename A, typename...Ts>
size_t size( TTag tag )
constexpr size_t size( TTag tag )
{
if (tag <= 0)
{
return sizeof(A);
}
return size<TTag, Ts...>( --tag );
return tag <= 0 ? sizeof(A) : size<TTag, Ts...>( --tag );
}
@ -216,17 +211,17 @@ public:
} // namespace impl
template<int L,typename Visitor,typename Data>
static const fc::array<typename Visitor::result_type(*)(Visitor&,Data),L>
static const std::array<typename Visitor::result_type(*)(Visitor&,Data),L>
init_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0)
{
return fc::array<typename Visitor::result_type(*)(Visitor&,Data),L>();
return std::array<typename Visitor::result_type(*)(Visitor&,Data),L>();
}
template<int L,typename Visitor,typename Data,typename T, typename ... Types>
static const fc::array<typename Visitor::result_type(*)(Visitor&,Data),L>
static const std::array<typename Visitor::result_type(*)(Visitor&,Data),L>
init_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 )
{
fc::array<typename Visitor::result_type(*)(Visitor&,Data),L> result{};
std::array<typename Visitor::result_type(*)(Visitor&,Data),L> result{};
if( !funcs ) funcs = result.begin();
*funcs++ = [] ( Visitor& v, Data d ) { return v( *reinterpret_cast<T*>( d ) ); };
init_wrappers<L,Visitor,Data,Types...>( v, d, funcs );
@ -234,17 +229,17 @@ static const fc::array<typename Visitor::result_type(*)(Visitor&,Data),L>
}
template<int L,typename Visitor,typename Data>
static const fc::array<typename Visitor::result_type(*)(Visitor&,Data),L>
static const std::array<typename Visitor::result_type(*)(Visitor&,Data),L>
init_const_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 )
{
return fc::array<typename Visitor::result_type(*)(Visitor&,Data),L>();
return std::array<typename Visitor::result_type(*)(Visitor&,Data),L>();
}
template<int L,typename Visitor,typename Data,typename T, typename ... Types>
static const fc::array<typename Visitor::result_type(*)(Visitor&,Data),L>
static const std::array<typename Visitor::result_type(*)(Visitor&,Data),L>
init_const_wrappers( Visitor& v, Data d, typename Visitor::result_type(**funcs)(Visitor&,Data) = 0 )
{
fc::array<typename Visitor::result_type(*)(Visitor&,Data),L> result{};
std::array<typename Visitor::result_type(*)(Visitor&,Data),L> result{};
if( !funcs ) funcs = result.begin();
*funcs++ = [] ( Visitor& v, Data d ) { return v( *reinterpret_cast<const T*>( d ) ); };
init_const_wrappers<L,Visitor,Data,Types...>( v, d, funcs );
@ -304,7 +299,7 @@ public:
template<typename X, typename = type_in_typelist<X>>
struct tag
{
static const int value = impl::position<X, Types...>::pos;
static constexpr int value = impl::position<X, Types...>::pos;
};
static_variant()
@ -434,7 +429,7 @@ public:
return wrappers[tag]( v, data );
}
static int count() { return impl::type_info<Types...>::count; }
static constexpr int count() { return impl::type_info<Types...>::count; }
void set_which( tag_type w ) {
FC_ASSERT( w >= 0 );
FC_ASSERT( w < count() );

View file

@ -1,9 +1,11 @@
#pragma once
#include <fc/time.hpp>
#include <fc/shared_ptr.hpp>
#include <fc/exception/exception.hpp>
#include <fc/thread/spin_yield_lock.hpp>
#include <fc/optional.hpp>
#include <memory>
#include <boost/atomic.hpp>
//#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<promise_base> {
public:
typedef fc::shared_ptr<promise_base> ptr;
promise_base(const char* desc FC_TASK_NAME_DEFAULT_ARG);
typedef std::shared_ptr<promise_base> 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<typename T = void>
class promise : virtual public promise_base {
public:
typedef fc::shared_ptr< promise<T> > 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<T> > ptr;
virtual ~promise(){}
static ptr create( const char* desc FC_TASK_NAME_DEFAULT_ARG )
{
return ptr( new promise<T>( desc ) );
}
static ptr create( const T& val )
{
return ptr( new promise<T>( val ) );
}
static ptr create( T&& val )
{
return ptr( new promise<T>( std::move(val) ) );
}
const T& wait(const microseconds& timeout = microseconds::maximum() ){
this->_wait( timeout );
return *result;
@ -132,22 +146,32 @@ namespace fc {
template<typename CompletionHandler>
void on_complete( CompletionHandler&& c ) {
_on_complete( new detail::completion_handler_impl<CompletionHandler,T>(fc::forward<CompletionHandler>(c)) );
_on_complete( new detail::completion_handler_impl<CompletionHandler,T>(std::forward<CompletionHandler>(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<T> result;
~promise(){}
};
template<>
class promise<void> : virtual public promise_base {
public:
typedef fc::shared_ptr< promise<void> > 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<void> > ptr;
virtual ~promise(){}
static ptr create( const char* desc FC_TASK_NAME_DEFAULT_ARG )
{
return ptr( new promise<void>( desc ) );
}
static ptr create( bool fulfilled, const char* desc FC_TASK_NAME_DEFAULT_ARG )
{
return ptr( new promise<void>( fulfilled, desc ) );
}
void wait(const microseconds& timeout = microseconds::maximum() ){
this->_wait( timeout );
}
@ -160,10 +184,13 @@ namespace fc {
template<typename CompletionHandler>
void on_complete( CompletionHandler&& c ) {
_on_complete( new detail::completion_handler_impl<CompletionHandler,void>(fc::forward<CompletionHandler>(c)) );
_on_complete( new detail::completion_handler_impl<CompletionHandler,void>(std::forward<CompletionHandler>(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<typename T>
class future {
public:
future( const fc::shared_ptr<promise<T>>& p ):m_prom(p){}
future( fc::shared_ptr<promise<T>>&& p ):m_prom(std::move(p)){}
future( const typename promise<T>::ptr& p ):m_prom(p){}
future( typename promise<T>::ptr&& p ):m_prom(std::move(p)){}
future(const future<T>& 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<typename CompletionHandler>
void on_complete( CompletionHandler&& c ) {
m_prom->on_complete( fc::forward<CompletionHandler>(c) );
m_prom->on_complete( std::forward<CompletionHandler>(c) );
}
private:
friend class thread;
fc::shared_ptr<promise<T>> m_prom;
typename promise<T>::ptr m_prom;
};
template<>
class future<void> {
public:
future( const fc::shared_ptr<promise<void>>& p ):m_prom(p){}
future( fc::shared_ptr<promise<void>>&& p ):m_prom(std::move(p)){}
future( const typename promise<void>::ptr& p ):m_prom(p){}
future( typename promise<void>::ptr&& p ):m_prom(std::move(p)){}
future(const future<void>& f ) : m_prom(f.m_prom){}
future(){}
@ -308,12 +334,12 @@ namespace fc {
template<typename CompletionHandler>
void on_complete( CompletionHandler&& c ) {
m_prom->on_complete( fc::forward<CompletionHandler>(c) );
m_prom->on_complete( std::forward<CompletionHandler>(c) );
}
private:
friend class thread;
fc::shared_ptr<promise<void>> m_prom;
typename promise<void>::ptr m_prom;
};
}

View file

@ -55,8 +55,8 @@ namespace fc {
~ticket_guard();
void wait_for_my_turn();
private:
promise<void>* my_promise;
future<void>* ticket;
promise<void>::ptr my_promise;
future<void>* ticket;
};
friend class ticket_guard;
@ -96,11 +96,12 @@ namespace fc {
template<typename Functor>
auto do_parallel( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG ) -> fc::future<decltype(f())> {
typedef decltype(f()) Result;
typedef typename fc::deduce<Functor>::type FunctorType;
fc::task<Result,sizeof(FunctorType)>* tsk =
new fc::task<Result,sizeof(FunctorType)>( fc::forward<Functor>(f), desc );
fc::future<Result> r(fc::shared_ptr< fc::promise<Result> >(tsk,true) );
detail::get_worker_pool().post( tsk );
typedef typename std::remove_const_t< std::remove_reference_t<Functor> > FunctorType;
typename task<Result,sizeof(FunctorType)>::ptr tsk =
task<Result,sizeof(FunctorType)>::create( std::forward<Functor>(f), desc );
tsk->retain(); // HERE BE DRAGONS
fc::future<Result> r( std::dynamic_pointer_cast< promise<Result> >(tsk) );
detail::get_worker_pool().post( tsk.get() );
return r;
}
}

View file

@ -2,6 +2,7 @@
#include <fc/thread/future.hpp>
#include <fc/thread/priority.hpp>
#include <fc/fwd.hpp>
#include <type_traits>
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<promise_base> _self;
boost::atomic<int32_t> _retain_count;
};
namespace detail {
@ -90,41 +113,57 @@ namespace fc {
template<typename R,uint64_t FunctorSize=64>
class task : virtual public task_base, virtual public promise<R> {
public:
typedef std::shared_ptr<task<R,FunctorSize>> ptr;
virtual ~task(){}
template<typename Functor>
static ptr create( Functor&& f, const char* desc )
{
return ptr( new task<R,FunctorSize>( std::move(f), desc ) );
}
virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); }
private:
template<typename Functor>
task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise<R>(desc) {
typedef typename fc::deduce<Functor>::type FunctorType;
typedef typename std::remove_const_t< std::remove_reference_t<Functor> > FunctorType;
static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" );
new ((char*)&_functor) FunctorType( fc::forward<Functor>(f) );
new ((char*)&_functor) FunctorType( std::forward<Functor>(f) );
_destroy_functor = &detail::functor_destructor<FunctorType>::destroy;
_promise_impl = static_cast<promise<R>*>(this);
_run_functor = &detail::functor_run<FunctorType>::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<uint64_t FunctorSize>
class task<void,FunctorSize> : virtual public task_base, virtual public promise<void> {
class task<void,FunctorSize> : public task_base, public promise<void> {
public:
typedef std::shared_ptr<task<void,FunctorSize>> ptr;
virtual ~task(){}
template<typename Functor>
static ptr create( Functor&& f, const char* desc )
{
return ptr( new task<void,FunctorSize>( std::move(f), desc ) );
}
virtual void cancel(const char* reason FC_CANCELATION_REASON_DEFAULT_ARG) override { task_base::cancel(reason); }
private:
template<typename Functor>
task( Functor&& f, const char* desc ):promise_base(desc), task_base(&_functor), promise<void>(desc) {
typedef typename fc::deduce<Functor>::type FunctorType;
typedef typename std::remove_const_t< std::remove_reference_t<Functor> > FunctorType;
static_assert( sizeof(f) <= sizeof(_functor), "sizeof(Functor) is larger than FunctorSize" );
new ((char*)&_functor) FunctorType( fc::forward<Functor>(f) );
new ((char*)&_functor) FunctorType( std::forward<Functor>(f) );
_destroy_functor = &detail::functor_destructor<FunctorType>::destroy;
_promise_impl = static_cast<promise<void>*>(this);
_run_functor = &detail::void_functor_run<FunctorType>::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];
};
}

View file

@ -86,11 +86,12 @@ namespace fc {
template<typename Functor>
auto async( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future<decltype(f())> {
typedef decltype(f()) Result;
typedef typename fc::deduce<Functor>::type FunctorType;
fc::task<Result,sizeof(FunctorType)>* tsk =
new fc::task<Result,sizeof(FunctorType)>( fc::forward<Functor>(f), desc );
fc::future<Result> r(fc::shared_ptr< fc::promise<Result> >(tsk,true) );
async_task(tsk,prio);
typedef typename std::remove_const_t< std::remove_reference_t<Functor> > FunctorType;
typename task<Result,sizeof(FunctorType)>::ptr tsk =
task<Result,sizeof(FunctorType)>::create( std::forward<Functor>(f), desc );
tsk->retain(); // HERE BE DRAGONS
fc::future<Result> r( std::dynamic_pointer_cast< promise<Result> >(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<decltype(f())> {
typedef decltype(f()) Result;
fc::task<Result,sizeof(Functor)>* tsk =
new fc::task<Result,sizeof(Functor)>( fc::forward<Functor>(f), desc );
fc::future<Result> r(fc::shared_ptr< fc::promise<Result> >(tsk,true) );
async_task(tsk,prio,when);
typename task<Result,sizeof(Functor)>::ptr tsk =
task<Result,sizeof(Functor)>::create( std::forward<Functor>(f), desc );
tsk->retain(); // HERE BE DRAGONS
fc::future<Result> r( std::dynamic_pointer_cast< promise<Result> >(tsk) );
async_task(tsk.get(),prio,when);
return r;
}
@ -147,8 +149,8 @@ namespace fc {
template<typename T1, typename T2>
int wait_any( const fc::future<T1>& f1, const fc::future<T2>& f2, const microseconds& timeout_us = microseconds::maximum()) {
std::vector<fc::promise_base::ptr> proms(2);
proms[0] = fc::static_pointer_cast<fc::promise_base>(f1.m_prom);
proms[1] = fc::static_pointer_cast<fc::promise_base>(f2.m_prom);
proms[0] = std::static_pointer_cast<fc::promise_base>(f1.m_prom);
proms[1] = std::static_pointer_cast<fc::promise_base>(f2.m_prom);
return wait_any_until(std::move(proms), fc::time_point::now()+timeout_us );
}
private:
@ -223,11 +225,11 @@ namespace fc {
template<typename Functor>
auto async( Functor&& f, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future<decltype(f())> {
return fc::thread::current().async( fc::forward<Functor>(f), desc, prio );
return fc::thread::current().async( std::forward<Functor>(f), desc, prio );
}
template<typename Functor>
auto schedule( Functor&& f, const fc::time_point& t, const char* desc FC_TASK_NAME_DEFAULT_ARG, priority prio = priority()) -> fc::future<decltype(f())> {
return fc::thread::current().schedule( fc::forward<Functor>(f), t, desc, prio );
return fc::thread::current().schedule( std::forward<Functor>(f), t, desc, prio );
}
/**

View file

@ -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 <limits>
#ifdef __SIZEOF_INT128__
#include <stdint.h>
#include <string>
#include <fc/config.hpp>
#include <fc/exception/exception.hpp>
#include <fc/crypto/city.hpp>
#include <fc/io/raw.hpp>
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<uint64_t>::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<typename Stream>
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<typename Stream>
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<fc::uint128>
{
size_t operator()( const fc::uint128& s )const;
};
inline uint64_t uint128_lo64(const uint128_t x) {
return static_cast<uint64_t>(x & 0xffffffffffffffffULL);
}
inline uint64_t uint128_hi64(const uint128_t x) {
return static_cast<uint64_t>( x >> 64 );
}
FC_REFLECT( fc::uint128_t, (hi)(lo) )
} // namespace fc
#ifdef _MSC_VER
#pragma warning (pop)
#endif ///_MSC_VER
#else // __SIZEOF_INT128__
#include <boost/multiprecision/integer.hpp>
namespace fc {
using boost::multiprecision::int128_t;
using boost::multiprecision::uint128_t;
inline uint64_t uint128_lo64(const uint128_t& x) {
return static_cast<uint64_t>(x & 0xffffffffffffffffULL);
}
inline uint64_t uint128_hi64(const uint128_t& x) {
return static_cast<uint64_t>( 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

View file

@ -1,41 +0,0 @@
#pragma once
#include <stdint.h>
#include <new>
#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<typename T> struct deduce { typedef T type; };
template<typename T> struct deduce<T&> { typedef T type; };
template<typename T> struct deduce<const T&> { typedef T type; };
template<typename T> struct deduce<T&&> { typedef T type; };
template<typename T> struct deduce<const T&&>{ typedef T type; };
template<typename T, typename U>
inline T&& forward( U&& u ) { return static_cast<T&&>(u); }
struct true_type { enum _value { value = 1 }; };
struct false_type { enum _value { value = 0 }; };
namespace detail {
template<typename T> fc::true_type is_class_helper(void(T::*)());
template<typename T> fc::false_type is_class_helper(...);
}
template<typename T>
struct is_class { typedef decltype(detail::is_class_helper<T>(0)) type; enum value_enum { value = type::value }; };
}

View file

@ -1,5 +1,7 @@
#pragma once
#include <array>
#include <cstddef>
#include <deque>
#include <map>
#include <memory>
@ -11,7 +13,9 @@
#include <string.h> // memset
#include <fc/optional.hpp>
#include <fc/uint128.hpp>
#include <fc/container/flat_fwd.hpp>
#include <fc/crypto/hex.hpp>
#include <boost/endian/buffers.hpp>
#include <boost/multi_index_container_fwd.hpp>
@ -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<typename T>
variant& operator=( T&& v )
{
return *this = variant( fc::forward<T>(v) );
return *this = variant( std::forward<T>(v) );
}
template<typename T>
@ -654,6 +661,36 @@ namespace fc
c.insert( item.as<T>( max_depth - 1 ) );
}
template<size_t N>
void to_variant( const std::array<char,N>& bi, variant& v, uint32_t max_depth = 1 )
{
v = variant( to_hex( bi.data(), N ) );
}
template<size_t N>
void from_variant( const variant& v, std::array<char,N>& bi, uint32_t max_depth = 1 )
{
std::string ve = v.as_string();
if( ve.size() )
from_hex( ve, bi.data(), std::min<size_t>( ve.size() / 2, bi.size() ) );
else
memset( bi.data(), 0, bi.size() );
}
template<size_t N>
void to_variant( const std::array<unsigned char,N>& bi, variant& v, uint32_t max_depth = 1 )
{
v = variant( to_hex( (char*) bi.data(), N ) );
}
template<size_t N>
void from_variant( const variant& v, std::array<unsigned char,N>& bi, uint32_t max_depth = 1 )
{
std::string ve = v.as_string();
if( ve.size() )
from_hex( ve, (char*)bi.data(), std::min<size_t>( 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 );

View file

@ -1,6 +1,6 @@
#pragma once
#include <fc/variant.hpp>
#include <fc/shared_ptr.hpp>
#include <memory>
namespace fc
{
@ -70,7 +70,7 @@ namespace fc
variant_object( string key, T&& val )
:_key_value( std::make_shared<std::vector<entry> >() )
{
*this = variant_object( std::move(key), variant(forward<T>(val)) );
*this = variant_object( std::move(key), variant(std::forward<T>(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<T>(var), max_depth - 1 ) );
set( std::move(key), variant( std::forward<T>(var), max_depth - 1 ) );
return *this;
}
/**
@ -191,7 +191,7 @@ namespace fc
explicit mutable_variant_object( T&& v )
:_key_value( new std::vector<entry>() )
{
*this = variant(fc::forward<T>(v)).get_object();
*this = variant(std::forward<T>(v)).get_object();
}
mutable_variant_object();
@ -202,7 +202,7 @@ namespace fc
mutable_variant_object( string key, T&& val )
:_key_value( new std::vector<entry>() )
{
set( std::move(key), variant(forward<T>(val)) );
set( std::move(key), variant(std::forward<T>(val)) );
}
mutable_variant_object( mutable_variant_object&& );
@ -232,7 +232,7 @@ namespace fc
optional<variant> v;
try
{
v = variant( fc::forward<T>(var), _max_depth );
v = variant( std::forward<T>(var), _max_depth );
}
catch( ... )
{

View file

@ -190,7 +190,7 @@ namespace fc {
try
{
resolver res( fc::asio::default_io_service() );
promise<std::vector<boost::asio::ip::tcp::endpoint> >::ptr p( new promise<std::vector<boost::asio::ip::tcp::endpoint> >("tcp::resolve completion") );
promise<std::vector<boost::asio::ip::tcp::endpoint> >::ptr p = promise<std::vector<boost::asio::ip::tcp::endpoint> >::create("tcp::resolve completion");
res.async_resolve( boost::asio::ip::tcp::resolver::query(hostname,port),
boost::bind( detail::resolve_handler<boost::asio::ip::tcp::endpoint,resolver_iterator>, p, _1, _2 ) );
return p->wait();
@ -204,7 +204,7 @@ namespace fc {
try
{
resolver res( fc::asio::default_io_service() );
promise<std::vector<endpoint> >::ptr p( new promise<std::vector<endpoint> >("udp::resolve completion") );
promise<std::vector<endpoint> >::ptr p = promise<std::vector<endpoint> >::create("udp::resolve completion");
res.async_resolve( resolver::query(hostname,port),
boost::bind( detail::resolve_handler<endpoint,resolver_iterator>, p, _1, _2 ) );
return p->wait();

View file

@ -4,11 +4,11 @@
#include <fc/fwd_impl.hpp>
#include <fc/io/fstream.hpp>
#include <fc/io/raw.hpp>
#include <fc/log/logger.hpp>
#include <fc/thread/thread.hpp>
#include <fc/io/raw.hpp>
#include <boost/endian/buffers.hpp>
#include <boost/thread/mutex.hpp>
#include <openssl/opensslconf.h>
@ -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",

View file

@ -31,10 +31,9 @@
//#include <city.h>
#include <algorithm>
#include <array>
#include <string.h> // for memcpy and memset
#include <fc/crypto/city.hpp>
#include <fc/uint128.hpp>
#include <fc/array.hpp>
#include <boost/endian/buffers.hpp>
#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<uint64_t, uint64_t> 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<uint64_t,4> 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] );
}
}

View file

@ -19,7 +19,7 @@
namespace fc { namespace ecc {
namespace detail {
typedef fc::array<char,37> chr37;
typedef std::array<unsigned char,37> 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<char, 37> 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<char, 37> 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 );
}

View file

@ -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<char,37> chr37;
typedef std::array<char,37> 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<const unsigned char*> 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<commitment_type>& commits_in, const std::vector<commitment_type>& neg_commits_in, int64_t excess )
{
std::vector<const unsigned char*> 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<const unsigned char*> 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<char>& 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<char> range_proof_sign( uint64_t min_value,
@ -245,12 +246,12 @@ namespace fc { namespace ecc {
int proof_len = 5134;
std::vector<char> 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() ) );

View file

@ -96,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(); }
@ -217,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() )
@ -229,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 );
}

View file

@ -1,7 +1,7 @@
#include <fc/io/datastream.hpp>
#include <fc/exception/exception.hpp>
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) );
}

View file

@ -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;
};

View file

@ -24,7 +24,7 @@ namespace fc {
std::cin.read(&c,1);
while( !std::cin.eof() ) {
while( write_pos - read_pos > 0xfffff ) {
fc::promise<void>::ptr wr( new fc::promise<void>("cin_buffer::write_ready") );
fc::promise<void>::ptr wr = fc::promise<void>::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<void>::ptr rr( new fc::promise<void>("cin_buffer::read_ready") );
fc::promise<void>::ptr rr = fc::promise<void>::create("cin_buffer::read_ready");
{ // copy read_ready because it is accessed from multiple threads
fc::scoped_lock<boost::mutex> lock( b.read_ready_mutex );
b.read_ready = rr;

View file

@ -13,7 +13,7 @@
namespace fc {
class file_appender::impl : public fc::retainable
class file_appender::impl
{
public:
config cfg;

View file

@ -20,7 +20,7 @@
namespace fc
{
class gelf_appender::impl : public retainable
class gelf_appender::impl
{
public:
config cfg;

View file

@ -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,13 +96,10 @@ 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<appender>& a )
void logger::add_appender( const appender::ptr& a )
{ my->_appenders.push_back(a); }
// void logger::remove_appender( const fc::shared_ptr<appender>& a )
// { my->_appenders.erase(a); }
std::vector<fc::shared_ptr<appender> > logger::get_appenders()const
std::vector<appender::ptr> logger::get_appenders()const
{
return my->_appenders;
}

View file

@ -1,207 +0,0 @@
#include <fc/network/http/server.hpp>
#include <fc/thread/thread.hpp>
#include <fc/network/tcp_socket.hpp>
#include <fc/io/sstream.hpp>
#include <fc/network/ip.hpp>
#include <fc/io/stdio.hpp>
#include <fc/log/logger.hpp>
namespace fc { namespace http {
class server::response::impl : public fc::retainable
{
public:
impl( const fc::http::connection_ptr& c, const std::function<void()>& cont = std::function<void()>() )
: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 <<": "<<rep.headers[i].val <<"\r\n";
}
ss << "Content-Length: "<<body_length<<"\r\n\r\n";
auto s = ss.str();
//fc::cerr<<s<<"\n";
con->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<void()> 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<void>& 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<http::connection>();
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<void(const http::request&, const server::response& s )> do_on_req )
{
try
{
http::server::response rep( fc::shared_ptr<response::impl>( 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<void> accept_complete;
std::function<void(const http::request&, const server::response& s)> on_req;
std::vector<fc::future<void> > 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<server::response::impl>& 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<size_t>(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<void()>(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<void(const http::request&, const server::response& s )>& cb )
{
my->on_req = cb;
}
} }

View file

@ -292,8 +292,8 @@ namespace fc { namespace http {
if( _server.is_listening() )
_server.stop_listening();
if ( _connections.size() )
_closed = new fc::promise<void>();
if( _connections.size() )
_closed = promise<void>::create();
auto cpy_con = _connections;
for( auto item : cpy_con )
@ -642,13 +642,13 @@ namespace fc { namespace http {
websocketpp::lib::error_code ec;
my->_uri = uri;
my->_connected = fc::promise<void>::ptr( new fc::promise<void>("websocket::connect") );
my->_connected = promise<void>::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<detail::websocket_connection_impl<detail::websocket_client_connection_type>>( con );
my->_closed = fc::promise<void>::ptr( new fc::promise<void>("websocket::closed") );
my->_closed = promise<void>::create("websocket::closed");
my->_connected->set_value();
});
@ -670,12 +670,12 @@ namespace fc { namespace http {
websocketpp::lib::error_code ec;
smy->_uri = uri;
smy->_connected = fc::promise<void>::ptr( new fc::promise<void>("websocket::connect") );
smy->_connected = promise<void>::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<detail::websocket_connection_impl<detail::websocket_tls_client_connection_type>>( con );
smy->_closed = fc::promise<void>::ptr( new fc::promise<void>("websocket::closed") );
smy->_closed = promise<void>::create("websocket::closed");
smy->_connected->set_value();
});
@ -705,12 +705,12 @@ namespace fc { namespace http {
// wlog( "connecting to ${uri}", ("uri",uri));
websocketpp::lib::error_code ec;
my->_connected = fc::promise<void>::ptr( new fc::promise<void>("websocket::connect") );
my->_connected = promise<void>::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<detail::websocket_connection_impl<detail::websocket_tls_client_connection_type>>( con );
my->_closed = fc::promise<void>::ptr( new fc::promise<void>("websocket::closed") );
my->_closed = promise<void>::create("websocket::closed");
my->_connected->set_value();
});

View file

@ -284,7 +284,7 @@ namespace fc
size_t bytes_read;
if (_download_bytes_per_second)
{
promise<size_t>::ptr completion_promise(new promise<size_t>("rate_limiting_group_impl::readsome"));
promise<size_t>::ptr completion_promise = promise<size_t>::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<size_t>::ptr completion_promise(new promise<size_t>("rate_limiting_group_impl::writesome"));
promise<size_t>::ptr completion_promise = promise<size_t>::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<void>("rate_limiting_group_impl::process_pending_reads");
_new_read_operation_available_promise = promise<void>::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<void>("rate_limiting_group_impl::process_pending_writes");
_new_write_operation_available_promise = promise<void>::create("rate_limiting_group_impl::process_pending_writes");
try
{
if (_write_operations_in_progress.empty())

View file

@ -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<size_t>::ptr completion_promise(new promise<size_t>("udp_socket::send_to"));
promise<size_t>::ptr completion_promise = promise<size_t>::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<size_t>::ptr completion_promise(new promise<size_t>("udp_socket::send_to"));
promise<size_t>::ptr completion_promise = promise<size_t>::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<size_t>::ptr completion_promise(new promise<size_t>("udp_socket::receive_from"));
promise<size_t>::ptr completion_promise = promise<size_t>::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<size_t>::ptr completion_promise(new promise<size_t>("udp_socket::receive_from"));
promise<size_t>::ptr completion_promise = promise<size_t>::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();

54
src/popcount.cpp Normal file
View file

@ -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 <fc/popcount.hpp>
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<uint64_t>(v >> 64) )
+ popcount( static_cast<uint64_t>(v & 0xffffffffffffffffULL) );
}
} // namespace fc

View file

@ -1,130 +0,0 @@
#include <fc/real128.hpp>
#include <fc/crypto/bigint.hpp>
#include <fc/exception/exception.hpp>
#include <sstream>
#include <stdint.h>
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

View file

@ -1,141 +0,0 @@
#include <fc/rpc/http_api.hpp>
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<fc::rpc::request>(_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

View file

@ -46,7 +46,7 @@ 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<variant>::ptr( new fc::promise<variant>("json_connection::async_call") );
_awaiting[*request.id] = fc::promise<variant>::create("json_connection::async_call");
return request;
}
variant state::wait_for_response( const variant& request_id )

View file

@ -1,30 +0,0 @@
#include <fc/shared_ptr.hpp>
#include <boost/atomic.hpp>
#include <boost/memory_order.hpp>
#include <assert.h>
namespace fc {
retainable::retainable()
:_ref_count(1) {
static_assert( sizeof(_ref_count) == sizeof(boost::atomic<int32_t>), "failed to reserve enough space" );
}
retainable::~retainable() {
assert( _ref_count <= 0 );
assert( _ref_count == 0 );
}
void retainable::retain() {
((boost::atomic<int32_t>*)&_ref_count)->fetch_add(1, boost::memory_order_relaxed );
}
void retainable::release() {
boost::atomic_thread_fence(boost::memory_order_acquire);
if( 1 == ((boost::atomic<int32_t>*)&_ref_count)->fetch_sub(1, boost::memory_order_release ) ) {
delete this;
}
}
int32_t retainable::retain_count()const {
return _ref_count;
}
}

View file

@ -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(){

View file

@ -158,8 +158,8 @@ namespace fc {
serial_valve::ticket_guard::ticket_guard( boost::atomic<future<void>*>& latch )
{
my_promise = new promise<void>();
future<void>* my_future = new future<void>( promise<void>::ptr( my_promise, true ) );
my_promise = promise<void>::create();
future<void>* my_future = new future<void>( 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<void>( promise<void>::ptr( new promise<void>( true ), true ) ) );
latch.store( new future<void>( promise<void>::create( true ) ) );
}
serial_valve::~serial_valve()

View file

@ -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();
}
}

View file

@ -72,7 +72,7 @@ namespace fc {
}
thread::thread( const std::string& name, thread_idle_notifier* notifier ) {
promise<void>::ptr p(new promise<void>("thread start"));
promise<void>::ptr p = promise<void>::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

View file

@ -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<task_base> 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();
}

View file

@ -1,398 +0,0 @@
#include <fc/uint128.hpp>
#include <fc/variant.hpp>
#include <fc/crypto/bigint.hpp>
#include <boost/endian/buffers.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <stdexcept>
namespace fc
{
typedef boost::multiprecision::uint128_t m128;
template <typename T>
static void divide(const T &numerator, const T &denominator, T &quotient, 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<uint64_t>(self >> 64);
lo = static_cast<uint64_t>((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<fc::uint128>::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.
*/

View file

@ -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,6 +673,16 @@ void from_variant( const variant& var, std::vector<char>& vo, uint32_t max_depth
}
}
void to_variant( const uint128_t& var, variant& vo, uint32_t max_depth )
{
vo = boost::lexical_cast<std::string>( var );
}
void from_variant( const variant& var, uint128_t& vo, uint32_t max_depth )
{
vo = boost::lexical_cast<uint128_t>( 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) ); }

View file

@ -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 )
@ -44,7 +41,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

View file

@ -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) {

View file

@ -1,12 +1,13 @@
#define BOOST_TEST_MODULE HmacTest
#include <boost/test/unit_test.hpp>
#include <fc/array.hpp>
#include <fc/crypto/hex.hpp>
#include <fc/crypto/hmac.hpp>
#include <fc/crypto/sha224.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/crypto/sha512.hpp>
#include <array>
// 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<char,N> key_arr;
std::array<char,N> key_arr;
BOOST_CHECK_EQUAL( fc::from_hex( key, key_arr.begin(), key_arr.size() ), N );
fc::array<char,M> data_arr;
std::array<char,M> 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 );

View file

@ -1,55 +0,0 @@
#include <fc/real128.hpp>
#include <boost/test/unit_test.hpp>
#include <fc/log/logger.hpp>
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()

View file

@ -200,25 +200,25 @@ BOOST_AUTO_TEST_CASE( serial_valve )
fc::serial_valve valve;
{ // Simple test, f2 finishes before f1
fc::promise<void>* syncer = new fc::promise<void>();
fc::promise<void>* waiter = new fc::promise<void>();
fc::promise<void>::ptr syncer = fc::promise<void>::create();
fc::promise<void>::ptr waiter = fc::promise<void>::create();
auto p1 = fc::async([&counter,&valve,syncer,waiter] () {
valve.do_serial( [syncer,waiter](){ syncer->set_value();
fc::future<void>( fc::shared_ptr<fc::promise<void>>( waiter, true ) ).wait(); },
fc::future<void>( waiter ).wait(); },
[&counter](){ BOOST_CHECK_EQUAL( 0u, counter.load() );
counter.fetch_add(1); } );
});
fc::future<void>( fc::shared_ptr<fc::promise<void>>( syncer, true ) ).wait();
fc::future<void>( syncer ).wait();
// at this point, p1.f1 has started executing and is waiting on waiter
syncer = new fc::promise<void>();
syncer = fc::promise<void>::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<void>( fc::shared_ptr<fc::promise<void>>( syncer, true ) ).wait();
fc::future<void>( 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<void>* syncer = new fc::promise<void>();
fc::promise<void>* waiter = new fc::promise<void>();
fc::promise<void>::ptr syncer = fc::promise<void>::create();
fc::promise<void>::ptr waiter = fc::promise<void>::create();
counter.store(0);
auto p1 = fc::async([&counter,&valve,syncer,waiter] () {
valve.do_serial( [&syncer,waiter](){ syncer->set_value();
fc::future<void>( fc::shared_ptr<fc::promise<void>>( waiter, true ) ).wait(); },
fc::future<void>( waiter ).wait(); },
[&counter](){ BOOST_CHECK_EQUAL( 0u, counter.load() );
counter.fetch_add(1); } );
});
fc::future<void>( fc::shared_ptr<fc::promise<void>>( syncer, true ) ).wait();
fc::future<void>( syncer ).wait();
// at this point, p1.f1 has started executing and is waiting on waiter
syncer = new fc::promise<void>();
syncer = fc::promise<void>::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<void>( fc::shared_ptr<fc::promise<void>>( syncer, true ) ).wait();
fc::future<void>( syncer ).wait();
// at this point, p2.f1 has started executing and is sleeping
syncer = new fc::promise<void>();
syncer = fc::promise<void>::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<void>( fc::shared_ptr<fc::promise<void>>( syncer, true ) ).wait();
fc::future<void>( 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<void>* syncer = new fc::promise<void>();
fc::promise<void>* waiter = new fc::promise<void>();
fc::promise<void>::ptr syncer = fc::promise<void>::create();
fc::promise<void>::ptr waiter = fc::promise<void>::create();
counter.store(0);
auto p1 = fc::do_parallel([&counter,&valve,syncer,waiter] () {
valve.do_serial( [&syncer,waiter](){ syncer->set_value();
fc::future<void>( fc::shared_ptr<fc::promise<void>>( waiter, true ) ).wait(); },
fc::future<void>( waiter ).wait(); },
[&counter](){ BOOST_CHECK_EQUAL( 0u, counter.load() );
counter.fetch_add(1); } );
});
fc::future<void>( fc::shared_ptr<fc::promise<void>>( syncer, true ) ).wait();
fc::future<void>( syncer ).wait();
// at this point, p1.f1 has started executing and is waiting on waiter
syncer = new fc::promise<void>();
syncer = fc::promise<void>::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<void>( fc::shared_ptr<fc::promise<void>>( syncer, true ) ).wait();
fc::future<void>( syncer ).wait();
// at this point, p2.f1 has started executing and is sleeping
syncer = new fc::promise<void>();
syncer = fc::promise<void>::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<void>( fc::shared_ptr<fc::promise<void>>( syncer, true ) ).wait();
fc::future<void>( syncer ).wait();
fc::usleep( fc::milliseconds(10) );

View file

@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE( cancel_a_task_waiting_on_promise )
{
enum task_result{task_completed, task_aborted};
fc::promise<void>::ptr promise_to_wait_on(new fc::promise<void>());
fc::promise<void>::ptr promise_to_wait_on = fc::promise<void>::create();
fc::future<task_result> task = fc::async([promise_to_wait_on]() {
BOOST_TEST_MESSAGE("Starting async task");