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

Changeset 60cb9e1 in mainline


Ignore:
Timestamp:
2019-07-01T09:50:26Z (16 months ago)
Author:
Jaroslav Jindrak <dzejrou@…>
Branches:
master
Children:
d340254
Parents:
bd6ad4b
Message:

cpp: make shared_state work with void as its template parameter

File:
1 edited

Legend:

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

    rbd6ad4b r60cb9e1  
    4444#include <tuple>
    4545
    46 namespace std
    47 {
    48     enum class future_status;
    49 }
    50 
    5146namespace std::aux
    5247{
    53     template<class R>
    54     class shared_state: public aux::refcount_obj
    55     {
    56         public:
    57             shared_state()
    58                 : mutex_{}, condvar_{}, value_{}, value_set_{false},
     48    /**
     49     * TODO: Make this a shared_state_base which will not have the
     50     *       set_value functions, but will keep the rest. Then create
     51     *       shared state with the set_value function and a specialization
     52     *       of that with a set_value that takes no arguments.
     53     *
     54     *       The value itself should be in the children (as the void one
     55     *       won't have it).
     56     */
     57    class shared_state_base: public aux::refcount_obj
     58    {
     59        public:
     60            shared_state_base()
     61                : mutex_{}, condvar_{}, value_set_{false},
    5962                  exception_{}, has_exception_{false}
    6063            {
     
    7275            }
    7376
    74             void set_value(const R& val, bool set)
    75             {
    76                 /**
    77                  * Note: This is the 'mark ready' move described
    78                  *       in 30.6.4 (6).
    79                  */
    80 
    81                 aux::threading::mutex::lock(mutex_);
    82                 value_ = val;
     77            void mark_set(bool set = true) noexcept
     78            {
    8379                value_set_ = set;
    84                 aux::threading::mutex::unlock(mutex_);
    85 
    86                 aux::threading::condvar::broadcast(condvar_);
    87             }
    88 
    89             void set_value(R&& val, bool set = true)
    90             {
    91                 aux::threading::mutex::lock(mutex_);
    92                 value_ = std::move(val);
    93                 value_set_ = set;
    94                 aux::threading::mutex::unlock(mutex_);
    95 
    96                 aux::threading::condvar::broadcast(condvar_);
    97             }
    98 
    99             void mark_set(bool set = true) noexcept
    100             {
    101                 value_set_ = set;
    10280            }
    10381
     
    10583            {
    10684                return value_set_;
    107             }
    108 
    109             R& get()
    110             {
    111                 return value_;
    11285            }
    11386
     
    165138                aux::threading::mutex::lock(mutex_);
    166139                auto res = timed_wait_(
    167                     aux::threading::time(convert(abs_time - Clock::now()))
     140                    aux::threading::time::convert(abs_time - Clock::now())
    168141                );
    169142                aux::threading::mutex::unlock(mutex_);
     
    172145            }
    173146
    174             ~shared_state() override = default;
     147            ~shared_state_base() override = default;
    175148
    176149        protected:
     
    178151            aux::condvar_t condvar_;
    179152
    180             R value_;
    181153            bool value_set_;
    182154
     
    205177    };
    206178
     179    template<class R>
     180    class shared_state: public shared_state_base
     181    {
     182        public:
     183            shared_state()
     184                : shared_state_base{}
     185            { /* DUMMY BODY */ }
     186
     187            void set_value(const R& val, bool set)
     188            {
     189                /**
     190                 * Note: This is the 'mark ready' move described
     191                 *       in 30.6.4 (6).
     192                 */
     193
     194                aux::threading::mutex::lock(mutex_);
     195                value_ = val;
     196                value_set_ = set;
     197                aux::threading::mutex::unlock(mutex_);
     198
     199                aux::threading::condvar::broadcast(condvar_);
     200            }
     201
     202            void set_value(R&& val, bool set = true)
     203            {
     204                aux::threading::mutex::lock(mutex_);
     205                value_ = std::move(val);
     206                value_set_ = set;
     207                aux::threading::mutex::unlock(mutex_);
     208
     209                aux::threading::condvar::broadcast(condvar_);
     210            }
     211
     212            R& get()
     213            {
     214                return value_;
     215            }
     216
     217        protected:
     218            R value_;
     219    };
     220
     221    template<>
     222    class shared_state<void>: public shared_state_base
     223    {
     224        public:
     225            shared_state()
     226                : shared_state_base{}
     227            { /* DUMMY BODY */ }
     228
     229            void set_value()
     230            {
     231                value_set_ = true;
     232                aux::threading::condvar::broadcast(condvar_);
     233            }
     234
     235            void get()
     236            { /* DUMMY BODY */ }
     237    };
     238
    207239    /**
    208240     * We could make one state for both async and
     
    215247     * But since we have no plan (nor need) to make those,
    216248     * this approach seems to be the best one.
     249     *
     250     * Also note that unlike the parent class shared_state,
     251     * we do not need to specialize these for void. This is because
     252     * the difference in class contents are handled by the parent
     253     * specialization and setting the value can be handled easily
     254     * by if constexpr and checking for the equivalence of the
     255     * R template parameter and void.
    217256     */
    218257
     
    228267                        try
    229268                        {
    230                             this->set_value(invoke(f, args...));
     269                            if constexpr (!is_same_v<R, void>)
     270                                this->set_value(invoke(f, args...));
     271                            else
     272                            {
     273                                invoke(f, args...);
     274                                this->mark_set(true);
     275                            }
    231276                        }
    232277                        catch(...) // TODO: Any exception.
     
    307352                try
    308353                {
    309                     this->set_value(invoke(move(func_), get<Is>(move(args_))...));
     354                    if constexpr (!is_same_v<R, void>)
     355                        this->set_value(invoke(move(func_), get<Is>(move(args_))...));
     356                    else
     357                    {
     358                        invoke(move(func_), get<Is>(move(args_))...);
     359                        this->mark_set(true);
     360                    }
    310361                }
    311362                catch(...)
Note: See TracChangeset for help on using the changeset viewer.