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

Changeset a6c3bf3 in mainline


Ignore:
Timestamp:
2019-07-01T15:33:01Z (16 months ago)
Author:
Jaroslav Jindrak <dzejrou@…>
Branches:
master
Children:
8660ad0
Parents:
a552044
Message:

cpp: remove redundant specializations of shared_future using some metaprogramming tricks

Location:
uspace/lib/cpp/include/__bits/thread
Files:
2 edited

Legend:

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

    ra552044 ra6c3bf3  
    3030#define LIBCPP_BITS_THREAD_FUTURE_COMMON
    3131
     32#include <__bits/aux.hpp>
    3233#include <system_error>
    3334#include <stdexcept>
     
    8283            error_code code_;
    8384    };
     85
     86    namespace aux
     87    {
     88        /**
     89         * Auxilliary metafunctions that let us avoid
     90         * specializations in some cases. They represent
     91         * the inner stored type and the return type of
     92         * the get() member function, respectively.
     93         */
     94
     95        template<class T>
     96        struct future_inner: aux::type_is<T>
     97        { /* DUMMY BODY */ };
     98
     99        template<class T>
     100        struct future_inner<T&>: aux::type_is<T*>
     101        { /* DUMMY BODY */ };
     102
     103        template<class T>
     104        using future_inner_t = typename future_inner<T>::type;
     105
     106        template<class T>
     107        struct future_return: aux::type_is<const T&>
     108        { /* DUMMY BODY */ };
     109
     110        template<class T>
     111        struct future_return<T&>: aux::type_is<T&>
     112        { /* DUMMY BODY */ };
     113
     114        template<>
     115        struct future_return<void>: aux::type_is<void>
     116        { /* DUMMY BODY */ };
     117
     118        template<class T>
     119        using future_return_t = typename future_return<T>::type;
     120    }
    84121}
    85122
  • uspace/lib/cpp/include/__bits/thread/shared_future.hpp

    ra552044 ra6c3bf3  
    3131
    3232#include <__bits/thread/future.hpp>
     33#include <__bits/thread/future_common.hpp>
     34#include <type_traits>
    3335
    3436/**
     
    4951
    5052    template<class R>
    51     class shared_future: public aux::future_base<R>
     53    class shared_future: public aux::future_base<aux::future_inner_t<R>>
    5254    {
    5355        public:
     
    5961
    6062            shared_future(future<R>&& rhs)
    61                 : aux::future_base<R>{move(rhs.state_)}
     63                : aux::future_base<aux::future_inner_t<R>>{move(rhs.state_)}
    6264            {
    6365                rhs.state_ = nullptr;
     
    6870            shared_future& operator=(shared_future&&) noexcept = default;
    6971
    70             const R& get() const
     72            aux::future_return_t<R> get() const
    7173            {
    7274                assert(this->state_);
     
    7779                    this->state_->throw_stored_exception();
    7880
    79                 return move(this->state_->get());
    80             }
    81     };
     81                /**
     82                 * Using constexpr if and the future_inner and future_result
     83                 * metafunctions we can actually avoid having to create specializations
     84                 * for R& and void in this case.
     85                 */
     86                if constexpr (!is_same_v<R, void>)
     87                {
     88                    if constexpr (is_reference_v<R>)
     89                    {
     90                        assert(this->state_->get());
    8291
    83     template<class R>
    84     class shared_future<R&>: public aux::future_base<R*>
    85     {
    86         public:
    87             shared_future() noexcept = default;
    88 
    89             shared_future(const shared_future&) = default;
    90 
    91             shared_future(shared_future&&) noexcept = default;
    92 
    93             shared_future(future<R&>&& rhs)
    94                 : aux::future_base<R*>{move(rhs.state_)}
    95             {
    96                 rhs.state_ = nullptr;
    97             }
    98 
    99             shared_future& operator=(const shared_future&) = default;
    100 
    101             shared_future& operator=(shared_future&&) noexcept = default;
    102 
    103             R& get() const
    104             {
    105                 assert(this->state_);
    106 
    107                 this->wait();
    108 
    109                 if (this->state_->has_exception())
    110                     this->state_->throw_stored_exception();
    111 
    112                 assert(this->state_->get());
    113                 return *this->state_->get();
    114             }
    115     };
    116 
    117     template<>
    118     class shared_future<void>: public aux::future_base<void>
    119     {
    120         public:
    121             shared_future() noexcept = default;
    122 
    123             shared_future(const shared_future&) = default;
    124 
    125             shared_future(shared_future&&) noexcept = default;
    126 
    127             shared_future(future<void>&& rhs)
    128                 : aux::future_base<void>{move(rhs.state_)}
    129             {
    130                 rhs.state_ = nullptr;
    131             }
    132 
    133             shared_future& operator=(const shared_future&) = default;
    134 
    135             shared_future& operator=(shared_future&&) noexcept = default;
    136 
    137             void get() const
    138             {
    139                 assert(this->state_);
    140 
    141                 this->wait();
    142 
    143                 if (this->state_->has_exception())
    144                     this->state_->throw_stored_exception();
     92                        return *this->state_->get();
     93                    }
     94                    else
     95                        return this->state_->get();
     96                }
    14597            }
    14698    };
Note: See TracChangeset for help on using the changeset viewer.