diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-10-30 12:57:26 -0700 |
commit | 1a78a62555be32868418fe52f8e330c9d0f95d5a (patch) | |
tree | d3765a80e7d3b9640ec2e930743630cd6b9fce2b /doc/html/boost_asio/example/services | |
download | boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.gz boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.bz2 boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.zip |
Imported Upstream version 1.49.0upstream/1.49.0
Diffstat (limited to 'doc/html/boost_asio/example/services')
6 files changed, 705 insertions, 0 deletions
diff --git a/doc/html/boost_asio/example/services/basic_logger.hpp b/doc/html/boost_asio/example/services/basic_logger.hpp new file mode 100755 index 0000000000..1bc3540ca4 --- /dev/null +++ b/doc/html/boost_asio/example/services/basic_logger.hpp @@ -0,0 +1,83 @@ +// +// basic_logger.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef SERVICES_BASIC_LOGGER_HPP +#define SERVICES_BASIC_LOGGER_HPP + +#include <boost/asio.hpp> +#include <boost/noncopyable.hpp> +#include <string> + +namespace services { + +/// Class to provide simple logging functionality. Use the services::logger +/// typedef. +template <typename Service> +class basic_logger + : private boost::noncopyable +{ +public: + /// The type of the service that will be used to provide timer operations. + typedef Service service_type; + + /// The native implementation type of the timer. + typedef typename service_type::impl_type impl_type; + + /// Constructor. + /** + * This constructor creates a logger. + * + * @param io_service The io_service object used to locate the logger service. + * + * @param identifier An identifier for this logger. + */ + explicit basic_logger(boost::asio::io_service& io_service, + const std::string& identifier) + : service_(boost::asio::use_service<Service>(io_service)), + impl_(service_.null()) + { + service_.create(impl_, identifier); + } + + /// Destructor. + ~basic_logger() + { + service_.destroy(impl_); + } + + /// Get the io_service associated with the object. + boost::asio::io_service& get_io_service() + { + return service_.get_io_service(); + } + + /// Set the output file for all logger instances. + void use_file(const std::string& file) + { + service_.use_file(impl_, file); + } + + /// Log a message. + void log(const std::string& message) + { + service_.log(impl_, message); + } + +private: + /// The backend service implementation. + service_type& service_; + + /// The underlying native implementation. + impl_type impl_; +}; + +} // namespace services + +#endif // SERVICES_BASIC_LOGGER_HPP diff --git a/doc/html/boost_asio/example/services/daytime_client.cpp b/doc/html/boost_asio/example/services/daytime_client.cpp new file mode 100755 index 0000000000..e54ee89c90 --- /dev/null +++ b/doc/html/boost_asio/example/services/daytime_client.cpp @@ -0,0 +1,85 @@ +// +// daytime_client.cpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <boost/asio.hpp> +#include <boost/bind.hpp> +#include <iostream> +#include "logger.hpp" +#include "stream_socket_service.hpp" + +typedef boost::asio::basic_stream_socket<boost::asio::ip::tcp, + services::stream_socket_service<boost::asio::ip::tcp> > debug_stream_socket; + +char read_buffer[1024]; + +void read_handler(const boost::system::error_code& e, + std::size_t bytes_transferred, debug_stream_socket* s) +{ + if (!e) + { + std::cout.write(read_buffer, bytes_transferred); + + s->async_read_some(boost::asio::buffer(read_buffer), + boost::bind(read_handler, boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred, s)); + } +} + +void connect_handler(const boost::system::error_code& e, debug_stream_socket* s) +{ + if (!e) + { + s->async_read_some(boost::asio::buffer(read_buffer), + boost::bind(read_handler, boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred, s)); + } + else + { + std::cerr << e.message() << std::endl; + } +} + +int main(int argc, char* argv[]) +{ + try + { + if (argc != 2) + { + std::cerr << "Usage: daytime_client <host>" << std::endl; + return 1; + } + + boost::asio::io_service io_service; + + // Set the name of the file that all logger instances will use. + services::logger logger(io_service, ""); + logger.use_file("log.txt"); + + // Resolve the address corresponding to the given host. + boost::asio::ip::tcp::resolver resolver(io_service); + boost::asio::ip::tcp::resolver::query query(argv[1], "daytime"); + boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); + + // Start an asynchronous connect. + debug_stream_socket socket(io_service); + boost::asio::async_connect(socket, iterator, + boost::bind(connect_handler, + boost::asio::placeholders::error, &socket)); + + // Run the io_service until all operations have finished. + io_service.run(); + } + catch (std::exception& e) + { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/doc/html/boost_asio/example/services/logger.hpp b/doc/html/boost_asio/example/services/logger.hpp new file mode 100755 index 0000000000..ef811d2a82 --- /dev/null +++ b/doc/html/boost_asio/example/services/logger.hpp @@ -0,0 +1,24 @@ +// +// logger.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef SERVICES_LOGGER_HPP +#define SERVICES_LOGGER_HPP + +#include "basic_logger.hpp" +#include "logger_service.hpp" + +namespace services { + +/// Typedef for typical logger usage. +typedef basic_logger<logger_service> logger; + +} // namespace services + +#endif // SERVICES_LOGGER_HPP diff --git a/doc/html/boost_asio/example/services/logger_service.cpp b/doc/html/boost_asio/example/services/logger_service.cpp new file mode 100755 index 0000000000..ee43287ec6 --- /dev/null +++ b/doc/html/boost_asio/example/services/logger_service.cpp @@ -0,0 +1,17 @@ +// +// logger_service.cpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "logger_service.hpp" + +namespace services { + +boost::asio::io_service::id logger_service::id; + +} // namespace services diff --git a/doc/html/boost_asio/example/services/logger_service.hpp b/doc/html/boost_asio/example/services/logger_service.hpp new file mode 100755 index 0000000000..165018df06 --- /dev/null +++ b/doc/html/boost_asio/example/services/logger_service.hpp @@ -0,0 +1,145 @@ +// +// logger_service.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef SERVICES_LOGGER_SERVICE_HPP +#define SERVICES_LOGGER_SERVICE_HPP + +#include <boost/asio.hpp> +#include <boost/thread/thread.hpp> +#include <boost/bind.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/noncopyable.hpp> +#include <boost/scoped_ptr.hpp> +#include <fstream> +#include <sstream> +#include <string> + +namespace services { + +/// Service implementation for the logger. +class logger_service + : public boost::asio::io_service::service +{ +public: + /// The unique service identifier. + static boost::asio::io_service::id id; + + /// The backend implementation of a logger. + struct logger_impl + { + explicit logger_impl(const std::string& ident) : identifier(ident) {} + std::string identifier; + }; + + /// The type for an implementation of the logger. + typedef logger_impl* impl_type; + + /// Constructor creates a thread to run a private io_service. + logger_service(boost::asio::io_service& io_service) + : boost::asio::io_service::service(io_service), + work_io_service_(), + work_(new boost::asio::io_service::work(work_io_service_)), + work_thread_(new boost::thread( + boost::bind(&boost::asio::io_service::run, &work_io_service_))) + { + } + + /// Destructor shuts down the private io_service. + ~logger_service() + { + /// Indicate that we have finished with the private io_service. Its + /// io_service::run() function will exit once all other work has completed. + work_.reset(); + if (work_thread_) + work_thread_->join(); + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Return a null logger implementation. + impl_type null() const + { + return 0; + } + + /// Create a new logger implementation. + void create(impl_type& impl, const std::string& identifier) + { + impl = new logger_impl(identifier); + } + + /// Destroy a logger implementation. + void destroy(impl_type& impl) + { + delete impl; + impl = null(); + } + + /// Set the output file for the logger. The current implementation sets the + /// output file for all logger instances, and so the impl parameter is not + /// actually needed. It is retained here to illustrate how service functions + /// are typically defined. + void use_file(impl_type& /*impl*/, const std::string& file) + { + // Pass the work of opening the file to the background thread. + work_io_service_.post(boost::bind( + &logger_service::use_file_impl, this, file)); + } + + /// Log a message. + void log(impl_type& impl, const std::string& message) + { + // Format the text to be logged. + std::ostringstream os; + os << impl->identifier << ": " << message; + + // Pass the work of opening the file to the background thread. + work_io_service_.post(boost::bind( + &logger_service::log_impl, this, os.str())); + } + +private: + /// Helper function used to open the output file from within the private + /// io_service's thread. + void use_file_impl(const std::string& file) + { + ofstream_.close(); + ofstream_.clear(); + ofstream_.open(file.c_str()); + } + + /// Helper function used to log a message from within the private io_service's + /// thread. + void log_impl(const std::string& text) + { + ofstream_ << text << std::endl; + } + + /// Private io_service used for performing logging operations. + boost::asio::io_service work_io_service_; + + /// Work for the private io_service to perform. If we do not give the + /// io_service some work to do then the io_service::run() function will exit + /// immediately. + boost::scoped_ptr<boost::asio::io_service::work> work_; + + /// Thread used for running the work io_service's run loop. + boost::scoped_ptr<boost::thread> work_thread_; + + /// The file to which log messages will be written. + std::ofstream ofstream_; +}; + +} // namespace services + +#endif // SERVICES_LOGGER_SERVICE_HPP diff --git a/doc/html/boost_asio/example/services/stream_socket_service.hpp b/doc/html/boost_asio/example/services/stream_socket_service.hpp new file mode 100755 index 0000000000..c63d6f43d1 --- /dev/null +++ b/doc/html/boost_asio/example/services/stream_socket_service.hpp @@ -0,0 +1,351 @@ +// +// stream_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef SERVICES_STREAM_SOCKET_SERVICE_HPP +#define SERVICES_STREAM_SOCKET_SERVICE_HPP + +#include <boost/asio.hpp> +#include <boost/noncopyable.hpp> +#include <boost/lexical_cast.hpp> +#include "logger.hpp" + +namespace services { + +/// Debugging stream socket service that wraps the normal stream socket service. +template <typename Protocol> +class stream_socket_service + : public boost::asio::io_service::service +{ +private: + /// The type of the wrapped stream socket service. + typedef boost::asio::stream_socket_service<Protocol> service_impl_type; + +public: + /// The unique service identifier. + static boost::asio::io_service::id id; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// The implementation type of a stream socket. + typedef typename service_impl_type::implementation_type implementation_type; + + /// The native type of a stream socket. + typedef typename service_impl_type::native_handle_type native_handle_type; + + /// Construct a new stream socket service for the specified io_service. + explicit stream_socket_service(boost::asio::io_service& io_service) + : boost::asio::io_service::service(io_service), + service_impl_(boost::asio::use_service<service_impl_type>(io_service)), + logger_(io_service, "stream_socket") + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new stream socket implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a stream socket implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Open a new stream socket implementation. + boost::system::error_code open(implementation_type& impl, + const protocol_type& protocol, boost::system::error_code& ec) + { + logger_.log("Opening new socket"); + return service_impl_.open(impl, protocol, ec); + } + + /// Open a stream socket from an existing native socket. + boost::system::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_handle_type& native_socket, + boost::system::error_code& ec) + { + logger_.log("Assigning from a native socket"); + return service_impl_.assign(impl, protocol, native_socket, ec); + } + + /// Determine whether the socket is open. + bool is_open(const implementation_type& impl) const + { + logger_.log("Checking if socket is open"); + return service_impl_.is_open(impl); + } + + /// Close a stream socket implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + logger_.log("Closing socket"); + return service_impl_.close(impl, ec); + } + + /// Determine whether the socket is at the out-of-band data mark. + bool at_mark(const implementation_type& impl, + boost::system::error_code& ec) const + { + logger_.log("Checking if socket is at out-of-band data mark"); + return service_impl_.at_mark(impl, ec); + } + + /// Determine the number of bytes available for reading. + std::size_t available(const implementation_type& impl, + boost::system::error_code& ec) const + { + logger_.log("Determining number of bytes available for reading"); + return service_impl_.available(impl, ec); + } + + /// Bind the stream socket to the specified local endpoint. + boost::system::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, boost::system::error_code& ec) + { + logger_.log("Binding socket"); + return service_impl_.bind(impl, endpoint, ec); + } + + /// Connect the stream socket to the specified endpoint. + boost::system::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + logger_.log("Connecting socket to " + + boost::lexical_cast<std::string>(peer_endpoint)); + return service_impl_.connect(impl, peer_endpoint, ec); + } + + /// Handler to wrap asynchronous connect completion. + template <typename Handler> + class connect_handler + { + public: + connect_handler(Handler h, logger& l) + : handler_(h), + logger_(l) + { + } + + void operator()(const boost::system::error_code& e) + { + if (e) + { + std::string msg = "Asynchronous connect failed: "; + msg += e.message(); + logger_.log(msg); + } + else + { + logger_.log("Asynchronous connect succeeded"); + } + + handler_(e); + } + + private: + Handler handler_; + logger& logger_; + }; + + /// Start an asynchronous connect. + template <typename Handler> + void async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, Handler handler) + { + logger_.log("Starting asynchronous connect to " + + boost::lexical_cast<std::string>(peer_endpoint)); + service_impl_.async_connect(impl, peer_endpoint, + connect_handler<Handler>(handler, logger_)); + } + + /// Set a socket option. + template <typename Option> + boost::system::error_code set_option(implementation_type& impl, + const Option& option, boost::system::error_code& ec) + { + logger_.log("Setting socket option"); + return service_impl_.set_option(impl, option, ec); + } + + /// Get a socket option. + template <typename Option> + boost::system::error_code get_option(const implementation_type& impl, + Option& option, boost::system::error_code& ec) const + { + logger_.log("Getting socket option"); + return service_impl_.get_option(impl, option, ec); + } + + /// Perform an IO control command on the socket. + template <typename IO_Control_Command> + boost::system::error_code io_control(implementation_type& impl, + IO_Control_Command& command, boost::system::error_code& ec) + { + logger_.log("Performing IO control command on socket"); + return service_impl_.io_control(impl, command, ec); + } + + /// Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + logger_.log("Getting socket's local endpoint"); + return service_impl_.local_endpoint(impl, ec); + } + + /// Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + logger_.log("Getting socket's remote endpoint"); + return service_impl_.remote_endpoint(impl, ec); + } + + /// Disable sends or receives on the socket. + boost::system::error_code shutdown(implementation_type& impl, + boost::asio::socket_base::shutdown_type what, + boost::system::error_code& ec) + { + logger_.log("Shutting down socket"); + return service_impl_.shutdown(impl, what, ec); + } + + /// Send the given data to the peer. + template <typename Const_Buffers> + std::size_t send(implementation_type& impl, const Const_Buffers& buffers, + boost::asio::socket_base::message_flags flags, + boost::system::error_code& ec) + { + logger_.log("Sending data on socket"); + return service_impl_.send(impl, buffers, flags, ec); + } + + /// Handler to wrap asynchronous send completion. + template <typename Handler> + class send_handler + { + public: + send_handler(Handler h, logger& l) + : handler_(h), + logger_(l) + { + } + + void operator()(const boost::system::error_code& e, + std::size_t bytes_transferred) + { + if (e) + { + std::string msg = "Asynchronous send failed: "; + msg += e.message(); + logger_.log(msg); + } + else + { + logger_.log("Asynchronous send succeeded"); + } + + handler_(e, bytes_transferred); + } + + private: + Handler handler_; + logger& logger_; + }; + + /// Start an asynchronous send. + template <typename Const_Buffers, typename Handler> + void async_send(implementation_type& impl, const Const_Buffers& buffers, + boost::asio::socket_base::message_flags flags, Handler handler) + { + logger_.log("Starting asynchronous send"); + service_impl_.async_send(impl, buffers, flags, + send_handler<Handler>(handler, logger_)); + } + + /// Receive some data from the peer. + template <typename Mutable_Buffers> + std::size_t receive(implementation_type& impl, + const Mutable_Buffers& buffers, + boost::asio::socket_base::message_flags flags, + boost::system::error_code& ec) + { + logger_.log("Receiving data on socket"); + return service_impl_.receive(impl, buffers, flags, ec); + } + + /// Handler to wrap asynchronous receive completion. + template <typename Handler> + class receive_handler + { + public: + receive_handler(Handler h, logger& l) + : handler_(h), + logger_(l) + { + } + + void operator()(const boost::system::error_code& e, + std::size_t bytes_transferred) + { + if (e) + { + std::string msg = "Asynchronous receive failed: "; + msg += e.message(); + logger_.log(msg); + } + else + { + logger_.log("Asynchronous receive succeeded"); + } + + handler_(e, bytes_transferred); + } + + private: + Handler handler_; + logger& logger_; + }; + + /// Start an asynchronous receive. + template <typename Mutable_Buffers, typename Handler> + void async_receive(implementation_type& impl, const Mutable_Buffers& buffers, + boost::asio::socket_base::message_flags flags, Handler handler) + { + logger_.log("Starting asynchronous receive"); + service_impl_.async_receive(impl, buffers, flags, + receive_handler<Handler>(handler, logger_)); + } + +private: + /// The wrapped stream socket service. + service_impl_type& service_impl_; + + /// The logger used for writing debug messages. + mutable logger logger_; +}; + +template <typename Protocol> +boost::asio::io_service::id stream_socket_service<Protocol>::id; + +} // namespace services + +#endif // SERVICES_STREAM_SOCKET_SERVICE_HPP |