diff --git a/src/Communication/AsioCompatibility.h b/src/Communication/AsioCompatibility.h new file mode 100644 index 00000000..bbad0de6 --- /dev/null +++ b/src/Communication/AsioCompatibility.h @@ -0,0 +1,88 @@ +// Copyright (c) 2009, 2010, 2011 Object Computing, Inc. +// All rights reserved. +// See the file license.txt for licensing information. +// +#ifdef _MSC_VER +# pragma once +#endif +#ifndef ASIOCOMPATIBILITY_H +#define ASIOCOMPATIBILITY_H +#ifndef QUICKFAST_HEADERS +#error Please include preferably as a precompiled header file. +#endif //QUICKFAST_HEADERS + +#include "AsioService_fwd.h" +#include +#include + +namespace QuickFAST +{ + namespace Communication + { + // Boost 1.66 replaced several of the Asio interfaces QuickFAST is written + // against, and Boost 1.87 removed the originals. Each helper below spells + // its operation the way the Boost release being compiled against expects, + // so that the call sites do not have to. + + /// @brief Convert a dotted IP address to an asio address + /// @param address is the address in dotted notation + inline boost::asio::ip::address makeAddress(const std::string & address) + { +#if BOOST_VERSION >= 106600 + return boost::asio::ip::make_address(address); +#else + return boost::asio::ip::address::from_string(address); +#endif + } + + /// @brief Post a completion handler to an io service + /// @param ioService is the service that will run the handler + /// @param handler is the handler to be posted + template + inline void postHandler( + boost::asio::io_service & ioService, + CompletionHandler handler) + { +#if BOOST_VERSION >= 106600 + boost::asio::post(ioService, handler); +#else + ioService.post(handler); +#endif + } + + /// @brief Keeps an io service running while it has no work to do + /// + /// io_service::work was replaced by executor_work_guard in Boost 1.66 and + /// removed in Boost 1.87. +#if BOOST_VERSION >= 106600 + typedef boost::asio::executor_work_guard< + boost::asio::io_context::executor_type> WorkGuard; +#else + typedef boost::asio::io_service::work WorkGuard; +#endif + + /// @brief Create a work guard for an io service + /// @param ioService is the service to be kept alive + /// @returns a new work guard; the caller owns it + inline WorkGuard * makeWorkGuard(boost::asio::io_service & ioService) + { +#if BOOST_VERSION >= 106600 + return new WorkGuard(boost::asio::make_work_guard(ioService)); +#else + return new WorkGuard(ioService); +#endif + } + + /// @brief Prepare an io service to be run again after it has stopped + /// @param ioService is the service to be restarted + inline void restartService(boost::asio::io_service & ioService) + { +#if BOOST_VERSION >= 106600 + ioService.restart(); +#else + ioService.reset(); +#endif + } + } +} +#endif // ASIOCOMPATIBILITY_H diff --git a/src/Communication/AsioService.h b/src/Communication/AsioService.h index 4f619156..bd84fb76 100644 --- a/src/Communication/AsioService.h +++ b/src/Communication/AsioService.h @@ -7,7 +7,7 @@ #endif #ifndef ASIOSERVICE_H #define ASIOSERVICE_H -#include "AsioService_fwd.h" +#include "AsioCompatibility.h" #include #include #include @@ -87,7 +87,7 @@ namespace QuickFAST /// should be called after joinThreads before calling run*, poll*, etc. again. void resetService() { - ioService_.reset(); + restartService(ioService_); stopping_ = false; } @@ -100,12 +100,26 @@ namespace QuickFAST return ioService_; } +#if BOOST_VERSION >= 106600 + /// @brief the executor of the underlying io_service + /// + /// Boost 1.66 replaced the io_service& constructors of the Asio I/O + /// objects with a template that asks its argument for an executor. The + /// implicit cast above is no longer enough for an AsioService to be + /// passed where an io_service used to be accepted, so the question is + /// forwarded to the io_service being wrapped. + boost::asio::io_context::executor_type get_executor() + { + return ioService_.get_executor(); + } +#endif // BOOST_VERSION >= 106600 + ///@brief Post a completion handler for later processing (usually in a different thread) /// @param handler is the handler to be posted template void post(CompletionHandler handler) { - ioService_.post(handler); + postHandler(ioService_, handler); } /// @brief Attempt to determine how many threads are available to ASIO diff --git a/src/Communication/AsioService_fwd.h b/src/Communication/AsioService_fwd.h index dc2f2354..a3f01ab7 100644 --- a/src/Communication/AsioService_fwd.h +++ b/src/Communication/AsioService_fwd.h @@ -11,6 +11,24 @@ #error Please include preferably as a precompiled header file. #endif //QUICKFAST_HEADERS +// Boost 1.66 turned io_service into a typedef for io_context, so the class +// declaration QuickFAST used to make here now conflicts with the one Asio +// provides. From that release on, take the declaration from Boost itself; +// io_service.hpp only pulls in io_context, not all of Asio. +#include +#if BOOST_VERSION >= 108700 +// Boost 1.87 removed the io_service name altogether. +# include +namespace boost +{ + namespace asio + { + typedef io_context io_service; + } +} +#elif BOOST_VERSION >= 106600 +# include +#else // forward declare io_service without including // boost header namespace boost @@ -20,6 +38,7 @@ namespace boost class io_service; } } +#endif // BOOST_VERSION >= 106600 namespace QuickFAST { diff --git a/src/Communication/AsynchSender.cpp b/src/Communication/AsynchSender.cpp index 0261302f..669918f3 100644 --- a/src/Communication/AsynchSender.cpp +++ b/src/Communication/AsynchSender.cpp @@ -15,7 +15,7 @@ AsynchSender::AsynchSender( : Sender(recycler) , name_(name) , ioService_() - , keepAlive_(new boost::asio::io_service::work(ioService_)) + , keepAlive_(makeWorkGuard(ioService_)) { //std::cout << "Asynch Sender {" << (void *)this << "} keeping ioService " << (void*) &ioService_ << " alive." << std::endl; } @@ -27,7 +27,7 @@ AsynchSender::AsynchSender( : Sender(recycler) , name_(name) , ioService_(ioService) - , keepAlive_(new boost::asio::io_service::work(ioService_)) + , keepAlive_(makeWorkGuard(ioService_)) { // std::cout << "Asynch Sender {" << (void *)this << "} keeping shared ioService " << (void*) &ioService_ << " alive." << std::endl; } diff --git a/src/Communication/AsynchSender.h b/src/Communication/AsynchSender.h index 5eb02c25..b2393c0b 100644 --- a/src/Communication/AsynchSender.h +++ b/src/Communication/AsynchSender.h @@ -111,7 +111,7 @@ namespace QuickFAST /// needed for output-type service which may have nothing to write at the moment, unlike /// input-type services which should always have an outstanding read or an active handler /// callback. - boost::scoped_ptr keepAlive_; + boost::scoped_ptr keepAlive_; }; } } diff --git a/src/Communication/MulticastReceiver.h b/src/Communication/MulticastReceiver.h index cb9a9993..4aa4d423 100644 --- a/src/Communication/MulticastReceiver.h +++ b/src/Communication/MulticastReceiver.h @@ -36,10 +36,10 @@ namespace QuickFAST ) : parent_(parent) , name_(name) - , listenInterface_(boost::asio::ip::address::from_string(listenInterfaceIP)) + , listenInterface_(makeAddress(listenInterfaceIP)) , portNumber_(portNumber) - , multicastGroup_(boost::asio::ip::address::from_string(multicastGroupIP)) - , bindAddress_(boost::asio::ip::address::from_string(bindIP)) + , multicastGroup_(makeAddress(multicastGroupIP)) + , bindAddress_(makeAddress(bindIP)) , endpoint_(listenInterface_, portNumber) , socket_(ioService) , joined_(false) diff --git a/src/Communication/MulticastSender.h b/src/Communication/MulticastSender.h index f0c7be18..bcbb3f99 100644 --- a/src/Communication/MulticastSender.h +++ b/src/Communication/MulticastSender.h @@ -62,7 +62,7 @@ namespace QuickFAST ///@brief Prepare the sender to be used bool initializeSender() { - multicastAddress_ = boost::asio::ip::address::from_string(sendAddress_); + multicastAddress_ = makeAddress(sendAddress_); endpoint_ = boost::asio::ip::udp::endpoint(multicastAddress_, portNumber_); socket_.open(endpoint_.protocol()); return true; diff --git a/src/Communication/TCPReceiver.h b/src/Communication/TCPReceiver.h index 6ddb4363..8b45ebc3 100644 --- a/src/Communication/TCPReceiver.h +++ b/src/Communication/TCPReceiver.h @@ -60,12 +60,26 @@ namespace QuickFAST bool ok = true; // generate a collection of possible endpoints for this host:port boost::asio::ip::tcp::resolver resolver(ioService_); +#if BOOST_VERSION >= 106600 + // resolver::query and the iterator-returning resolve() were replaced + // in Boost 1.66 and removed in Boost 1.87. + boost::asio::ip::tcp::resolver::results_type endpoints = + resolver.resolve(hostName_, port_); + boost::asio::ip::tcp::resolver::results_type::const_iterator iterator = + endpoints.begin(); + boost::asio::ip::tcp::resolver::results_type::const_iterator endIterator = + endpoints.end(); + + // then iterate thru the collection until we find one that works. + boost::system::error_code error; +#else boost::asio::ip::tcp::resolver::query query( hostName_, port_); boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query); // then iterate thru the collection until we find one that works. boost::system::error_code error; boost::asio::ip::tcp::resolver::iterator endIterator; +#endif // BOOST_VERSION >= 106600 bool connected = false; while(!connected && iterator != endIterator) { diff --git a/src/Examples/FileToMulticast/FileToMulticast.cpp b/src/Examples/FileToMulticast/FileToMulticast.cpp index 4f714958..2c4e93f8 100644 --- a/src/Examples/FileToMulticast/FileToMulticast.cpp +++ b/src/Examples/FileToMulticast/FileToMulticast.cpp @@ -263,8 +263,18 @@ FileToMulticast::run() << "Largest is " << bufferSize_ << " bytes." << std::endl; } +#if BOOST_VERSION >= 106600 + // strand::wrap and strand::dispatch were replaced in Boost 1.66. + boost::asio::dispatch(strand_, boost::bind(&FileToMulticast::sendBurst, this)); +#else +#if BOOST_VERSION >= 106600 + // strand::dispatch now takes the handler itself, already bound. + boost::asio::dispatch(strand_, boost::bind(&FileToMulticast::sendBurst, this)); +#else strand_.dispatch( strand_.wrap(boost::bind(&FileToMulticast::sendBurst, this))); +#endif // BOOST_VERSION >= 106600 +#endif // BOOST_VERSION >= 106600 StopWatch lapse; this->ioService_.run(); unsigned long sendLapse = lapse.freeze(); @@ -302,9 +312,19 @@ FileToMulticast::sendBurst() // set the next timeout if(sendMicroseconds_ != 0) { +#if BOOST_VERSION >= 106600 + timer_.expires_after(std::chrono::microseconds(sendMicroseconds_)); +#else timer_.expires_from_now(boost::posix_time::microseconds(sendMicroseconds_)); +#endif // BOOST_VERSION >= 106600 timer_.async_wait( +#if BOOST_VERSION >= 106600 + // strand::wrap was replaced by bind_executor in Boost 1.66. + boost::asio::bind_executor( + strand_, boost::bind(&FileToMulticast::sendBurst, this)) +#else strand_.wrap(boost::bind(&FileToMulticast::sendBurst, this)) +#endif // BOOST_VERSION >= 106600 ); } diff --git a/src/Examples/FileToMulticast/FileToMulticast.h b/src/Examples/FileToMulticast/FileToMulticast.h index d6d62fff..60d4fab4 100644 --- a/src/Examples/FileToMulticast/FileToMulticast.h +++ b/src/Examples/FileToMulticast/FileToMulticast.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace QuickFAST{ namespace Examples{ @@ -64,8 +65,16 @@ namespace QuickFAST{ bool verbose_; Communication::AsioService ioService_; - boost::asio::strand strand_; + // boost::asio::strand became a template in Boost 1.66; the class this + // example uses is spelled io_service::strand in every release. + boost::asio::io_service::strand strand_; +#if BOOST_VERSION >= 106600 + // Asio's date_time based timers became opt-in, so the example uses the + // chrono based timer that is always available. + boost::asio::steady_timer timer_; +#else boost::asio::deadline_timer timer_; +#endif // BOOST_VERSION >= 106600 Application::CommandArgParser commandArgParser_; FILE * dataFile_; diff --git a/src/Examples/FileToTCP/FileToTCP.cpp b/src/Examples/FileToTCP/FileToTCP.cpp index 9ed52088..8d2a6187 100644 --- a/src/Examples/FileToTCP/FileToTCP.cpp +++ b/src/Examples/FileToTCP/FileToTCP.cpp @@ -121,12 +121,19 @@ FileToTCP::run() for (size_t count = 0; count < sendCount_ || sendCount_ == 0; ++count) { - tcp::iostream stream; if(verbose_) { std::cout << "Listening" << std::endl; } +#if BOOST_VERSION >= 106600 + // Boost 1.66 made basic_socket a private base of the stream buffer, so + // the accepted socket is moved into the stream instead of accepted into + // the stream's buffer. + tcp::iostream stream(acceptor.accept()); +#else + tcp::iostream stream; acceptor.accept(*stream.rdbuf()); +#endif // BOOST_VERSION >= 106600 if(verbose_) { std::cout << "Accepting" << std::endl; diff --git a/src/Examples/FileToTCP/FileToTCP.h b/src/Examples/FileToTCP/FileToTCP.h index 6bca9e08..48d322bb 100644 --- a/src/Examples/FileToTCP/FileToTCP.h +++ b/src/Examples/FileToTCP/FileToTCP.h @@ -5,6 +5,7 @@ #ifndef FILETOTCP_H #define FILETOTCP_H #include +#include #include #include diff --git a/src/Examples/InterpretApplication/InterpretApplication.cpp b/src/Examples/InterpretApplication/InterpretApplication.cpp index 9e908541..2185b1d2 100644 --- a/src/Examples/InterpretApplication/InterpretApplication.cpp +++ b/src/Examples/InterpretApplication/InterpretApplication.cpp @@ -252,7 +252,7 @@ InterpretApplication::run() "r" #endif ); - if(bufferFile <= 0) + if(bufferFile == 0) { std::cerr << "Can't open file " << bufferFilename_ << std::endl; return -1; diff --git a/src/Examples/PCapToMulticast/PCapToMulticast.cpp b/src/Examples/PCapToMulticast/PCapToMulticast.cpp index c08d11f2..b58dd7d3 100644 --- a/src/Examples/PCapToMulticast/PCapToMulticast.cpp +++ b/src/Examples/PCapToMulticast/PCapToMulticast.cpp @@ -166,7 +166,7 @@ PCapToMulticast::applyArgs() } ok = ok && pcapReader_.open(dataFileName_.c_str());// for debugging dump to->, &std::cout); - multicastAddress_ = boost::asio::ip::address::from_string(sendAddress_); + multicastAddress_ = Communication::makeAddress(sendAddress_); endpoint_ = boost::asio::ip::udp::endpoint(multicastAddress_, portNumber_); socket_.open(endpoint_.protocol()); std::cout << "Opening multicast group: " << endpoint_.address().to_string() << ':' << endpoint_.port() << std::endl; @@ -189,8 +189,13 @@ PCapToMulticast::run() std::cout << " Configuring multicast: " << multicastAddress_ << '|' << sendAddress_ << ':' << portNumber_ << std::endl; } +#if BOOST_VERSION >= 106600 + // strand::dispatch now takes the handler itself, already bound. + boost::asio::dispatch(strand_, boost::bind(&PCapToMulticast::sendBurst, this)); +#else strand_.dispatch( strand_.wrap(boost::bind(&PCapToMulticast::sendBurst, this))); +#endif // BOOST_VERSION >= 106600 StopWatch lapse; this->ioService_.run(); unsigned long sendLapse = lapse.freeze(); @@ -228,9 +233,19 @@ PCapToMulticast::sendBurst() // set the next timeout if(sendMicroseconds_ != 0) { +#if BOOST_VERSION >= 106600 + timer_.expires_after(std::chrono::microseconds(sendMicroseconds_)); +#else timer_.expires_from_now(boost::posix_time::microseconds(sendMicroseconds_)); +#endif // BOOST_VERSION >= 106600 timer_.async_wait( +#if BOOST_VERSION >= 106600 + // strand::wrap was replaced by bind_executor in Boost 1.66. + boost::asio::bind_executor( + strand_, boost::bind(&PCapToMulticast::sendBurst, this)) +#else strand_.wrap(boost::bind(&PCapToMulticast::sendBurst, this)) +#endif // BOOST_VERSION >= 106600 ); } diff --git a/src/Examples/PCapToMulticast/PCapToMulticast.h b/src/Examples/PCapToMulticast/PCapToMulticast.h index fe97b25b..44038e9e 100644 --- a/src/Examples/PCapToMulticast/PCapToMulticast.h +++ b/src/Examples/PCapToMulticast/PCapToMulticast.h @@ -8,8 +8,10 @@ #define PCAP_SUPPORT_IS_HEREx #include #include +#include #include #include +#include namespace QuickFAST{ namespace Examples{ @@ -66,8 +68,16 @@ namespace QuickFAST{ boost::asio::ip::address multicastAddress_; boost::asio::ip::udp::endpoint endpoint_; boost::asio::ip::udp::socket socket_; - boost::asio::strand strand_; + // boost::asio::strand became a template in Boost 1.66; the class this + // example uses is spelled io_service::strand in every release. + boost::asio::io_service::strand strand_; +#if BOOST_VERSION >= 106600 + // Asio's date_time based timers became opt-in, so the example uses the + // chrono based timer that is always available. + boost::asio::steady_timer timer_; +#else boost::asio::deadline_timer timer_; +#endif // BOOST_VERSION >= 106600 Application::CommandArgParser commandArgParser_; // FILE * dataFile_;