• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/libs/core/executors/examples/disable_thread_stealing_executor.cpp
1
//  Copyright (c) 2020-2024 Hartmut Kaiser
2
//
3
//  SPDX-License-Identifier: BSL-1.0
4
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
5
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6

7
///////////////////////////////////////////////////////////////////////////////
8
// The purpose of this example is to show how to write an executor disables
9
// thread stealing for the duration of the execution of a parallel algorithm
10
// it is used with.
11

12
#include <hpx/algorithm.hpp>
13
#include <hpx/assert.hpp>
14
#include <hpx/execution.hpp>
15
#include <hpx/init.hpp>
16

17
#include <algorithm>
18
#include <atomic>
19
#include <cstddef>
20
#include <iostream>
21
#include <type_traits>
22
#include <utility>
23
#include <vector>
24

25
namespace executor_example {
26

27
    template <typename BaseExecutor>
28
    class disable_thread_stealing_executor : public BaseExecutor
29
    {
30
    public:
31
        using execution_category = typename BaseExecutor::execution_category;
32
        using executor_parameters_type =
33
            typename BaseExecutor::executor_parameters_type;
34

35
        template <typename Executor>
36
            requires(!std::is_same_v<std::decay_t<Executor>,
37
                disable_thread_stealing_executor>)
38
        explicit disable_thread_stealing_executor(Executor&& exec)
×
39
          : BaseExecutor(std::forward<Executor>(exec))
×
40
        {
41
        }
42

43
        disable_thread_stealing_executor const& context() const noexcept
44
        {
45
            return *this;
46
        }
47

48
        // Add two executor API functions that will be called before the
49
        // parallel algorithm starts executing and after it has finished
50
        // executing.
51
        template <typename Parameters>
52
        friend void tag_invoke(
53
            hpx::execution::experimental::mark_begin_execution_t, Parameters&&,
54
            disable_thread_stealing_executor const& exec)
55
        {
×
56
            auto const pu_mask =
57
                hpx::execution::experimental::get_processing_units_mask(exec);
×
58
            hpx::threads::remove_scheduler_mode(
59
                hpx::threads::policies::scheduler_mode::enable_stealing,
×
60
                pu_mask);
61
        }
62

×
63
        template <typename Parameters>
64
        friend void tag_invoke(
×
65
            hpx::execution::experimental::mark_end_execution_t, Parameters&&,
66
            disable_thread_stealing_executor const& exec)
×
67
        {
68
            auto const pu_mask =
69
                hpx::execution::experimental::get_processing_units_mask(exec);
70
            hpx::threads::add_scheduler_mode(
71
                hpx::threads::policies::scheduler_mode::enable_stealing,
72
                pu_mask);
73
        }
74
    };
75

76
    // support all properties exposed by the wrapped executor
77
    // clang-format off
78
    template <typename Tag, typename BaseExecutor,typename Property,
79
        HPX_CONCEPT_REQUIRES_(
80
            hpx::execution::experimental::is_scheduling_property_v<Tag>
81
        )>
82
    auto tag_invoke(Tag tag,
83
        disable_thread_stealing_executor<BaseExecutor> const& exec,
84
        Property&& prop)
85
        -> decltype(disable_thread_stealing_executor<BaseExecutor>(
86
            std::declval<Tag>()(
87
                std::declval<BaseExecutor>(), std::declval<Property>())))
88
    // clang-format on
89
    {
90
        return disable_thread_stealing_executor<BaseExecutor>(
91
            tag(static_cast<BaseExecutor const&>(exec),
92
                HPX_FORWARD(Property, prop)));
93
    }
94

95
    // clang-format off
96
    template <typename Tag, typename BaseExecutor,
97
        HPX_CONCEPT_REQUIRES_(
98
            hpx::execution::experimental::is_scheduling_property_v<Tag>
99
        )>
100
    // clang-format on
101
    auto tag_invoke(
102
        Tag tag, disable_thread_stealing_executor<BaseExecutor> const& exec)
103
        -> decltype(std::declval<Tag>()(std::declval<BaseExecutor>()))
104
    {
105
        return tag(static_cast<BaseExecutor const&>(exec));
106
    }
107

108
    template <typename BaseExecutor>
109
    auto make_disable_thread_stealing_executor(BaseExecutor&& exec)
110
    {
111
        return disable_thread_stealing_executor<std::decay_t<BaseExecutor>>(
112
            std::forward<BaseExecutor>(exec));
113
    }
114
}    // namespace executor_example
115

116
///////////////////////////////////////////////////////////////////////////////
117
// simple forwarding implementations of executor traits
118
namespace hpx::execution::experimental {
119

120
    template <typename BaseExecutor>
121
    struct is_one_way_executor<
122
        executor_example::disable_thread_stealing_executor<BaseExecutor>>
123
      : is_one_way_executor<std::decay_t<BaseExecutor>>
124
    {
125
    };
126

127
    template <typename BaseExecutor>
128
    struct is_never_blocking_one_way_executor<
129
        executor_example::disable_thread_stealing_executor<BaseExecutor>>
130
      : is_never_blocking_one_way_executor<std::decay_t<BaseExecutor>>
131
    {
132
    };
133

134
    template <typename BaseExecutor>
135
    struct is_two_way_executor<
136
        executor_example::disable_thread_stealing_executor<BaseExecutor>>
137
      : is_two_way_executor<std::decay_t<BaseExecutor>>
138
    {
139
    };
140

141
    template <typename BaseExecutor>
142
    struct is_bulk_one_way_executor<
143
        executor_example::disable_thread_stealing_executor<BaseExecutor>>
144
      : is_bulk_one_way_executor<std::decay_t<BaseExecutor>>
145
    {
146
    };
147

148
    template <typename BaseExecutor>
149
    struct is_bulk_two_way_executor<
×
150
        executor_example::disable_thread_stealing_executor<BaseExecutor>>
151
      : is_bulk_two_way_executor<std::decay_t<BaseExecutor>>
×
152
    {
153
    };
154
}    // namespace hpx::execution::experimental
155

156
int hpx_main()
157
{
158
    std::vector<double> v(1000);
159
    std::iota(v.begin(), v.end(), 0.0);
×
160

161
    // The following for_loop will be executed while thread stealing is disabled
×
162
    auto exec = executor_example::make_disable_thread_stealing_executor(
163
        hpx::execution::par.executor());
164

×
165
    // This may lead to deadlock situations if the main thread executes some of
166
    // the chunks synchronously.
×
167
    auto hint = hpx::execution::experimental::get_hint(exec);
168
    hint.sharing_mode(hpx::threads::thread_sharing_hint::do_not_share_function |
169
        hpx::threads::thread_sharing_hint::do_not_combine_tasks);
170
    auto no_sharing_exec = hpx::execution::experimental::with_hint(exec, hint);
171

172
    hpx::experimental::for_loop(hpx::execution::par.on(no_sharing_exec), 0,
173
        v.size(), [](std::size_t) {});
174

175
    return hpx::local::finalize();
176
}
177

178
int main(int argc, char* argv[])
179
{
180
    return hpx::local::init(hpx_main, argc, argv);
181
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc