This commit is contained in:
Aart Stuurman 2018-01-25 18:17:43 +01:00
commit f25efd2235
6 changed files with 200 additions and 118 deletions

82
.travis.yml Normal file
View File

@ -0,0 +1,82 @@
################
# project config
################
# C++ project
language: cpp
dist: trusty
sudo: required
group: edge
################
# build matrix
################
matrix:
include:
################
# Linux / GCC
################
- os: linux
compiler: gcc
env: COMPILER=g++-5
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-6
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'ninja-build']
- os: linux
compiler: gcc
env: COMPILER=g++-7
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-7', 'ninja-build']
################
# Linux / Clang
################
- os: linux
compiler: clang
env: COMPILER=clang++-4.0
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-4.0']
packages: ['clang-4.0', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-5.0
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0']
packages: ['clang-5.0', 'ninja-build']
################
# build / test
################
script:
# show OS/compiler version
- uname -a
- $CXX --version
# compile and execute unit tests
- mkdir -p build.release && cd build.release
- cmake .. ${CMAKE_OPTIONS} -GNinja && cmake --build . --config Release
- cd ..

View File

@ -34,7 +34,7 @@ sure that your compiler is up-to-date and supports C++11.
**Note for the reader:** This readme file has a peculiar structure. We start
explaining the pure and hard core low level interface in which you have to
take care of opening socket connections yourself. In reality, you probably want
to use the simpler TCP interface that is being described later on.
to use the simpler TCP interface that is being described [later on](#tcp-connections).
ABOUT

View File

@ -26,35 +26,12 @@
#include <boost/asio/posix/stream_descriptor.hpp>
#include <boost/bind.hpp>
///////////////////////////////////////////////////////////////////
#define STRAND_SOCKET_HANDLER(_fn) \
[fn = _fn, strand = _strand](const boost::system::error_code &ec, \
const std::size_t bytes_transferred) \
{ \
const std::shared_ptr<boost::asio::io_service::strand> apStrand = strand.lock(); \
if (!apStrand) \
{ \
fn(boost::system::errc::make_error_code(boost::system::errc::operation_canceled),std::size_t{0}); \
return; \
} \
\
apStrand->dispatch(boost::bind(fn,ec,bytes_transferred)); \
}
///////////////////////////////////////////////////////////////////
#define STRAND_TIMER_HANDLER(_fn) \
[fn = _fn, strand = _strand](const boost::system::error_code &ec) \
{ \
const std::shared_ptr<boost::asio::io_service::strand> apStrand = strand.lock(); \
if (!apStrand) \
{ \
fn(boost::system::errc::make_error_code(boost::system::errc::operation_canceled)); \
return; \
} \
\
apStrand->dispatch(boost::bind(fn,ec)); \
}
// C++17 has 'weak_from_this()' support.
#if __cplusplus >= 201701L
#define PTR_FROM_THIS weak_from_this
#else
#define PTR_FROM_THIS shared_from_this
#endif
/**
* Set up namespace
@ -120,6 +97,64 @@ private:
*/
bool _write_pending{false};
using handler_cb = boost::function<void(boost::system::error_code,std::size_t)>;
using io_handler = boost::function<void(const boost::system::error_code&, const std::size_t)>;
/**
* Builds a io handler callback that executes the io callback in a strand.
* @param io_handler The handler callback to dispatch
* @return handler_cb A function wrapping the execution of the handler function in a io_service::strand.
*/
handler_cb get_dispatch_wrapper(io_handler fn)
{
return [fn, strand = _strand](const boost::system::error_code &ec, const std::size_t bytes_transferred)
{
const std::shared_ptr<boost::asio::io_service::strand> apStrand = strand.lock();
if (!apStrand)
{
fn(boost::system::errc::make_error_code(boost::system::errc::operation_canceled), std::size_t{0});
return;
}
apStrand->dispatch(boost::bind(fn, ec, bytes_transferred));
};
}
/**
* Binds and returns a read handler for the io operation.
* @param connection The connection being watched.
* @param fd The file descripter being watched.
* @return handler callback
*/
handler_cb get_read_handler(TcpConnection *const connection, const int fd)
{
auto fn = boost::bind(&Watcher::read_handler,
this,
_1,
_2,
PTR_FROM_THIS(),
connection,
fd);
return get_dispatch_wrapper(fn);
}
/**
* Binds and returns a read handler for the io operation.
* @param connection The connection being watched.
* @param fd The file descripter being watched.
* @return handler callback
*/
handler_cb get_write_handler(TcpConnection *const connection, const int fd)
{
auto fn = boost::bind(&Watcher::write_handler,
this,
_1,
_2,
PTR_FROM_THIS(),
connection,
fd);
return get_dispatch_wrapper(fn);
}
/**
* Handler method that is called by boost's io_service when the socket pumps a read event.
* @param ec The status of the callback.
@ -148,20 +183,9 @@ private:
_read_pending = true;
_socket.async_read_some(boost::asio::null_buffers(),
STRAND_SOCKET_HANDLER(
boost::bind(&Watcher::read_handler,
this,
boost::placeholders::_1,
boost::placeholders::_2,
// C++17 has 'weak_from_this()' support.
#if __cplusplus >= 201701L
weak_from_this(),
#else
shared_from_this(),
#endif
connection,
fd)));
_socket.async_read_some(
boost::asio::null_buffers(),
get_read_handler(connection, fd));
}
}
@ -193,20 +217,9 @@ private:
_write_pending = true;
_socket.async_write_some(boost::asio::null_buffers(),
STRAND_SOCKET_HANDLER(
boost::bind(&Watcher::write_handler,
this,
boost::placeholders::_1,
boost::placeholders::_2,
// C++17 has 'weak_from_this()' support.
#if __cplusplus >= 201701L
weak_from_this(),
#else
shared_from_this(),
#endif
connection,
fd)));
_socket.async_write_some(
boost::asio::null_buffers(),
get_write_handler(connection, fd));
}
}
@ -262,20 +275,9 @@ private:
{
_read_pending = true;
_socket.async_read_some(boost::asio::null_buffers(),
STRAND_SOCKET_HANDLER(
boost::bind(&Watcher::read_handler,
this,
boost::placeholders::_1,
boost::placeholders::_2,
// C++17 has 'weak_from_this()' support.
#if __cplusplus >= 201701L
weak_from_this(),
#else
shared_from_this(),
#endif
connection,
fd)));
_socket.async_read_some(
boost::asio::null_buffers(),
get_read_handler(connection, fd));
}
// 2. Handle writes?
@ -286,20 +288,9 @@ private:
{
_write_pending = true;
_socket.async_write_some(boost::asio::null_buffers(),
STRAND_SOCKET_HANDLER(
boost::bind(&Watcher::write_handler,
this,
boost::placeholders::_1,
boost::placeholders::_2,
// C++17 has 'weak_from_this()' support.
#if __cplusplus >= 201701L
weak_from_this(),
#else
shared_from_this(),
#endif
connection,
fd)));
_socket.async_write_some(
boost::asio::null_buffers(),
get_write_handler(connection, fd));
}
}
};
@ -329,11 +320,39 @@ private:
*/
boost::asio::deadline_timer _timer;
using handler_fn = boost::function<void(boost::system::error_code)>;
/**
* Binds and returns a lamba function handler for the io operation.
* @param connection The connection being watched.
* @param timeout The file descripter being watched.
* @return handler callback
*/
handler_fn get_handler(TcpConnection *const connection, const uint16_t timeout)
{
auto fn = boost::bind(&Timer::timeout,
this,
_1,
PTR_FROM_THIS(),
connection,
timeout);
return [fn, strand = _strand](const boost::system::error_code &ec)
{
const std::shared_ptr<boost::asio::io_service::strand> apStrand = strand.lock();
if (!apStrand)
{
fn(boost::system::errc::make_error_code(boost::system::errc::operation_canceled));
return;
}
apStrand->dispatch(boost::bind(fn, ec));
};
}
/**
* Callback method that is called by libev when the timer expires
* @param ec error code returned from loop
* @param loop The loop in which the event was triggered
* @param timer Internal timer object
* @param revents The events that triggered this call
* @param connection
* @param timeout
*/
void timeout(const boost::system::error_code &ec,
std::weak_ptr<Timer> awpThis,
@ -357,18 +376,7 @@ private:
_timer.expires_at(_timer.expires_at() + boost::posix_time::seconds(timeout));
// Posts the timer event
_timer.async_wait(STRAND_TIMER_HANDLER(
boost::bind(&Timer::timeout,
this,
boost::placeholders::_1,
// C++17 has 'weak_from_this()' support.
#if __cplusplus >= 201701L
weak_from_this(),
#else
shared_from_this(),
#endif
connection,
timeout)));
_timer.async_wait(get_handler(connection, timeout));
}
}
@ -423,19 +431,11 @@ private:
// stop timer in case it was already set
stop();
// Reschedule the timer for the future:
_timer.expires_from_now(boost::posix_time::seconds(timeout));
_timer.async_wait(STRAND_TIMER_HANDLER(
boost::bind(&Timer::timeout,
this,
boost::placeholders::_1,
// C++17 has 'weak_from_this()' support.
#if __cplusplus >= 201701L
weak_from_this(),
#else
shared_from_this(),
#endif
connection,
timeout)));
// Posts the timer event
_timer.async_wait(get_handler(connection, timeout));
}
};

View File

@ -196,8 +196,8 @@ public:
properties["product"] = "Copernica AMQP library";
properties["version"] = "Unknown";
properties["platform"] = "Unknown";
properties["copyright"] = "Copyright 2015 Copernica BV";
properties["information"] = "http://www.copernica.com";
properties["copyright"] = "Copyright 2015 - 2018 Copernica BV";
properties["information"] = "https://www.copernica.com";
properties["capabilities"] = capabilities;
// move connection to handshake mode

View File

@ -1,6 +1,6 @@
CPP = g++
CPP = g++
CPPFLAGS = -Wall -c -I. -O2 -flto -std=c++11 -g
LD = g++
LD = g++
LDFLAGS = -lamqpcpp -lcopernica_event -lcopernica_network -lev
RESULT = a.out
SOURCES = $(wildcard *.cpp)

View File

@ -5,7 +5,7 @@
*
* @author Gavin Smith <gavin.smith@coralbay.tv>
*
* Compile with g++ libboostasio.cpp -o boost_test -lpthread -lboost_system -lamqpcpp
* Compile with g++ -std=c++14 libboostasio.cpp -o boost_test -lpthread -lboost_system -lamqpcpp
*/
/**