• 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
/examples/quickstart/fibonacci_await.cpp
1
//  Copyright (c) 2007-2025 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
// This is a purely local version demonstrating the proposed extension to
8
// C++ implementing resumable functions (see N3564,
9
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3564.pdf). The
10
// necessary transformations are performed by hand.
11

12
#include <hpx/chrono.hpp>
13
#include <hpx/functional.hpp>
14
#include <hpx/future.hpp>
15
#include <hpx/init.hpp>
16

17
#include <cstddef>
18
#include <cstdint>
19
#include <exception>
20
#include <iostream>
21
#include <memory>
22
#include <string>
23
#include <utility>
24

25
///////////////////////////////////////////////////////////////////////////////
26
std::uint64_t threshold = 2;
27

28
///////////////////////////////////////////////////////////////////////////////
×
29
HPX_NOINLINE std::uint64_t fibonacci_serial(std::uint64_t n)
30
{
×
31
    if (n < 2)
32
        return n;
×
33
    return fibonacci_serial(n - 1) + fibonacci_serial(n - 2);
34
}
35

36
///////////////////////////////////////////////////////////////////////////////
37
//
38
// hpx::future<std::uint64_t> fibonacci(std::uint64_t) resumable
39
// {
40
//     if (n < 2) return hpx::make_ready_future(n);
41
//     if (n < threshold) return hpx::make_ready_future(fibonacci_serial(n));
42
//
43
//     hpx::future<std::uint64_t> lhs = hpx::async(&fibonacci, n-1);
44
//     hpx::future<std::uint64_t> rhs = fibonacci(n-2);
45
//
46
//     return await lhs + await rhs;
47
// }
48
//
49

50
hpx::future<std::uint64_t> fibonacci(std::uint64_t n);
51

52
struct _fibonacci_frame
53
{
54
    int state_;
55
    hpx::future<std::uint64_t> result_;
56
    hpx::promise<std::uint64_t> result_promise_;
57

×
58
    _fibonacci_frame(std::uint64_t n)
×
59
      : state_(0)
×
60
      , n_(n)
×
61
      , lhs_result_(0)
×
62
      , rhs_result_(0)
63
    {
×
64
    }
65

66
    // local variables
67
    std::uint64_t n_;
68
    hpx::future<std::uint64_t> lhs_;
69
    hpx::future<std::uint64_t> rhs_;
70
    std::uint64_t lhs_result_;
71
    std::uint64_t rhs_result_;
72
};
73

×
74
void _fibonacci(std::shared_ptr<_fibonacci_frame> const& frame_)
75
{
76
    _fibonacci_frame* frame = frame_.get();
×
77
    int state = frame->state_;
78

×
79
    switch (state)
80
    {
×
81
    case 1:
×
82
        goto L1;
×
83
    case 2:
×
84
        goto L2;
85
    default:
86
        std::terminate();
87
    }
×
88

89
    // if (n < 2) return hpx::make_ready_future(n);
×
90
    if (frame->n_ < 2)
91
    {
×
92
        if (state == 0)
93
            // never paused
×
94
            frame->result_ = hpx::make_ready_future(frame->n_);
×
95
        else
96
            frame->result_promise_.set_value(frame->n_);
97
        return;
98
    }
×
99

100
    // if (n < threshold) return hpx::make_ready_future(fibonacci_serial(n));
×
101
    if (frame->n_ < threshold)
102
    {
103
        if (state == 0)
×
104
            // never paused
105
            frame->result_ =
×
106
                hpx::make_ready_future(fibonacci_serial(frame->n_));
×
107
        else
108
            frame->result_promise_.set_value(fibonacci_serial(frame->n_));
109
        return;
110
    }
×
111

112
    // hpx::future<std::uint64_t> lhs = hpx::async(&fibonacci, n-1);
113
    frame->lhs_ = hpx::async(&fibonacci, frame->n_ - 1);
×
114

115
    // hpx::future<std::uint64_t> rhs = fibonacci(n-2);
116
    frame->rhs_ = fibonacci(frame->n_ - 2);
117

×
118
    if (!frame->lhs_.is_ready())
×
119
    {
×
120
        frame->state_ = 1;
×
121
        if (!frame->result_.valid())
×
122
            frame->result_ = frame->result_promise_.get_future();
123
        frame->lhs_.then(hpx::bind(&_fibonacci, frame_));
124
        return;
×
125
    }
×
126

127
L1:
128
    frame->lhs_result_ = frame->lhs_.get();
129

×
130
    if (!frame->rhs_.is_ready())
×
131
    {
×
132
        frame->state_ = 2;
×
133
        if (!frame->result_.valid())
×
134
            frame->result_ = frame->result_promise_.get_future();
135
        frame->rhs_.then(hpx::bind(&_fibonacci, frame_));
136
        return;
×
137
    }
×
138

139
L2:
×
140
    frame->rhs_result_ = frame->rhs_.get();
141

142
    if (state == 0)
×
143
        // never paused
144
        frame->result_ =
145
            hpx::make_ready_future(frame->lhs_result_ + frame->rhs_result_);
×
146
    else
147
        frame->result_promise_.set_value(
148
            frame->lhs_result_ + frame->rhs_result_);
149
    return;
×
150
}
151

152
hpx::future<std::uint64_t> fibonacci(std::uint64_t n)
153
{
154
    std::shared_ptr<_fibonacci_frame> frame =
×
155
        std::make_shared<_fibonacci_frame>(n);
156

×
157
    _fibonacci(frame);
158

159
    return std::move(frame->result_);
160
}
×
161

162
///////////////////////////////////////////////////////////////////////////////
163
int hpx_main(hpx::program_options::variables_map& vm)
×
164
{
×
165
    // extract command line argument, i.e. fib(N)
×
166
    std::uint64_t n = vm["n-value"].as<std::uint64_t>();
167
    std::string test = vm["test"].as<std::string>();
×
168
    std::uint64_t max_runs = vm["n-runs"].as<std::uint64_t>();
169

170
    if (max_runs == 0)
171
    {
172
        std::cerr << "fibonacci_await: wrong command line argument value for "
×
173
                     "option 'n-runs', should not be zero"
174
                  << std::endl;
175
        return hpx::local::finalize();    // Handles HPX shutdown
×
176
    }
×
177

178
    threshold = vm["threshold"].as<unsigned int>();
179
    if (threshold < 2 || threshold > n)
180
    {
181
        std::cerr << "fibonacci_await: wrong command line argument value for "
×
182
                     "option 'threshold', should be in between 2 and n-value"
×
183
                     ", value specified: "
184
                  << threshold << std::endl;
185
        return hpx::local::finalize();    // Handles HPX shutdown
186
    }
×
187

188
    bool executed_one = false;
×
189
    std::uint64_t r = 0;
190

191
    if (test == "all" || test == "0")
192
    {
193
        // Keep track of the time required to execute.
×
194
        std::uint64_t start = hpx::chrono::high_resolution_clock::now();
195

196
        for (std::size_t i = 0; i != max_runs; ++i)
×
197
        {
198
            // serial execution
199
            r = fibonacci_serial(n);
200
        }
×
201

202
        // double d = double(hpx::chrono::high_resolution_clock::now() - start) / 1.e9;
203
        std::uint64_t d = hpx::chrono::high_resolution_clock::now() - start;
×
204
        char const* fmt = "fibonacci_serial({1}) == {2},"
205
                          "elapsed time:,{3},[s]\n";
206
        hpx::util::format_to(std::cout, fmt, n, r, d / max_runs);
207

208
        executed_one = true;
×
209
    }
210

211
    if (test == "all" || test == "1")
212
    {
213
        // Keep track of the time required to execute.
×
214
        std::uint64_t start = hpx::chrono::high_resolution_clock::now();
215

216
        for (std::size_t i = 0; i != max_runs; ++i)
217
        {
×
218
            // Create a future for the whole calculation, execute it locally,
219
            // and wait for it.
220
            r = fibonacci(n).get();
221
        }
×
222

223
        // double d = double(hpx::chrono::high_resolution_clock::now() - start) / 1.e9;
224
        std::uint64_t d = hpx::chrono::high_resolution_clock::now() - start;
×
225
        char const* fmt = "fibonacci_await({1}) == {2},"
226
                          "elapsed time:,{3},[s]\n";
227
        hpx::util::format_to(std::cout, fmt, n, r, d / max_runs);
228

229
        executed_one = true;
×
230
    }
231

232
    if (!executed_one)
233
    {
234
        std::cerr << "fibonacci_await: wrong command line argument value for "
235
                     "option 'tests', should be either 'all' or a number "
236
                     "between zero "
237
                     "and 1, value specified: "
238
                  << test << std::endl;
×
239
    }
240

241
    return hpx::local::finalize();    // Handles HPX shutdown
242
}
×
243

244
///////////////////////////////////////////////////////////////////////////////
245
int main(int argc, char* argv[])
246
{
×
247
    // Configure application-specific options
248
    hpx::program_options::options_description desc_commandline(
249
        "Usage: " HPX_APPLICATION_STRING " [options]");
250

×
251
    using hpx::program_options::value;
×
252
    // clang-format off
253
    desc_commandline.add_options()
×
254
        ("n-value", value<std::uint64_t>()->default_value(10),
255
         "n value for the Fibonacci function")
×
256
        ("n-runs", value<std::uint64_t>()->default_value(1),
257
         "number of runs to perform")
×
258
        ("threshold", value<unsigned int>()->default_value(2),
259
         "threshold for switching to serial code")
260
        ("test", value<std::string>()->default_value("all"),
261
        "select tests to execute (0-1, default: all)");
262
    // clang-format on
×
263

×
264
    // Initialize and run HPX
265
    hpx::local::init_params init_args;
×
266
    init_args.desc_cmdline = desc_commandline;
×
267

268
    return hpx::local::init(hpx_main, argc, argv, init_args);
269
}
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