Changeset 48d9187 in mainline


Ignore:
Timestamp:
2018-07-05T21:41:19Z (6 years ago)
Author:
Dzejrou <dzejrou@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1df0165
Parents:
ee51635
git-author:
Dzejrou <dzejrou@…> (2018-03-01 22:20:05)
git-committer:
Dzejrou <dzejrou@…> (2018-07-05 21:41:19)
Message:

cpp: added generic joinable threads

Location:
uspace/lib/cpp
Files:
2 edited

Legend:

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

    ree51635 r48d9187  
    4141    }
    4242
     43    namespace aux
     44    {
     45        template<class Callable>
     46        int thread_main(void*);
     47
     48        /**
     49         * Fibrils in HelenOS are not joinable. They were
     50         * in the past, but that functionality was removed from them
     51         * so we created a workaround using a conditional variable that
     52         * comprises the following two wrapper classes.
     53         */
     54        class joinable_wrapper
     55        {
     56            public:
     57                joinable_wrapper()
     58                    : join_mtx_{}, join_cv_{},
     59                      finished_{false}, detached_{false}
     60                {
     61                    fibril_mutex_initialize(&join_mtx_);
     62                    fibril_condvar_initialize(&join_cv_);
     63                }
     64
     65                void join()
     66                {
     67                    fibril_mutex_lock(&join_mtx_);
     68                    while (!finished_)
     69                        fibril_condvar_wait(&join_cv_, &join_mtx_);
     70                    fibril_mutex_unlock(&join_mtx_);
     71                }
     72
     73                bool finished() const
     74                {
     75                    return finished_;
     76                }
     77
     78                void detach()
     79                {
     80                    detached_ = true;
     81                }
     82
     83                bool detached() const
     84                {
     85                    return detached_;
     86                }
     87
     88            protected:
     89                fibril_mutex_t join_mtx_;
     90                fibril_condvar_t join_cv_;
     91                bool finished_;
     92                bool detached_;
     93        };
     94
     95        template<class Callable>
     96        class callable_wrapper: public joinable_wrapper
     97        {
     98            public:
     99                callable_wrapper(Callable&& clbl)
     100                    : joinable_wrapper{}, callable_{forward<Callable>(clbl)}
     101                { /* DUMMY BODY */ }
     102
     103                void operator()()
     104                {
     105                    callable_();
     106
     107                    fibril_mutex_lock(&join_mtx_);
     108                    finished_ = true;
     109                    fibril_mutex_unlock(&join_mtx_);
     110
     111                    fibril_condvar_broadcast(&join_cv_);
     112                }
     113
     114            private:
     115                Callable callable_;
     116        };
     117    }
     118
    43119    /**
    44120     * 30.3.1, class thread:
     
    65141            template<class F, class... Args>
    66142            explicit thread(F&& f, Args&&... args)
     143                : id_{}
    67144            {
    68                 // TODO: create std::function out of f and args,
    69                 //       then use fibril_create with that as
    70                 //       the argument and call it?
    71                 id_ = fibril_create(f, nullptr);
     145                auto callable = [&](){
     146                    return f(forward<Args>(args)...);
     147                };
     148
     149                auto callable_wrapper = new aux::callable_wrapper<decltype(callable)>{move(callable)};
     150                joinable_wrapper_ = static_cast<aux::joinable_wrapper*>(callable_wrapper);
     151
     152                id_ = fibril_create(
     153                        aux::thread_main<decltype(callable_wrapper)>,
     154                        static_cast<void*>(callable_wrapper)
     155                );
    72156                fibril_add_ready(id_);
    73157            }
     
    99183        private:
    100184            fid_t id_;
     185            aux::joinable_wrapper* joinable_wrapper_{nullptr};
     186
     187            template<class Callable>
     188            friend int aux::thread_main(void*);
    101189    };
     190
     191    namespace aux
     192    {
     193        template<class CallablePtr>
     194        int thread_main(void* clbl)
     195        {
     196            if (!clbl)
     197                return 1;
     198
     199            auto callable = static_cast<CallablePtr>(clbl);
     200            (*callable)();
     201
     202            if (callable->detached()) // No thread owns the wrapper.
     203                delete callable;
     204
     205            return 0;
     206        }
     207    }
    102208
    103209    void swap(thread& x, thread& y) noexcept;
  • uspace/lib/cpp/src/thread.cpp

    ree51635 r48d9187  
    4242        if (joinable())
    4343        {
     44            if (joinable_wrapper_)
     45            {
     46                joinable_wrapper_->join();
     47                delete joinable_wrapper_;
     48            }
     49
    4450            // TODO: this crashes :(
    4551            /* fibril_teardown((fibril_t*)id_, false); */
     
    6975    bool thread::joinable() const noexcept
    7076    {
    71         return get_id() != id{};
     77        return id_ != fid_t{};
    7278    }
    7379
    7480    void thread::join()
    7581    {
    76         // TODO:
     82        if (joinable_wrapper_)
     83        {
     84            printf("JOINING\n");
     85            joinable_wrapper_->join();
     86            printf("JOIN ENDED\n");
     87        }
    7788    }
    7889
     
    8091    {
    8192        id_ = fid_t{};
     93
     94        if (joinable_wrapper_)
     95        {
     96            joinable_wrapper_->detach();
     97            joinable_wrapper_ = nullptr;
     98        }
    8299    }
    83100
Note: See TracChangeset for help on using the changeset viewer.