Skip to content

ASL libraries will be migrated here in the stlab namespace, new libraries will be created here.

License

Notifications You must be signed in to change notification settings

davidwilcox/libraries

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

stlab/libraries

ASL libraries will be migrated here in the stlab namespace, new libraries will be created here.

[ This is temporary documentation - to be replaced at a later date. ]

<stlab/future>

This is a proof of concept implementation of a packaged task and future to replace the standard components. This is a list of some of the differences from standard (as of C++14) and boost (as of boost 1.58.0).

There is no promise type, packaged_task and futures are created as pairs with the package() function.

package_task is copyable, not just movable, and the call operator is const. This allows packaged_task objects to be stored in std::function<>. Once any copy of a packaged_task<> is called, all copies are invalid.

future is also copyable, there is no need for a shared future. If a future is only used as an rvalue and there are no copies then the value returned, by get_try or through a continuation, will be moved.

Multiple continutations may be attached to a single future with then(). then() is declared const since it does not mutate the result object of the future.

The continuation is called with the value type, not the future. A sink argument to a continuation should take the argument by value and move the object as needed. If the continuation reads the argument it should take it by const&. Behavior of modifying the argument through a non-const reference is undefined (may be a compliation error).

If the last copy of a future destructs, the associated task and any held futures for the task arguments are released and the associated packaged_task will become a no-op if called.

There are no wait() or get() function. Instead there is a get_try() which returns an optional (or if T is void, the result is a bool with true indicating the associated task has executed.

If the associated task through an exception, get_try() with rethrow the exception.

For a future if T is move only then the future is move only and can only contain one continuation.

[ TODO - for notification of errors the plan is to add a recover() clause to futures which is passed the exception and may return a value T or rethrow. recover() will be executed prior to continuations. ]

when_all() takes an n'ary function and n futures as arguments.

Here is a trivial scheduler using threads:

auto schedule = [](auto f) // F is void() and movable
{
    thread(move(f)).detach();
};

Here is an example scheduler function that uses Apple's libdispatch.

auto schedule = [](auto f) // F is void() and movable
{
    using f_t = decltype(f);

    dispatch_async_f(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
            new f_t(std::move(f)), [](void* f_) {
                auto f = static_cast<f_t*>(f_);
                (*f)();
                delete f;
            });
};
template<typename R, typename ...Args >
class packaged_task<R (Args...)> {
  public:
    packaged_task();
    ~packaged_task();

    packaged_task(const packaged_task&);
    packaged_task(packaged_task&&) noexcept;
    packaged_task& operator=(const packaged_task&);
    packaged_task& operator=(packaged_task&&) noexcept;

    template <typename... A>
    void operator()(A&&... args) const;
};

template <typename T>
class future {
  public:
    future();
    ~future();

    future(const future&);
    future(future&&) noexcept;
    future& operator=(const future&);
    future& operator=(future&& x) noexcept;

    template <typename F>
    auto then(F&& f) const&; // -> future<result_of_t<F(T)>>

    template <typename S, typename F>
    auto then(S&& s, F&& f) const&; // -> future<result_of_t<F(T)>>

    template <typename F>
    auto then(F&& f) &&; // -> future<result_of_t<F(T)>>

    template <typename S, typename F>
    auto then(S&& s, F&& f) &&; // -> future<result_of_t<F(T)>>

    bool cancel_try();

    auto get_try() const&; // -> T == void ? bool : optional<T>
    auto get_try() &&; // -> T == void ? bool : optional<T>
};

template <typename S, typename F, typename... Ts>
auto when_all(S, F, future<Ts>... args); // -> future<result_of_t<F(Ts...>>

template <typename Sig, typename S, typename F>
auto package(S s, F f); // -> pair<packaged_task<Sig>, future<result_of_t<Sig>>>;

template <typename S, typename F, typename ...Args>
auto async(S s, F&& f, Args&&... args) -> future<std::result_of_t<F (Args...)>>

About

ASL libraries will be migrated here in the stlab namespace, new libraries will be created here.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 100.0%