diff --git a/CMakeLists.txt b/CMakeLists.txt index 3105407..ed581cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,7 @@ set( sources src/pke.cpp src/base64.cpp src/udp_socket.cpp + src/asio.cpp ) setup_library( fc SOURCES ${sources} ) diff --git a/include/fc/signals.hpp b/include/fc/signals.hpp new file mode 100644 index 0000000..c28c8c6 --- /dev/null +++ b/include/fc/signals.hpp @@ -0,0 +1,25 @@ +#ifndef _FC_SIGNALS_HPP +#define _FC_SIGNALS_HPP +#include +#include +#include + +namespace fc { + template + using signal = boost::signal; + + template + inline T wait( boost::signal& sig, const microseconds& timeout_us=microseconds::max() ) { + typename promise::ptr p(new promise()); + boost::signals::scoped_connection c = sig.connect( [=]( T t ) { p->set_value(t); } ); + return p->wait( timeout_us ); + } + + inline void wait( boost::signal& sig, const microseconds& timeout_us=microseconds::max() ) { + promise::ptr p(new promise()); + boost::signals::scoped_connection c = sig.connect( [=]() { p->set_value(); } ); + p->wait( timeout_us ); + } +} + +#endif diff --git a/include/fc/time.hpp b/include/fc/time.hpp index 6f0d853..247297e 100644 --- a/include/fc/time.hpp +++ b/include/fc/time.hpp @@ -16,6 +16,7 @@ namespace fc { int64_t _count; }; inline microseconds seconds( int64_t s ) { return microseconds( s * 1000000 ); } + inline microseconds milliseconds( int64_t s ) { return microseconds( s * 1000 ); } class time_point { public: diff --git a/src/asio.cpp b/src/asio.cpp new file mode 100644 index 0000000..9a2e0c2 --- /dev/null +++ b/src/asio.cpp @@ -0,0 +1,71 @@ +#include +#include +#include + +namespace fc { + namespace asio { + namespace detail { + void read_write_handler( const promise::ptr& p, const boost::system::error_code& ec, size_t bytes_transferred ) { + if( !ec ) p->set_value(bytes_transferred); + else p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) ); + } + void read_write_handler_ec( promise* p, boost::system::error_code* oec, const boost::system::error_code& ec, size_t bytes_transferred ) { + p->set_value(bytes_transferred); + *oec = ec; + } + void error_handler( const promise::ptr& p, + const boost::system::error_code& ec ) { + p->set_value(ec); + } + + void error_handler_ec( promise* p, + const boost::system::error_code& ec ) { + p->set_value(ec); + } + + template + void resolve_handler( + const typename promise >::ptr& p, + const boost::system::error_code& ec, + IteratorType itr) { + if( !ec ) { + std::vector eps; + while( itr != IteratorType() ) { + eps.push_back(*itr); + ++itr; + } + p->set_value( eps ); + } else { + p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) ); + } + } + } + boost::asio::io_service& default_io_service() { + static boost::asio::io_service* io = new boost::asio::io_service(); + static boost::asio::io_service::work the_work(*io); + static boost::thread io_t([=] { fc::thread::current().set_name("asio1"); io->run(); }); + static boost::thread io_t2([=]{ fc::thread::current().set_name("asio2"); io->run(); }); + static boost::thread io_t3([=]{ fc::thread::current().set_name("asio3"); io->run(); }); + return *io; + } + + namespace tcp { + std::vector resolve( const std::string& hostname, const std::string& port) { + resolver res( fc::asio::default_io_service() ); + promise >::ptr p( new promise >() ); + res.async_resolve( boost::asio::ip::tcp::resolver::query(hostname,port), + boost::bind( detail::resolve_handler, p, _1, _2 ) ); + return p->wait();; + } + } + namespace udp { + std::vector resolve( resolver& r, const std::string& hostname, const std::string& port) { + resolver res( fc::asio::default_io_service() ); + promise >::ptr p( new promise >() ); + res.async_resolve( resolver::query(hostname,port), + boost::bind( detail::resolve_handler, p, _1, _2 ) ); + return p->wait(); + } + } + +} } // namespace fc::asio diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index c178151..bd5eb64 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -74,7 +74,7 @@ namespace fc { } } void udp_socket::close() { - my->_sock->cancel(); + my->_sock.cancel(); my->_sock.close(); }