Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset fda6dd4 in mainline


Ignore:
Timestamp:
2019-07-01T18:32:08Z (16 months ago)
Author:
Jaroslav Jindrak <dzejrou@…>
Branches:
master
Children:
239d25b
Parents:
1621f91
Message:

cpp: implemented packaged_task

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/cpp/include/__bits/thread/packaged_task.hpp

    r1621f91 rfda6dd4  
    3030#define LIBCPP_BITS_THREAD_PACKAGED_TASK
    3131
     32#include <__bits/functional/function.hpp>
     33#include <__bits/thread/future.hpp>
     34#include <__bits/thread/future_common.hpp>
     35#include <__bits/thread/shared_state.hpp>
     36#include <type_traits>
     37#include <utility>
     38
    3239namespace std
    3340{
     
    4249    class packaged_task<R(Args...)>
    4350    {
    44         packaged_task() noexcept
    45         {}
    46 
    47         template<class F>
    48         explicit packaged_task(F&& f)
    49         {}
    50 
    51         template<class F, class Allocator>
    52         explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f)
    53         {}
    54 
    55         ~packaged_task()
    56         {}
    57 
    58         packaged_task(const packaged_task&) = delete;
    59         packaged_task& operator=(const packaged_task&) = delete;
    60 
    61         packaged_task(packaged_task&& rhs)
    62         {}
    63 
    64         packaged_task& operator=(packaged_task&& rhs)
    65         {}
    66 
    67         void swap(packaged_task& other) noexcept
    68         {}
    69 
    70         bool valid() const noexcept
    71         {}
    72 
    73         future<R> get_future()
    74         {}
    75 
    76         void operator()(Args...)
    77         {}
    78 
    79         void make_ready_at_thread_exit(Args...)
    80         {}
    81 
    82         void reset()
    83         {}
     51        public:
     52            packaged_task() noexcept
     53                : func_{}, state_{}
     54            { /* DUMMY BODY */ }
     55
     56            template<
     57                class F, enable_if_t<
     58                    !is_same_v<
     59                        decay_t<F>, packaged_task<R(Args...)>
     60                    >, int
     61                > = 0
     62            >
     63            explicit packaged_task(F&& f)
     64                : func_{forward<F>(f)}, state_{new aux::shared_state<R>{}}
     65            { /* DUMMY BODY */ }
     66
     67            template<
     68                class F, class Allocator, enable_if_t<
     69                    is_same_v<
     70                        decay_t<F>, packaged_task<R(Args...)>
     71                    >, int
     72                > = 0
     73            >
     74            explicit packaged_task(allocator_arg_t, const Allocator& a, F&& f)
     75                : packaged_task{forward<F>(f)}
     76            {
     77                // TODO: use the allocator
     78            }
     79
     80            ~packaged_task()
     81            {
     82                if (state_)
     83                {
     84                    if (!state_->is_set())
     85                    {
     86                        // TODO: store future_error
     87                        state_->mark_set(true);
     88                    }
     89
     90                    if (state_->decrement())
     91                    {
     92                        state_->destroy();
     93                        delete state_;
     94                        state_ = nullptr;
     95                    }
     96                }
     97            }
     98
     99            packaged_task(const packaged_task&) = delete;
     100            packaged_task& operator=(const packaged_task&) = delete;
     101
     102            packaged_task(packaged_task&& rhs)
     103                : func_{move(rhs.func_)}, state_{move(rhs.state_)}
     104            { /* DUMMY BODY */ }
     105
     106            packaged_task& operator=(packaged_task&& rhs)
     107            {
     108                if (state_)
     109                {
     110                    if (state_->decrement())
     111                    {
     112                        state_->destroy();
     113                        delete state_;
     114                        state_ = nullptr;
     115                    }
     116                }
     117
     118                func_ = move(rhs.func_);
     119                state_ = move(rhs.state_);
     120
     121                return *this;
     122            }
     123
     124            void swap(packaged_task& other) noexcept
     125            {
     126                std::swap(func_, other.func_);
     127                std::swap(state_, other.state_);
     128            }
     129
     130            bool valid() const noexcept
     131            {
     132                return state_ != nullptr;
     133            }
     134
     135            future<R> get_future()
     136            {
     137                if (!state_)
     138                    throw future_error{make_error_code(future_errc::no_state)};
     139
     140                state_->increment();
     141
     142                return future<R>{state_};
     143            }
     144
     145            /**
     146             * Note: This is how the signature is in the standard,
     147             *       should be investigated and verified.
     148             */
     149            void operator()(Args... args)
     150            {
     151                if (!state_)
     152                    throw future_error{make_error_code(future_errc::no_state)};
     153                if (state_->is_set())
     154                {
     155                    throw future_error{
     156                        make_error_code(future_errc::promise_already_satisfied)
     157                    };
     158                }
     159
     160                try
     161                {
     162                    state_->set_value(invoke(func_, args...));
     163                }
     164                catch(...)
     165                {
     166                    // TODO: store it
     167                }
     168            }
     169
     170            void make_ready_at_thread_exit(Args...)
     171            {
     172                // TODO: implement
     173            }
     174
     175            void reset()
     176            {
     177                if (!state_)
     178                    throw future_error{make_error_code(future_errc::no_state)};
     179
     180                *this = packaged_task{move(func_)};
     181            }
     182
     183        private:
     184            function<R(Args...)> func_;
     185
     186            aux::shared_state<R>* state_;
    84187    };
    85188
Note: See TracChangeset for help on using the changeset viewer.