diff --git a/test/endpoint/endpoint.cpp b/test/endpoint/endpoint.cpp index 08b0560..a48c535 100644 --- a/test/endpoint/endpoint.cpp +++ b/test/endpoint/endpoint.cpp @@ -57,6 +57,33 @@ BOOST_AUTO_TEST_CASE( initialize_server_asio_external ) { s.init_asio(&ios); } +#ifdef _WEBSOCKETPP_MOVE_SEMANTICS_ +BOOST_AUTO_TEST_CASE( move_construct_server_core ) { + websocketpp::server s1; + + websocketpp::server s2(std::move(s1)); +} + +BOOST_AUTO_TEST_CASE( emplace ) { + std::stringstream out1; + std::stringstream out2; + + std::vector> v; + + v.emplace_back(); + v.emplace_back(); + + v[0].get_alog().set_ostream(&out1); + v[0].get_alog().set_ostream(&out2); + + v[0].get_alog().write(websocketpp::log::alevel::app,"devel0"); + v[1].get_alog().write(websocketpp::log::alevel::app,"devel1"); + BOOST_CHECK( out1.str().size() > 0 ); + BOOST_CHECK( out2.str().size() > 0 ); +} + +#endif // _WEBSOCKETPP_MOVE_SEMANTICS_ + struct endpoint_extension { endpoint_extension() : extension_value(5) {} diff --git a/test/logger/basic.cpp b/test/logger/basic.cpp index de51e5a..dd8d6b4 100644 --- a/test/logger/basic.cpp +++ b/test/logger/basic.cpp @@ -34,6 +34,8 @@ #include #include +typedef websocketpp::log::basic basic_access_log_type; + BOOST_AUTO_TEST_CASE( is_token_char ) { typedef websocketpp::log::basic error_log; @@ -79,3 +81,61 @@ BOOST_AUTO_TEST_CASE( basic_concurrency ) { //std::cout << "|" << out.str() << "|" << std::endl; BOOST_CHECK( out.str().size() > 0 ); } + + +BOOST_AUTO_TEST_CASE( copy_constructor ) { + std::stringstream out; + + basic_access_log_type logger1(0xffffffff,&out); + basic_access_log_type logger2(logger1); + + logger2.set_channels(0xffffffff); + logger2.write(websocketpp::log::alevel::devel,"devel"); + BOOST_CHECK( out.str().size() > 0 ); +} + +BOOST_AUTO_TEST_CASE( move_constructor ) { + std::stringstream out; + + basic_access_log_type logger1(0xffffffff,&out); + basic_access_log_type logger2(std::move(logger1)); + + logger2.set_channels(0xffffffff); + logger2.write(websocketpp::log::alevel::devel,"devel"); + BOOST_CHECK( out.str().size() > 0 ); +} + +#ifdef _WEBSOCKETPP_MOVE_SEMANTICS_ +BOOST_AUTO_TEST_CASE( emplace ) { + std::stringstream out1; + std::stringstream out2; + + std::vector v; + + v.emplace_back(websocketpp::log::level(0xffffffff),&out1); + v.emplace_back(websocketpp::log::level(0xffffffff),&out2); + + v[0].set_channels(0xffffffff); + v[1].set_channels(0xffffffff); + v[0].write(websocketpp::log::alevel::devel,"devel"); + v[1].write(websocketpp::log::alevel::devel,"devel"); + BOOST_CHECK( out1.str().size() > 0 ); + BOOST_CHECK( out2.str().size() > 0 ); +} +#endif // #ifdef _WEBSOCKETPP_MOVE_SEMANTICS_ + +// As long as there are const member variables these can't exist +// These remain commented as they are useful for testing the deleted operators +/*BOOST_AUTO_TEST_CASE( copy_assign ) { + basic_access_log_type logger1; + basic_access_log_type logger2; + + logger2 = logger1; +} + +BOOST_AUTO_TEST_CASE( move_assign ) { + basic_access_log_type logger1; + basic_access_log_type logger2; + + logger2 = std::move(logger1); +}*/ \ No newline at end of file diff --git a/test/transport/integration.cpp b/test/transport/integration.cpp index 1d2e7e7..f886fbf 100644 --- a/test/transport/integration.cpp +++ b/test/transport/integration.cpp @@ -607,3 +607,11 @@ BOOST_AUTO_TEST_CASE( pause_reading ) { BOOST_AUTO_TEST_CASE( server_connection_cleanup ) { server_tls s; } + +#ifdef _WEBSOCKETPP_MOVE_SEMANTICS_ +BOOST_AUTO_TEST_CASE( move_construct_transport ) { + server s1; + + server s2(std::move(s1)); +} +#endif // _WEBSOCKETPP_MOVE_SEMANTICS_ diff --git a/websocketpp/common/cpp11.hpp b/websocketpp/common/cpp11.hpp index 6c79d64..a150de3 100644 --- a/websocketpp/common/cpp11.hpp +++ b/websocketpp/common/cpp11.hpp @@ -80,6 +80,12 @@ #ifndef _WEBSOCKETPP_NULLPTR_TOKEN_ #define _WEBSOCKETPP_NULLPTR_TOKEN_ nullptr #endif + #ifndef _WEBSOCKETPP_MOVE_SEMANTICS_ + #define _WEBSOCKETPP_MOVE_SEMANTICS_ + #endif + #ifndef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + #define _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + #endif #ifndef __GNUC__ // GCC as of version 4.9 (latest) does not support std::put_time yet. diff --git a/websocketpp/endpoint.hpp b/websocketpp/endpoint.hpp index 467f0d8..91e17ea 100644 --- a/websocketpp/endpoint.hpp +++ b/websocketpp/endpoint.hpp @@ -104,6 +104,56 @@ public: transport_type::init_logging(&m_alog, &m_elog); } + + /// Destructor + ~endpoint() {} + + #ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + // no copy constructor because endpoints are not copyable + endpoint(endpoint &) = delete; + + // no copy assignment operator because endpoints are not copyable + endpoint & operator=(endpoint const &) = delete; + #endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + + #ifdef _WEBSOCKETPP_MOVE_SEMANTICS_ + /// Move constructor + endpoint(endpoint && o) + : config::transport_type(std::move(o)) + , config::endpoint_base(std::move(o)) + , m_alog(std::move(o.m_alog)) + , m_elog(std::move(o.m_elog)) + , m_user_agent(std::move(o.m_user_agent)) + , m_open_handler(std::move(o.m_open_handler)) + + , m_close_handler(std::move(o.m_close_handler)) + , m_fail_handler(std::move(o.m_fail_handler)) + , m_ping_handler(std::move(o.m_ping_handler)) + , m_pong_handler(std::move(o.m_pong_handler)) + , m_pong_timeout_handler(std::move(o.m_pong_timeout_handler)) + , m_interrupt_handler(std::move(o.m_interrupt_handler)) + , m_http_handler(std::move(o.m_http_handler)) + , m_validate_handler(std::move(o.m_validate_handler)) + , m_message_handler(std::move(o.m_message_handler)) + + , m_open_handshake_timeout_dur(o.m_open_handshake_timeout_dur) + , m_close_handshake_timeout_dur(o.m_close_handshake_timeout_dur) + , m_pong_timeout_dur(o.m_pong_timeout_dur) + , m_max_message_size(o.m_max_message_size) + , m_max_http_body_size(o.m_max_http_body_size) + + , m_rng(std::move(o.m_rng)) + , m_is_server(o.m_is_server) + {} + + #ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + // no move assignment operator because of const member variables + endpoint & operator=(endpoint &&) = delete; + #endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + + #endif // _WEBSOCKETPP_MOVE_SEMANTICS_ + + /// Returns the user agent string that this endpoint will use /** * Returns the user agent string that this endpoint will use when creating diff --git a/websocketpp/logger/basic.hpp b/websocketpp/logger/basic.hpp index 95099a8..8451413 100644 --- a/websocketpp/logger/basic.hpp +++ b/websocketpp/logger/basic.hpp @@ -80,6 +80,36 @@ public: , m_dynamic_channels(0) , m_out(out) {} + /// Destructor + ~basic() {} + + /// Copy constructor + basic(basic const & other) + : m_static_channels(other.m_static_channels) + , m_dynamic_channels(other.m_dynamic_channels) + , m_out(other.m_out) + {} + +#ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + // no copy assignment operator because of const member variables + basic & operator=(basic const &) = delete; +#endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + +#ifdef _WEBSOCKETPP_MOVE_SEMANTICS_ + /// Move constructor + basic(basic && other) + : m_static_channels(other.m_static_channels) + , m_dynamic_channels(other.m_dynamic_channels) + , m_out(other.m_out) + {} + +#ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + // no move assignment operator because of const member variables + basic & operator=(basic &&) = delete; +#endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + +#endif // _WEBSOCKETPP_MOVE_SEMANTICS_ + void set_ostream(std::ostream * out = &std::cout) { m_out = out; } diff --git a/websocketpp/roles/server_endpoint.hpp b/websocketpp/roles/server_endpoint.hpp index 45a4bef..dadcf72 100644 --- a/websocketpp/roles/server_endpoint.hpp +++ b/websocketpp/roles/server_endpoint.hpp @@ -69,6 +69,28 @@ public: endpoint_type::m_alog.write(log::alevel::devel, "server constructor"); } + /// Destructor + ~server() {} + +#ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + // no copy constructor because endpoints are not copyable + server(server &) = delete; + + // no copy assignment operator because endpoints are not copyable + server & operator=(server const &) = delete; +#endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + +#ifdef _WEBSOCKETPP_MOVE_SEMANTICS_ + /// Move constructor + server(server && o) : endpoint,config>(std::move(o)) {} + +#ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + // no move assignment operator because of const member variables + server & operator=(server &&) = delete; +#endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + +#endif // _WEBSOCKETPP_MOVE_SEMANTICS_ + /// Create and initialize a new connection /** * The connection will be initialized and ready to begin. Call its start() diff --git a/websocketpp/transport/asio/endpoint.hpp b/websocketpp/transport/asio/endpoint.hpp index ef3b07d..08512a3 100644 --- a/websocketpp/transport/asio/endpoint.hpp +++ b/websocketpp/transport/asio/endpoint.hpp @@ -113,23 +113,28 @@ public: /// transport::asio objects are moveable but not copyable or assignable. /// The following code sets this situation up based on whether or not we /// have C++11 support or not -#ifdef _WEBSOCKETPP_DELETED_FUNCTIONS_ - endpoint(const endpoint& src) = delete; +#ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ + endpoint(const endpoint & src) = delete; endpoint& operator= (const endpoint & rhs) = delete; #else private: - endpoint(const endpoint& src); - endpoint& operator= (const endpoint & rhs); + endpoint(const endpoint & src); + endpoint & operator= (const endpoint & rhs); public: -#endif +#endif // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_ -#ifdef _WEBSOCKETPP_RVALUE_REFERENCES_ - endpoint (endpoint&& src) - : m_io_service(src.m_io_service) +#ifdef _WEBSOCKETPP_MOVE_SEMANTICS_ + endpoint (endpoint && src) + : config::socket_type(std::move(src)) + , m_tcp_pre_init_handler(src.m_tcp_pre_init_handler) + , m_tcp_post_init_handler(src.m_tcp_post_init_handler) + , m_io_service(src.m_io_service) , m_external_io_service(src.m_external_io_service) , m_acceptor(src.m_acceptor) , m_listen_backlog(boost::asio::socket_base::max_connections) , m_reuse_addr(src.m_reuse_addr) + , m_elog(src.m_elog) + , m_alog(src.m_alog) , m_state(src.m_state) { src.m_io_service = NULL; @@ -138,7 +143,7 @@ public: src.m_state = UNINITIALIZED; } - endpoint& operator= (const endpoint && rhs) { + /*endpoint & operator= (const endpoint && rhs) { if (this != &rhs) { m_io_service = rhs.m_io_service; m_external_io_service = rhs.m_external_io_service; @@ -152,10 +157,13 @@ public: rhs.m_acceptor = NULL; rhs.m_listen_backlog = boost::asio::socket_base::max_connections; rhs.m_state = UNINITIALIZED; + + // TODO: this needs to be updated } return *this; - } -#endif + }*/ +#endif // _WEBSOCKETPP_MOVE_SEMANTICS_ + /// Return whether or not the endpoint produces secure connections. bool is_secure() const { return socket_type::is_secure();