Skip to content

Commit

Permalink
Asio completion token support and thread-safe Session operations
Browse files Browse the repository at this point in the history
- All asynchronous operations in Session now accept a generic
  completion token.
- C++20 coroutines now supported by Session.
- Added examples using Asio stackless coroutines, C++20 coroutines, and
  std::future.
- Migrated from AsyncResult to new ErrorOr class which better emulates
  the proposed std::expected.
- Session's asynchonous operations now return an ErrorOr result when
  passed a yield_context as the completion token, and will not throw
  if there was a runtime error.
- Added Session::strand so that users may serialize access to the
  Session when using a thread pool.
- Added Session overloads with the ThreadSafe tag type which can be
  called concurrently by multiple threads.
- Added the SessionErrc::invalidState enumerator.
- Renamed AnyExecutor to AnyIoExecutor. AnyExecutor is now deprecated.
- Added AnyReusableHandler which type-erases a copyable multi-shot
  handler.
- Added AnyCompletionHandler which is a Boost-ified version of the
  prototype asio::any_completion_handler.
- Added AnyCompletionExecutor which is a Boost-ified version of the
  prototype asio::any_completion_executor.
- Session and transports now extract a strand from the `Connector`
  passed by the user.
- Moved corounpacker implementation to header directory root.
- Added Realm::captureAbort.
- Made config.hpp a public header.
- Added DecodingErrc and DecodingCategory for deserialization errors
  not covered by jsoncons.
- Session's setWarningHandler, setTraceHandler, setStateChangeHandler,
  and setChallengeHandler now take effect immediately even when
  connected. Those handlers are now executed via Session::userExecutor
  by default.
- Boost.Asio cancellation slot support for Session::call.
- Added withArgsTuple, convertToTuple and moveToTuple to Payload class.
- Added the Deferment tag type (with 'deferment' constexpr variable) to
  more conveniently return a deferred Outcome from an RPC handler.
- Renamed Cancellation to CallCancellation. Cancellation is now
  deprecated.
- Renamed CancelMode to CallCancelMode. CancelMode is now deprecated.
- Renamed Basic[Coro]<Event|Invocation>Unpacker to
  Simple[Coro]<Event|Invocation>Unpacker, with the former kept as
  deprecated aliases.
- Renamed basic[Coro]<Event|Rpc> to simple[Coro]<Event|Rpc>, with the
  former kept as deprecated aliases.
- Renamed the CppWAMP::coro-headers CMake target to CppWAMP::coro-usage,
  leaving the former as an alias.
- Deprecated CoroSession, AsyncResult, error::Decode, and
  Outcome::deferred
- Deprecated the Session::cancel overloads taking CallCancellation.
  • Loading branch information
ecorm committed Aug 13, 2022
1 parent b1555e8 commit 29153f6
Show file tree
Hide file tree
Showing 172 changed files with 13,917 additions and 4,441 deletions.
140 changes: 140 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,143 @@
v0.10.0
======
Asio completion token support and thread-safe Session operations.

- All asynchronous operations in Session now accept a generic
[completion token](https://www.boost.org/doc/libs/release/doc/html/boost_asio/overview/model/completion_tokens.html),
which can either be a callback function, a `yield_context`, `use_awaitable`,
or `use_future`.
- C++20 coroutines now supported by Session.
- Added examples using Asio stackless coroutines, C++20 coroutines, and
std::future.
- Migrated from `AsyncResult` to new `ErrorOr` class which better emulates
the proposed `std::expected`.
- `Session`'s asynchonous operations now return an `ErrorOr` result when passed
a `yield_context` as the completion token, and will not throw if there was
a runtime error. `ErrorOr::value` must be called to obtain the operation's
actual result (or throw an exception if there was an error).
- Added `Session::strand` so that users may serialize access to the `Session`
when using a thread pool.
- Added `Session` overloads with the `ThreadSafe` tag type which can be called
concurrently by multiple threads. These overloads will be automatically
dispatch operations via the `Session`'s execution strand.
- Added the `SessionErrc::invalidState` enumerator which is now used to report
errors when attempting to perform `Session` operations during an invalid
session state.
- Renamed `AnyExecutor` to `AnyIoExecutor` which aliases
`boost::asio::any_io_executor`. AnyExecutor is now deprecated.
- Added `AnyReusableHandler` which type-erases a copyable multi-shot handler,
while storing the executor to which it is possibly bound.
- Added `AnyCompletionHandler` which is a Boost-ified version of the prototype
[asio::any_completion_handler]
(https://github.com/chriskohlhoff/asio/issues/1100).
- Added `AnyCompletionExecutor` which is a Boost-ified version of the prototype
`asio::any_completion_executor`.
- Session and transports now extract a
[strand](https://www.boost.org/doc/libs/release/doc/html/boost_asio/overview/core/strands.html)
from the `Connector` passed by the user.
- Moved corounpacker implementation to header directory root.
- Added `Realm::captureAbort`.
- Made config.hpp a public header.
- Added DecodingErrc and DecodingCategory for deserialization errors
not covered by jsoncons.
- `Session`'s `setWarningHandler`, `setTraceHandler`, `setStateChangeHandler`,
and `setChallengeHandler` now take effect immediately even when connected.
- `Session`'s handlers for `setWarningHandler`, `setTraceHandler`,
`setStateChangeHandler`, and `setChallengeHandler` are now executed via
`Session::userExecutor` by default.
- Boost.Asio [cancellation slot]
(https://www.boost.org/doc/libs/release/doc/html/boost_asio/overview/core/cancellation.html)
support for `Session::call`.
- Added `Rpc::withCancelMode` which specifies the cancel mode to use when
triggered by Asio cancellation slots.
- Added `withArgsTuple`, `convertToTuple` and `moveToTuple` to Payload class.
- Added the `Deferment` tag type (with `deferment` constexpr variable`) to
more conveniently return a deferred `Outcome` from an RPC handler.
- Renamed `Cancellation` to `CallCancellation`. `Cancellation` is now a
deprecated alias to ``CallCancellation`.
- Renamed `CancelMode` to `CallCancelMode`. `CancelMode` is now a deprecated
alias to `CallCancelMode`.
- Renamed `Basic[Coro]<Event|Invocation>Unpacker` to
`Simple[Coro]<Event|Invocation>Unpacker`, with the former kept as deprecated
aliases.
- Renamed `basic[Coro]<Event|Rpc>` to `simple[Coro]<Event|Rpc>`, with the
former kept as deprecated aliases.
- Renamed the CppWAMP::coro-headers CMake target to CppWAMP::coro-usage,
leaving the former as an alias.
- Deprecated `CoroSession` and `AsyncResult`.
- Deprecated `error::Decode`
- Deprecated the `Session::cancel` overloads taking `CallCancellation`.
- Deprecated `Outcome::deferred`.


### Breaking Changes

- Bumped Boost version requirements to 1.77 to support Asio cancellation slots.
- Errors due to attempting to perform an asynchronous `Session` operation during
an invalid state are now emitted via the `ErrorOr` passed to the handler,
instead of throwing `error::Logic`. This is to avoid `error::Logic` exceptions
being thrown due to race conditions outside the library user's control (for
example, calling a remote procedure just as the peer terminates the session).
This also avoids the complications involved in transporting exceptions to
coroutines, as well as having two mechanisms for reporting errors from the
same function.
- `Session::authenticate` no longer throws if the session is not in the
`SessionState::authenticating` state. Instead, the authentication is discarded
and a warning is emitted.
- `Session::publish(Pub)` no longer throws if the session is not in the
`SessionState::established` state. Instead, the publicatioon is discarded
and a warning is emitted.
- `Session::cancel` no longer throws if the session is not in the
`SessionState::established` state. Instead, the cancellation is discarded
and a warning is emitted.
- Numeric values of enumerators following `SesesionErrc::invalidState` have
been bumped by one.
- `Session::call` no longer returns the request ID. To obtain the request ID,
use the new `Session::call` overload which takes a `CallChit` out
parameter by reference.
- The signature of `lookupWampErrorUri` has been changed so that it returns
whether the corresponding error code was found.
- Codec decoders now return a std::error_code instead of throwing an exception.
- The `Transport` type requirement has been changed so that it provides a
`boost::asio::strand` instead of a `boost::asio::any_executor`.

### Migration Guide

- Replace `AnyExecutor` with `AnyIoExecutor`.
- Replace `AsyncResult` with `ErrorOr`.
- Replace `AsyncResult::get` with `ErrorOr::value`.
- Replace `AsyncResult::errorCode` with `ErrorOr::error`.
- Replace `AsyncResult::setValue` with `ErrorOr::emplace`.
- Replace `Basic[Coro]<Event|Invocation>Unpacker` with
`Simple[Coro]<Event|Invocation>Unpacker`
- Replace `basic[Coro]<Event|Rpc>` with `simple[Coro]<Event|Rpc>`
- Replace `Cancellation` with `CallCancellation`
- Replace `CancelMode` with `CallCancelMode`
- Replace `CoroSession<>` with `Session`.
- Replace `Outcome::deferred` with `deferment`.
- Replace `#include <cppwamp/corosession.hpp>` with
`#include <boost/asio/spawn.hpp>` and `#include <cppwamp/session.hpp>`.
- Add `.value()` to `Session` methods taking a `yield_context` to preserve the
old behavior where either the result value is returned upon success or an
exception is thrown upon failure.
- `std::error_code` pointers cannot be passed to the the consolidated `Session`
class. Instead check the returned `ErrorOr` result via `operator bool` and
`AsyncResult::error()`.
- `Session::call` no longer returns the RPC request ID. Instead use the
`Session::call` overload which takes a `CallChit` out parameter by reference.
Alternatively, you may bind an Asio cancellation slot to the completion token.
- Replace `Session::cancel(CallCancellation)` usages with
`Session::cancel(CallChit)`.
- If used directly, check the `std::error_code` returned by codec decoders
instead of catching `error::Decode` exceptions.
- Replace the `CppWAMP::coro-headers` CMake target with `CppWAMP::coro-usage`.


v0.9.2
======
Fixed the non-compilation of examples.


v0.9.1
======
Add -fPIC when building vendorized static Boost libraries.
Expand Down
22 changes: 13 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
# This project defines one of more of the following targets, depending
# on the how the CPPWAMP_OPT_X options are set:
#
# Target | Import alias | All | Description
# ----------------------- | ------------------------ | --- | -----------
# cppwamp-core | CppWAMP::core | Yes | Compiled libcppwamp-core library
# cppwamp-core-headers | CppWAMP::core-headers | Yes | Header-only usage requirements
# cppwamp-coro-headers | CppWAMP::coro-headers | Yes | Boost.Coroutine usage requirements
# cppwamp-doc | <none> | No | Doxygen documentation
# cppwamp-examples | <none> | No | Compiled example programs
# cppwamp-test | <none> | No | Compiled test suite program
# Target | Import alias | All | Description
# -------------------- | --------------------- | --- | -----------
# cppwamp-core | CppWAMP::core | Yes | Compiled libcppwamp-core library
# cppwamp-core-headers | CppWAMP::core-headers | Yes | Header-only usage requirements
# cppwamp-coro-usage | CppWAMP::coro-usage | Yes | Boost.Coroutine usage requirements
# cppwamp-doc | <none> | No | Doxygen documentation
# cppwamp-examples | <none> | No | Compiled example programs
# cppwamp-test | <none> | No | Compiled test suite program
#
# 'All' means that the target (if enabled) is built as part of the 'all' target.
# 'Usage requirements' means that the appropriate compiler flags will be set
Expand All @@ -38,7 +38,7 @@ cmake_minimum_required (VERSION 3.12)
include_guard()

project(CppWAMP
VERSION 0.9.1
VERSION 0.10.0
LANGUAGES CXX)

include(ProcessorCount)
Expand Down Expand Up @@ -84,6 +84,10 @@ option(CPPWAMP_OPT_WITH_CORO
that depend on it"
ON)

option(CPPWAMP_OPT_WITH_CORO20
"Adds C++20 couroutine examples if examples are enabled"
OFF)

option(CPPWAMP_OPT_WITH_DOCS
"Creates a build target for generating documentation"
${isTopLevel})
Expand Down
36 changes: 25 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ C++11 client library for the [WAMP][wamp] protocol.
- Roles: _Caller_, _Callee_, _Subscriber_, _Publisher_
- Transports: TCP and Unix domain raw sockets
- Serializations: JSON, MsgPack, and CBOR
- Provides both callback and coroutine-based asynchronous APIs
- Supports Boost.Asio completion tokens for callbacks, stackful coroutines,
stackless couroutines, C++20 coroutines, and std::future.
- Easy conversion between static and dynamic types
- RPC and pub/sub event handlers can have static argument types
- User-defined types can be registered and exchanged via RPC and pub-sub
Expand All @@ -21,7 +22,7 @@ C++11 client library for the [WAMP][wamp] protocol.
**Dependencies**:

- [Boost.Asio][boost-asio] for raw socket transport
(requires [Boost][boost] 1.74 or greater)
(requires [Boost][boost] 1.77 or greater)
- [jsoncons][jsoncons] for serialization
- (optional) [Boost.Coroutine][boost-coroutine] and
[Boost.Context][boost-context]
Expand Down Expand Up @@ -50,8 +51,8 @@ Tested Platforms

This library has been tested with:

- GCC x86_64-linux-gnu, versions 7.5 and 10.3
- Clang x86_64-pc-linux-gnu, versions 6.0.1 and 12.0,
- GCC x86_64-linux-gnu, version 10.3
- Clang x86_64-pc-linux-gnu, version 12.0

<a name="advanced"></a>Supported Advanced Profile Features
----------------------------------------------------------
Expand All @@ -70,19 +71,23 @@ This library has been tested with:
Roadmap
-------

### v0.11

- Polymorphic codecs and transports to prevent combinatorial explosion of
explicit template instantiations when new codecs/transports are added.

### v1.0

- Make `wamp::Session` more thread-safe.
- Remove `wamp::CoroSession` and make it so that `wamp::Session` can accept any
completion token (`yield`, `use_future`, etc) supported by Boost.Asio.
- Remove all deprecated types and functions.
- Aim for API stability until v2.0.

### v1.1

- Add embedded router functionality
- Embedded router functionality

### v1.2 (maybe)

- Add websocket support via Boost.Beast
- Websocket support via Boost.Beast

### v2.0 (maybe)

Expand All @@ -104,8 +109,8 @@ For reporting bugs or for suggesting enhancements, please use the GitHub
[issues]: https://github.com/ecorm/cppwamp/issues


Usage Examples Using Coroutines
---------------------------------
Usage Examples Using Stackful Coroutines
----------------------------------------

_For a more comprehensive overview, check out the
[Tutorials](https://ecorm.github.io/cppwamp/_tutorial.html) in the
Expand Down Expand Up @@ -517,6 +522,15 @@ your project or via your project's CMake scripts (for example by using
`ExternalProject_add` or `FetchContent`).


Bundled Open-Source Software
----------------------------

This library bundles modified versions of `any_completion_handler` and
`any_completion_executor` written by Christopher M. Kohlhoff,
Copyright (c) 2003-2022, under the terms of the Boost Software License,
Version 1.0 (http://www.boost.org/LICENSE_1_0.txt).


License
-------

Expand Down
9 changes: 4 additions & 5 deletions cmake/CppWAMPDependencies.cmake
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#-------------------------------------------------------------------------------
# Copyright Butterfly Energy Systems 2022.
# 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)
# Copyright Butterfly Energy Systems 2022.
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
#-------------------------------------------------------------------------------

include_guard()
Expand All @@ -11,7 +10,7 @@ include(FetchContent)
set(FETCHCONTENT_QUIET OFF CACHE INTERNAL "")

# These minumum dependency versions must be made the same in CppWAMPConfig.cmake
set(CPPWAMP_MINIMUM_BOOST_VERSION 1.74.0)
set(CPPWAMP_MINIMUM_BOOST_VERSION 1.77.0)

set(CPPWAMP_VENDORIZED_BOOST_VERSION 1.79.0)
set(CPPWAMP_VENDORIZED_BOOST_SHA256
Expand Down
7 changes: 3 additions & 4 deletions cmake/FindCatch2.cmake
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#-------------------------------------------------------------------------------
# Copyright Butterfly Energy Systems 2022.
# 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)
# Copyright Butterfly Energy Systems 2022.
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
#-------------------------------------------------------------------------------

#[=======================================================================[.rst:
Expand Down
7 changes: 3 additions & 4 deletions cmake/FindJsoncons.cmake
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#-------------------------------------------------------------------------------
# Copyright Butterfly Energy Systems 2022.
# 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)
# Copyright Butterfly Energy Systems 2022.
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
#-------------------------------------------------------------------------------

#[=======================================================================[.rst:
Expand Down
25 changes: 15 additions & 10 deletions cppwamp-coro/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
#-------------------------------------------------------------------------------
# Copyright Butterfly Energy Systems 2022.
# 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)
# Copyright Butterfly Energy Systems 2022.
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
#-------------------------------------------------------------------------------

add_library(cppwamp-coro-headers INTERFACE)
target_compile_features(cppwamp-coro-headers INTERFACE cxx_std_11)
target_link_libraries(cppwamp-coro-headers
# Empty interface library for conveniently adding usage requirements to
# projects wanting to use stackful coroutines.
add_library(cppwamp-coro-usage INTERFACE)
target_compile_features(cppwamp-coro-usage INTERFACE cxx_std_11)
target_link_libraries(cppwamp-coro-usage
INTERFACE
CppWAMP::core-headers
CppWAMP::coro-usage
"$<TARGET_NAME_IF_EXISTS:Boost::coroutine>")
set_target_properties(cppwamp-coro-headers PROPERTIES EXPORT_NAME coro-headers)
add_library(CppWAMP::coro-headers ALIAS cppwamp-coro-headers)
set_target_properties(cppwamp-coro-usage PROPERTIES EXPORT_NAME coro-usage)
add_library(CppWAMP::coro-usage ALIAS cppwamp-coro-usage)

# Deprecated aliases left for backward compatibility
add_library(cppwamp-coro-headers ALIAS cppwamp-coro-usage)
add_library(CppWAMP::coro-headers ALIAS cppwamp-coro-usage)
Loading

0 comments on commit 29153f6

Please sign in to comment.