Code Monkey home page Code Monkey logo

ufiber's Introduction

μfiber

Language Build Coverage License
Standard hosted-latest-vcpkg codecov License

Introduction

μfiber is a minimalistic, header-only fiber library compatible with the asynchronous operation model specified in the C++ Networking TS and implemented in Boost.ASIO. It implements an interface similar to boost::asio::spawn(), but takes advantage of C++11 move semantics to avoid additional memory allocations that are necessary in boost::asio::spawn() and supports more than 2 results of an asynchronous operation. Additionally, this library does not use deprecated Boost libraries, so it generates no deprecation warnings when used.

Dependencies

μfiber depends on:

  • Boost.Context
  • Boost.ASIO

Installation

μfiber is header-only, so you only need to add the include directory to the include paths in your build system. An install target is available in CMake which will install the headers and a CMake find_package configuration script for easy consumption in projects built with CMake:

mkdir build
cd build
cmake ..
make install

After installation, a project built with CMake can consume the library using find_package:

find_package(ufiber REQUIRED)
target_link_libraries(my_target PUBLIC ufiber::ufiber)

Examples

  • Echo - a well documented, echo server that uses fibers to accept clients and then sends back octets to the client.

API

yield_token

template<class Executor>
class yield_token
{
public:
    using executor_type = Executor;

    executor_type get_executor() noexcept;
};

struct broken_promise final : std::exception
{
    char const* what() const noexcept final;
};

yield_token is a lightweight handle to the currently running fiber, which may be used as a CompletionToken in an asynchronous initiation function. The behavior of a yield_token, outside the fiber it was created on, is undefined. Executor shall satisfy the constraints of Executor. The executor on which the current fiber runs can be retrieved via get_executor().

When yield_token is used as a CompletionToken, the asynchronous initiation function that it is passed to as an argument will suspend execution of the current fiber. Once the operation completes, the fiber is resumed and the async function will return the results of the operation as its return value. The return type depends on the number of results:

  • 0 results: returns void
  • 1 result: returns T
  • N results: returns std::tuple<T...>

Exceptions

If an asynchronous operation has been abandoned, the fiber will be resumed but the asynchronous initiation function will throw ufiber::broken_promise. This happens if an io_context is destroyed with pending asynchronous operations. If exceptions are disabled, the user will need to provide their own definition of [[noreturn]] ufiber::detail::throw_broken_promise(). Note that, if an operation has been abandoned, the fiber may not be running within the context of its executor, so catching ufiber::broken_promise is not recommended.

Any exception (except for ufiber::broken_promise) that excapes the fiber's main function, will result in a call to std::terminate() (same behavior as in std::thread).


Spawning fibers

Fibers are created by calling one of the provided overloads of the spawn() function. Fibers are scheduled on the executor they are spawned on, migration between threads is managed by the executor. Note that when using this library with executors provided by ASIO, one needs to either avoid using TLS variables or ensure that the executor cannot schedule the fiber on another thread.

  1. Spawn a fiber on ex with the function object f as its main function. The implementation will construct an object from f via DECAY_COPY. This function participates in overload resolution if and only if, E satisfies the constraints of Executor:

    template<class E, class F>
    auto
    spawn(E const& ex, F&& f) -> /* SFINAE */ void;

    Requires:

    • F shall be invokable with the signature void(yield_token<E>)

    Example usage:

    boost::asio::io_context io;
    boost::asio::strand<decltype(io)::executor_type> strand{io.get_executor()};
    ufiber::spawn(
        strand,
        [](ufiber::yield_token<decltype(strand)> yield)
        {
            // The fiber will run on the strand
            boost::asio::steady_timer timer{yield.get_executor().context()};
            timer.expires_from_now(std::chrono::seconds{1});
            auto ec = timer.async_wait(yield);
            // Handle the timer expiration
        });

  2. Spawn a fiber on ctx's executor with the function object f as its main function. The implementation will construct an object from f via DECAY_COPY. This function participates in overload resolution if and only if, Ctx satisfies the constraints of ExecutionContext:

    template<class Ctx, class F>
    auto
    spawn(Ctx& ctx, F&& f) -> /* SFINAE */ void;

    Requires:

    • F shall be invokable with the signature void(yield_token<Ctx::executor_type>).

    Example usage:

    boost::asio::io_context io;
    
    ufiber::spawn(
        io,
        [](auto yield)
        {
            boost::asio::steady_timer timer{yield.get_executor().context()};
            timer.expires_from_now(std::chrono::seconds{1});
            auto ec = timer.async_wait(yield);
            // Handle the timer expiration
        });

  3. Spawn a fiber on ex with the function object f as its main function, sa will be used to allocate the fiber's stack. The implementation will construct an object from f via DECAY_COPY:

    template<class Alloc, class E, class F>
    void
    spawn(std::allocator_arg_t arg, StackAllocator&& sa, E const& ex, F&& f);

    Requires:

    • E shall satisfy the constraints of Executor.
    • F shall be invokable with the signature void(yield_token<E>).
    • Alloc shall satisfy the constraints of StackAllocator.

    Example usage:

    boost::asio::io_context io;
    
    ufiber::spawn(
        std::allocator_arg,
        boost::context::protected_fixedsize{PTHREAD_STACK_MIN},
        io.get_executor(),
        [](auto yield)
        {
            boost::asio::signal_set set{yield.get_executor().context()};
            set.add(SIGINT);
            set.add(SIGHUP);
            auto [ec, sig_num] = set.async_wait(yield);
            // Handle the signal
        });

License

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)

ufiber's People

Contributors

azure-pipelines[bot] avatar djarek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.