Ignore:
Timestamp:
2019-07-24T11:44:40Z (5 years ago)
Author:
GitHub <noreply@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a448937, f42ee6f
Parents:
9fb280c (diff), 8c0b781 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Jaroslav Jindrak <Dzejrou@…> (2019-07-24 11:44:40)
git-committer:
GitHub <noreply@…> (2019-07-24 11:44:40)
Message:

Merge pull request #171 from Dzejrou/hackweek

C++ stdlib: <future>

File:
1 edited

Legend:

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

    r9fb280c r9fe2fd7  
    3030#define LIBCPP_BITS_THREAD_FUTURE
    3131
     32#include <__bits/thread/future_common.hpp>
     33#include <__bits/thread/shared_state.hpp>
     34#include <__bits/utility/forward_move.hpp>
    3235#include <cassert>
    33 #include <memory>
    34 #include <system_error>
    35 #include <type_traits>
    3636
    3737namespace std
    3838{
    3939    /**
    40      * 30.6, futures:
     40     * 30.6.6, class template future:
    4141     */
    4242
    43     enum class future_errc
    44     { // The 5001 start is to not collide with system_error's codes.
    45         broken_promise = 5001,
    46         future_already_retrieved,
    47         promise_already_satisfied,
    48         no_state
     43    namespace aux
     44    {
     45        /**
     46         * Note: Because of shared_future, this base class
     47         *       does implement copy constructor and copy
     48         *       assignment operator. This means that the
     49         *       children (std::future) need to delete this
     50         *       constructor and operator themselves.
     51         */
     52        template<class R>
     53        class future_base
     54        {
     55            public:
     56                future_base() noexcept
     57                    : state_{nullptr}
     58                { /* DUMMY BODY */ }
     59
     60                future_base(const future_base& rhs)
     61                    : state_{rhs.state_}
     62                {
     63                    state_->increment();
     64                }
     65
     66                future_base(future_base&& rhs) noexcept
     67                    : state_{move(rhs.state_)}
     68                {
     69                    rhs.state_ = nullptr;
     70                }
     71
     72                future_base(aux::shared_state<R>* state)
     73                    : state_{state}
     74                {
     75                    /**
     76                     * Note: This is a custom non-standard constructor that allows
     77                     *       us to create a future directly from a shared state. This
     78                     *       should never be a problem as aux::shared_state is a private
     79                     *       type and future has no constructor templates.
     80                     */
     81                }
     82
     83                virtual ~future_base()
     84                {
     85                    release_state_();
     86                }
     87
     88                future_base& operator=(const future_base& rhs)
     89                {
     90                    release_state_();
     91                    state_ = rhs.state_;
     92
     93                    state_->increment();
     94
     95                    return *this;
     96                }
     97
     98                future_base& operator=(future_base&& rhs) noexcept
     99                {
     100                    release_state_();
     101                    state_ = move(rhs.state_);
     102                    rhs.state_ = nullptr;
     103
     104                    return *this;
     105                }
     106
     107                bool valid() const noexcept
     108                {
     109                    return state_ != nullptr;
     110                }
     111
     112                void wait() const noexcept
     113                {
     114                    assert(state_);
     115
     116                    state_->wait();
     117                }
     118
     119                template<class Rep, class Period>
     120                future_status
     121                wait_for(const chrono::duration<Rep, Period>& rel_time) const
     122                {
     123                    assert(state_);
     124
     125                    return state_->wait_for(rel_time);
     126                }
     127
     128                template<class Clock, class Duration>
     129                future_status
     130                wait_until(
     131                    const chrono::time_point<Clock, Duration>& abs_time
     132                ) const
     133                {
     134                    assert(state_);
     135
     136                    return state_->wait_until(abs_time);
     137                }
     138
     139            protected:
     140                void release_state_()
     141                {
     142                    if (!state_)
     143                        return;
     144
     145                    /**
     146                     * Note: This is the 'release' move described in
     147                     *       30.6.4 (5).
     148                     * Last reference to state -> destroy state.
     149                     * Decrement refcount of state otherwise.
     150                     * Will not block, unless all following hold:
     151                     *  1) State was created by call to std::async.
     152                     *  2) State is not yet ready.
     153                     *  3) This was the last reference to the shared state.
     154                     */
     155                    if (state_->decrement())
     156                    {
     157                        /**
     158                         * The destroy call handles the special case
     159                         * when 1) - 3) hold.
     160                         */
     161                        state_->destroy();
     162                        delete state_;
     163                        state_ = nullptr;
     164                    }
     165                }
     166
     167                aux::shared_state<R>* state_;
     168        };
     169    }
     170
     171    template<class R>
     172    class shared_future;
     173
     174    template<class R>
     175    class future: public aux::future_base<aux::future_inner_t<R>>
     176    {
     177        friend class shared_future<R>;
     178
     179        public:
     180            future() noexcept
     181                : aux::future_base<aux::future_inner_t<R>>{}
     182            { /* DUMMY BODY */ }
     183
     184            future(const future&) = delete;
     185
     186            future(future&& rhs) noexcept
     187                : aux::future_base<aux::future_inner_t<R>>{move(rhs)}
     188            { /* DUMMY BODY */ }
     189
     190            future(aux::shared_state<aux::future_inner_t<R>>* state)
     191                : aux::future_base<aux::future_inner_t<R>>{state}
     192            { /* DUMMY BODY */ }
     193
     194            future& operator=(const future&) = delete;
     195
     196            future& operator=(future&& rhs) noexcept = default;
     197
     198            shared_future<R> share()
     199            {
     200                return shared_future<R>{move(*this)};
     201            }
     202
     203            R get()
     204            {
     205                assert(this->state_);
     206
     207                this->wait();
     208
     209                if (this->state_->has_exception())
     210                    this->state_->throw_stored_exception();
     211
     212                if constexpr (!is_same_v<R, void>)
     213                {
     214                    if constexpr (is_reference_v<R>)
     215                    {
     216                        assert(this->state_->get());
     217
     218                        return *this->state_->get();
     219                    }
     220                    else
     221                        return this->state_->get();
     222                }
     223            }
     224
     225            /**
     226             * Useful for testing as we can check some information
     227             * otherwise unavailable to us without waiting, e.g.
     228             * to check whether the state is ready, its reference
     229             * count etc.
     230             */
     231            aux::shared_state<aux::future_inner_t<R>>* __state() noexcept
     232            {
     233                return this->state_;
     234            }
    49235    };
    50 
    51     enum class launch
    52     {
    53         async,
    54         deferred
    55     };
    56 
    57     enum class future_status
    58     {
    59         ready,
    60         timeout,
    61         deferred
    62     };
    63 
    64     /**
    65      * 30.6.2, error handling:
    66      */
    67 
    68     template<>
    69     struct is_error_code_enum<future_errc>: true_type
    70     { /* DUMMY BODY */ };
    71 
    72     error_code make_error_code(future_errc) noexcept;
    73     error_condition make_error_condition(future_errc) noexcept;
    74 
    75     const error_category& future_category() noexcept;
    76 
    77     /**
    78      * 30.6.3, class future_error:
    79      */
    80 
    81     class future_error: public logic_error
    82     {
    83         public:
    84             future_error(error_code ec);
    85 
    86             const error_code& code() const noexcept;
    87 
    88         private:
    89             error_code code_;
    90     };
    91 
    92     /**
    93      * 30.6.4, shared state:
    94      */
    95 
    96     template<class R>
    97     class promise
    98     {
    99     };
    100 
    101     template<class R>
    102     class promise<R&>
    103     {
    104     };
    105 
    106     template<>
    107     class promise<void>
    108     {
    109     };
    110 
    111     template<class R>
    112     void swap(promise<R>& lhs, promise<R>& rhs) noexcept
    113     {
    114         lhs.swap(rhs);
    115     }
    116 
    117     template<class R, class Alloc>
    118     struct uses_allocator<promise<R>, Alloc>: true_type
    119     { /* DUMMY BODY */ };
    120 
    121     template<class R>
    122     class future
    123     {
    124     };
    125 
    126     template<class R>
    127     class future<R&>
    128     {
    129     };
    130 
    131     template<>
    132     class future<void>
    133     {
    134     };
    135 
    136     template<class R>
    137     class shared_future
    138     {
    139     };
    140 
    141     template<class R>
    142     class shared_future<R&>
    143     {
    144     };
    145 
    146     template<>
    147     class shared_future<void>
    148     {
    149     };
    150 
    151     template<class>
    152     class packaged_task; // undefined
    153 
    154     template<class R, class... Args>
    155     class packaged_task<R(Args...)>
    156     {
    157     };
    158 
    159     template<class R, class... Args>
    160     void swap(packaged_task<R(Args...)>& lhs, packaged_task<R(Args...)>& rhs) noexcept
    161     {
    162         lhs.swap(rhs);
    163     };
    164 
    165     template<class R, class Alloc>
    166     struct uses_allocator<packaged_task<R>, Alloc>: true_type
    167     { /* DUMMY BODY */ };
    168 
    169     template<class F, class... Args>
    170     future<result_of_t<decay_t<F>(decay_t<Args>...)>>
    171     async(F&& f, Args&&... args)
    172     {
    173         // TODO: implement
    174         __unimplemented();
    175     }
    176 
    177     template<class F, class... Args>
    178     future<result_of_t<decay_t<F>(decay_t<Args>...)>>
    179     async(launch, F&& f, Args&&... args)
    180     {
    181         // TODO: implement
    182         __unimplemented();
    183     }
    184236}
    185237
Note: See TracChangeset for help on using the changeset viewer.