1 //  Copyright (c) 2016 Thomas Heller
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #ifndef HPX_LCOS_DETAIL_BARRIER_NODE_HPP
7 #define HPX_LCOS_DETAIL_BARRIER_NODE_HPP
8 
9 #include <hpx/config.hpp>
10 #include <hpx/lcos/base_lco.hpp>
11 #include <hpx/lcos/future.hpp>
12 #include <hpx/lcos/local/barrier.hpp>
13 #include <hpx/lcos/local/promise.hpp>
14 #include <hpx/lcos/local/spinlock.hpp>
15 #include <hpx/runtime/components/server/managed_component_base.hpp>
16 #include <hpx/runtime/naming/id_type.hpp>
17 #include <hpx/traits/managed_component_policies.hpp>
18 #include <hpx/util/assert.hpp>
19 #include <hpx/util/atomic_count.hpp>
20 
21 #include <cstddef>
22 #include <string>
23 #include <vector>
24 
25 #include <hpx/config/warnings_prefix.hpp>
26 
27 namespace hpx { namespace lcos { namespace detail {
28     struct HPX_EXPORT barrier_node;
29 }}}
30 
31 ///////////////////////////////////////////////////////////////////////////////
32 namespace hpx {
33 namespace traits {
34     template <>
35     struct managed_component_dtor_policy<
36         lcos::detail::barrier_node>
37     {
38         typedef managed_object_is_lifetime_controlled type;
39     };
40 }
41 }
42 
43 namespace hpx { namespace lcos { namespace detail {
44     struct barrier_node : base_lco
45     {
46         typedef components::managed_component<barrier_node> wrapping_type;
47         typedef hpx::lcos::local::spinlock mutex_type;
48 
49         barrier_node();
50         barrier_node(std::string base_name, std::size_t num, std::size_t rank);
51         void set_event();
52         hpx::future<void> gather();
53 
54         hpx::future<void> wait(bool async);
55 
56         HPX_DEFINE_COMPONENT_DIRECT_ACTION(barrier_node, gather);
57 
58     private:
59         hpx::util::atomic_count count_;
60 
61         std::vector<naming::id_type> children_;
62 
63     public:
64         std::string base_name_;
65         std::size_t rank_;
66         std::size_t num_;
67         std::size_t arity_;
68         std::size_t cut_off_;
69     private:
70         hpx::lcos::local::promise<void> gather_promise_;
71         hpx::lcos::local::promise<void> broadcast_promise_;
72         hpx::lcos::local::barrier local_barrier_;
73 
74         template <typename This>
75         hpx::future<void> do_wait(This this_, hpx::future<void> future);
76 
77         template <typename>
78         friend struct components::detail_adl_barrier::init;
79 
set_back_ptrhpx::lcos::detail::barrier_node80         void set_back_ptr(components::managed_component<barrier_node>* bp)
81         {
82             HPX_ASSERT(bp);
83         }
84 
85         // intrusive reference counting
intrusive_ptr_add_ref(barrier_node * p)86         friend void intrusive_ptr_add_ref(barrier_node* p)
87         {
88             ++p->count_;
89         }
90 
91         // intrusive reference counting
intrusive_ptr_release(barrier_node * p)92         friend void intrusive_ptr_release(barrier_node* p)
93         {
94             if (p && --p->count_ == 0)
95             {
96                 delete p;
97             }
98         }
99     };
100 }}}
101 
102 HPX_REGISTER_ACTION_DECLARATION(hpx::lcos::detail::barrier_node::gather_action,
103     barrier_node_gather_action);
104 
105 #include <hpx/config/warnings_suffix.hpp>
106 
107 #endif
108