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

STEllAR-GROUP / hpx / #864

12 Jan 2023 03:29PM UTC coverage: 86.354% (-0.2%) from 86.533%
#864

push

web-flow
Merge pull request #6133 from STEllAR-GROUP/background_scheduler

Adding abridged static scheduler that supports running background threads only

263 of 263 new or added lines in 4 files covered. (100.0%)

174319 of 201865 relevant lines covered (86.35%)

1939452.8 hits per line

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

15.8
/libs/full/runtime_components/tests/unit/components/migrate_component.cpp
1
//  Copyright (c) 2014-2016 Hartmut Kaiser
2
//  Copyright (c)      2016 Thomas Heller
3
//
4
//  SPDX-License-Identifier: BSL-1.0
5
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
6
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
#include <hpx/config.hpp>
9
#if !defined(HPX_COMPUTE_DEVICE_CODE)
10
#include <hpx/hpx_main.hpp>
11
#include <hpx/include/actions.hpp>
12
#include <hpx/include/components.hpp>
13
#include <hpx/include/lcos.hpp>
14
#include <hpx/include/runtime.hpp>
15
#include <hpx/include/serialization.hpp>
16
#include <hpx/iostream.hpp>
17
#include <hpx/modules/testing.hpp>
18

19
#include <chrono>
20
#include <cstddef>
21
#include <cstdint>
22
#include <utility>
23
#include <vector>
24

25
///////////////////////////////////////////////////////////////////////////////
26
struct dummy_server : hpx::components::component_base<dummy_server>
606✔
27
{
28
    dummy_server() = default;
606✔
29

30
    hpx::id_type call() const
606✔
31
    {
32
        return hpx::find_here();
606✔
33
    }
34

35
    HPX_DEFINE_COMPONENT_ACTION(dummy_server, call)
36
};
37

38
typedef hpx::components::component<dummy_server> dummy_server_type;
39
HPX_REGISTER_COMPONENT(dummy_server_type, dummy_server)
4,163✔
40

41
typedef dummy_server::call_action dummy_action;
42
HPX_REGISTER_ACTION(dummy_action)
609✔
43

44
struct dummy_client : hpx::components::client_base<dummy_client, dummy_server>
2,530✔
45
{
46
    typedef hpx::components::client_base<dummy_client, dummy_server> base_type;
47

48
    dummy_client() = default;
×
49

50
    dummy_client(hpx::id_type const& id)
51
      : base_type(id)
52
    {
53
    }
54
    dummy_client(hpx::future<hpx::id_type>&& id)
1,518✔
55
      : base_type(std::move(id))
1,518✔
56
    {
1,518✔
57
    }
1,518✔
58

59
    hpx::id_type call() const
×
60
    {
61
        return hpx::async<dummy_action>(this->get_id()).get();
×
62
    }
×
63
};
64

65
///////////////////////////////////////////////////////////////////////////////
66
struct test_server
67
  : hpx::components::migration_support<
68
        hpx::components::component_base<test_server>>
69
{
70
    typedef hpx::components::migration_support<
71
        hpx::components::component_base<test_server>>
72
        base_type;
73

74
    test_server(int data = 0)
618✔
75
      : data_(data)
618✔
76
    {
618✔
77
    }
618✔
78
    ~test_server() {}
618✔
79

80
    hpx::id_type call() const
1,160✔
81
    {
82
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
1,160✔
83
        return hpx::find_here();
1,160✔
84
    }
85

86
    void busy_work() const
1✔
87
    {
88
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
1✔
89
        hpx::this_thread::sleep_for(std::chrono::seconds(1));
1✔
90
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
1✔
91
    }
1✔
92

93
    hpx::future<void> lazy_busy_work() const
2✔
94
    {
95
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
2✔
96

97
        auto f = hpx::make_ready_future_after(std::chrono::seconds(1));
2✔
98

99
        return f.then([this](hpx::future<void>&& f) -> void {
4✔
100
            HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
2✔
101
            f.get();
2✔
102
            HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
2✔
103
        });
2✔
104
    }
2✔
105

106
    int get_data() const
508✔
107
    {
108
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
508✔
109
        return data_;
508✔
110
    }
111

112
    hpx::future<int> lazy_get_data() const
606✔
113
    {
114
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
606✔
115

116
        auto f = hpx::make_ready_future(data_);
606✔
117

118
        return f.then([this](hpx::future<int>&& f) -> int {
1,212✔
119
            HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
606✔
120
            auto result = f.get();
606✔
121
            HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
606✔
122
            return result;
606✔
123
        });
124
    }
606✔
125

126
    dummy_client lazy_get_client(hpx::id_type there) const
506✔
127
    {
128
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
506✔
129

130
        auto f = dummy_client(hpx::new_<dummy_server>(there));
506✔
131

132
        return f.then([this](dummy_client&& f) -> hpx::id_type {
1,012✔
133
            HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
506✔
134
            auto result = f.get();
506✔
135
            HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
506✔
136
            return result;
506✔
137
        });
506✔
138
    }
506✔
139

140
    // Components which should be migrated using hpx::migrate<> need to
141
    // be Serializable and CopyConstructable. Components can be
142
    // MoveConstructable in which case the serialized data is moved into the
143
    // component's constructor.
144
    test_server(test_server const& rhs)
145
      : base_type(rhs)
146
      , data_(rhs.data_)
147
    {
148
    }
149

150
    test_server(test_server&& rhs)
606✔
151
      : base_type(std::move(rhs))
606✔
152
      , data_(rhs.data_)
606✔
153
    {
606✔
154
    }
606✔
155

156
    test_server& operator=(test_server const& rhs)
157
    {
158
        data_ = rhs.data_;
159
        return *this;
160
    }
161
    test_server& operator=(test_server&& rhs)
162
    {
163
        data_ = rhs.data_;
164
        return *this;
165
    }
166

167
    HPX_DEFINE_COMPONENT_ACTION(test_server, call, call_action)
168
    HPX_DEFINE_COMPONENT_ACTION(test_server, busy_work, busy_work_action)
169
    HPX_DEFINE_COMPONENT_ACTION(
170
        test_server, lazy_busy_work, lazy_busy_work_action)
171

172
    HPX_DEFINE_COMPONENT_ACTION(test_server, get_data, get_data_action)
173
    HPX_DEFINE_COMPONENT_ACTION(
174
        test_server, lazy_get_data, lazy_get_data_action)
175
    HPX_DEFINE_COMPONENT_ACTION(
176
        test_server, lazy_get_client, lazy_get_client_action)
177

178
    template <typename Archive>
179
    void serialize(Archive& ar, unsigned)
2,424✔
180
    {
181
        // clang-format off
182
        ar & data_;
2,424✔
183
        // clang-format on
184
    }
2,424✔
185

186
private:
187
    int data_;
188
};
189

190
typedef hpx::components::component<test_server> server_type;
191
HPX_REGISTER_COMPONENT(server_type, test_server)
11,588✔
192

193
typedef test_server::call_action call_action;
194
HPX_REGISTER_ACTION_DECLARATION(call_action)
195
HPX_REGISTER_ACTION(call_action)
2,510✔
196

197
typedef test_server::busy_work_action busy_work_action;
198
HPX_REGISTER_ACTION_DECLARATION(busy_work_action)
199
HPX_REGISTER_ACTION(busy_work_action)
4✔
200

201
typedef test_server::lazy_busy_work_action lazy_busy_work_action;
202
HPX_REGISTER_ACTION_DECLARATION(lazy_busy_work_action)
203
HPX_REGISTER_ACTION(lazy_busy_work_action)
5✔
204

205
typedef test_server::get_data_action get_data_action;
206
HPX_REGISTER_ACTION_DECLARATION(get_data_action)
207
HPX_REGISTER_ACTION(get_data_action)
1,318✔
208

209
typedef test_server::lazy_get_data_action lazy_get_data_action;
210
HPX_REGISTER_ACTION_DECLARATION(lazy_get_data_action)
211
HPX_REGISTER_ACTION(lazy_get_data_action)
1,516✔
212

213
typedef test_server::lazy_get_client_action lazy_get_client_action;
214
HPX_REGISTER_ACTION_DECLARATION(lazy_get_client_action)
215
HPX_REGISTER_ACTION(lazy_get_client_action)
1,318✔
216

217
struct test_client : hpx::components::client_base<test_client, test_server>
×
218
{
219
    typedef hpx::components::client_base<test_client, test_server> base_type;
220

221
    test_client() {}
222
    test_client(hpx::shared_future<hpx::id_type> const& id)
×
223
      : base_type(id)
×
224
    {
×
225
    }
×
226
    test_client(hpx::id_type&& id)
×
227
      : base_type(std::move(id))
×
228
    {
×
229
    }
×
230

231
    hpx::id_type call() const
×
232
    {
233
        return call_action()(this->get_id());
×
234
    }
235

236
    hpx::future<void> busy_work() const
×
237
    {
238
        return hpx::async<busy_work_action>(this->get_id());
×
239
    }
240

241
    hpx::future<void> lazy_busy_work() const
×
242
    {
243
        return hpx::async<lazy_busy_work_action>(this->get_id());
×
244
    }
245

246
    int get_data() const
×
247
    {
248
        return get_data_action()(this->get_id());
×
249
    }
250

251
    int lazy_get_data() const
×
252
    {
253
        return lazy_get_data_action()(this->get_id()).get();
×
254
    }
×
255

256
    dummy_client lazy_get_client(hpx::id_type there) const
×
257
    {
258
        return lazy_get_client_action()(this->get_id(), there);
×
259
    }
260
};
261

262
///////////////////////////////////////////////////////////////////////////////
263
bool test_migrate_component(hpx::id_type source, hpx::id_type target)
×
264
{
265
    // create component on given locality
266
    test_client t1 = hpx::new_<test_client>(source, 42);
×
267
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
268

269
    // the new object should live on the source locality
270
    HPX_TEST_EQ(t1.call(), source);
×
271
    HPX_TEST_EQ(t1.get_data(), 42);
×
272

273
    try
274
    {
275
        // migrate t1 to the target
276
        test_client t2(hpx::components::migrate(t1, target));
×
277

278
        // wait for migration to be done
279
        HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
280

281
        // the migrated object should have the same id as before
282
        HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
283

284
        // the migrated object should live on the target now
285
        HPX_TEST_EQ(t2.call(), target);
×
286
        HPX_TEST_EQ(t2.get_data(), 42);
×
287
    }
×
288
    catch (hpx::exception const& e)
289
    {
290
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
291
        return false;
×
292
    }
×
293

294
    return true;
×
295
}
×
296

297
bool test_migrate_lazy_component(hpx::id_type source, hpx::id_type target)
×
298
{
299
    // create component on given locality
300
    test_client t1 = hpx::new_<test_client>(source, 42);
×
301
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
302

303
    // the new object should live on the source locality
304
    HPX_TEST_EQ(t1.call(), source);
×
305
    HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
306

307
    try
308
    {
309
        // migrate t1 to the target
310
        test_client t2(hpx::components::migrate(t1, target));
×
311

312
        // wait for migration to be done
313
        HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
314

315
        // the migrated object should have the same id as before
316
        HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
317

318
        // the migrated object should live on the target now
319
        HPX_TEST_EQ(t2.call(), target);
×
320
        HPX_TEST_EQ(t2.lazy_get_data(), 42);
×
321
    }
×
322
    catch (hpx::exception const& e)
323
    {
324
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
325
        return false;
×
326
    }
×
327

328
    return true;
×
329
}
×
330

331
bool test_migrate_lazy_component_client(
×
332
    hpx::id_type source, hpx::id_type target)
333
{
334
    // create component on given locality
335
    test_client t1 = hpx::new_<test_client>(source, 42);
×
336
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
337

338
    // the new object should live on the source locality
339
    HPX_TEST_EQ(t1.call(), source);
×
340
    HPX_TEST_EQ(t1.lazy_get_client(target).call(), target);
×
341

342
    try
343
    {
344
        // migrate t1 to the target
345
        test_client t2(hpx::components::migrate(t1, target));
×
346

347
        // wait for migration to be done
348
        HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
349

350
        // the migrated object should have the same id as before
351
        HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
352

353
        // the migrated object should live on the target now
354
        HPX_TEST_EQ(t2.call(), target);
×
355
        HPX_TEST_EQ(t2.lazy_get_client(source).call(), source);
×
356
    }
×
357
    catch (hpx::exception const& e)
358
    {
359
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
360
        return false;
×
361
    }
×
362

363
    return true;
×
364
}
×
365

366
///////////////////////////////////////////////////////////////////////////////
367
bool test_migrate_busy_component(hpx::id_type source, hpx::id_type target)
×
368
{
369
    // create component on given locality
370
    test_client t1 = hpx::new_<test_client>(source, 42);
×
371
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
372

373
    // the new object should live on the source locality
374
    HPX_TEST_EQ(t1.call(), source);
×
375
    HPX_TEST_EQ(t1.get_data(), 42);
×
376

377
    // add some concurrent busy work
378
    hpx::future<void> busy_work = t1.busy_work();
×
379

380
    try
381
    {
382
        // migrate t1 to the target
383
        test_client t2(hpx::components::migrate(t1, target));
×
384

385
        HPX_TEST_EQ(t1.get_data(), 42);
×
386

387
        // wait for migration to be done
388
        HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
389

390
        // the migrated object should have the same id as before
391
        HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
392

393
        // the migrated object should live on the target now
394
        HPX_TEST_EQ(t2.call(), target);
×
395
        HPX_TEST_EQ(t2.get_data(), 42);
×
396
    }
×
397
    catch (hpx::exception const& e)
398
    {
399
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
400
        return false;
×
401
    }
×
402

403
    // the busy work should be finished by now, wait anyways
404
    busy_work.wait();
×
405

406
    return true;
×
407
}
×
408

409
///////////////////////////////////////////////////////////////////////////////
410
bool test_migrate_lazy_busy_component(hpx::id_type source, hpx::id_type target)
×
411
{
412
    // create component on given locality
413
    test_client t1 = hpx::new_<test_client>(source, 42);
×
414
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
415

416
    // the new object should live on the source locality
417
    HPX_TEST_EQ(t1.call(), source);
×
418
    HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
419

420
    // add some concurrent busy work
421
    hpx::future<void> lazy_busy_work = t1.lazy_busy_work();
×
422

423
    try
424
    {
425
        // migrate t1 to the target
426
        test_client t2(hpx::components::migrate(t1, target));
×
427

428
        HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
429

430
        // wait for migration to be done
431
        HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
432

433
        // the migrated object should have the same id as before
434
        HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
435

436
        // the migrated object should live on the target now
437
        HPX_TEST_EQ(t2.call(), target);
×
438
        HPX_TEST_EQ(t2.lazy_get_data(), 42);
×
439
    }
×
440
    catch (hpx::exception const& e)
441
    {
442
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
443
        return false;
×
444
    }
×
445

446
    // the busy work should be finished by now, wait anyways
447
    lazy_busy_work.wait();
×
448

449
    return true;
×
450
}
×
451

452
bool test_migrate_lazy_busy_component_client(
×
453
    hpx::id_type source, hpx::id_type target)
454
{
455
    // create component on given locality
456
    test_client t1 = hpx::new_<test_client>(source, 42);
×
457
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
458

459
    // the new object should live on the source locality
460
    HPX_TEST_EQ(t1.call(), source);
×
461
    HPX_TEST_EQ(t1.lazy_get_client(target).call(), target);
×
462

463
    // add some concurrent busy work
464
    hpx::future<void> lazy_busy_work = t1.lazy_busy_work();
×
465

466
    try
467
    {
468
        // migrate t1 to the target
469
        test_client t2(hpx::components::migrate(t1, target));
×
470

471
        HPX_TEST_EQ(t1.lazy_get_client(target).call(), target);
×
472

473
        // wait for migration to be done
474
        HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
475

476
        // the migrated object should have the same id as before
477
        HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
478

479
        // the migrated object should live on the target now
480
        HPX_TEST_EQ(t2.call(), target);
×
481
        HPX_TEST_EQ(t2.lazy_get_client(source).call(), source);
×
482
    }
×
483
    catch (hpx::exception const& e)
484
    {
485
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
486
        return false;
×
487
    }
×
488

489
    // the busy work should be finished by now, wait anyways
490
    lazy_busy_work.wait();
×
491

492
    return true;
×
493
}
×
494

495
////////////////////////////////////////////////////////////////////////////////
496
bool test_migrate_component2(hpx::id_type source, hpx::id_type target)
×
497
{
498
    test_client t1 = hpx::new_<test_client>(source, 42);
×
499
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
500

501
    // the new object should live on the source locality
502
    HPX_TEST_EQ(t1.call(), source);
×
503
    HPX_TEST_EQ(t1.get_data(), 42);
×
504

505
    std::size_t N = 100;
×
506

507
    try
508
    {
509
        // migrate an object back and forth between 2 localities a couple of
510
        // times
511
        for (std::size_t i = 0; i < N; ++i)
×
512
        {
513
            // migrate t1 to the target (loc2)
514
            test_client t2(hpx::components::migrate(t1, target));
×
515

516
            HPX_TEST_EQ(t1.get_data(), 42);
×
517

518
            // wait for migration to be done
519
            HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
520

521
            // the migrated object should have the same id as before
522
            HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
523

524
            // the migrated object should live on the target now
525
            HPX_TEST_EQ(t2.call(), target);
×
526
            HPX_TEST_EQ(t2.get_data(), 42);
×
527

528
            hpx::cout << "." << std::flush;
×
529

530
            std::swap(source, target);
×
531
        }
×
532

533
        hpx::cout << std::endl;
×
534
    }
×
535
    catch (hpx::exception const& e)
536
    {
537
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
538
        return false;
×
539
    }
×
540

541
    return true;
×
542
}
×
543

544
bool test_migrate_lazy_component2(hpx::id_type source, hpx::id_type target)
×
545
{
546
    test_client t1 = hpx::new_<test_client>(source, 42);
×
547
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
548

549
    // the new object should live on the source locality
550
    HPX_TEST_EQ(t1.call(), source);
×
551
    HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
552

553
    std::size_t N = 100;
×
554

555
    try
556
    {
557
        // migrate an object back and forth between 2 localities a couple of
558
        // times
559
        for (std::size_t i = 0; i < N; ++i)
×
560
        {
561
            // migrate t1 to the target (loc2)
562
            test_client t2(hpx::components::migrate(t1, target));
×
563

564
            HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
565

566
            // wait for migration to be done
567
            HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
568

569
            // the migrated object should have the same id as before
570
            HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
571

572
            // the migrated object should live on the target now
573
            HPX_TEST_EQ(t2.call(), target);
×
574
            HPX_TEST_EQ(t2.lazy_get_data(), 42);
×
575

576
            hpx::cout << "." << std::flush;
×
577

578
            std::swap(source, target);
×
579
        }
×
580

581
        hpx::cout << std::endl;
×
582
    }
×
583
    catch (hpx::exception const& e)
584
    {
585
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
586
        return false;
×
587
    }
×
588

589
    return true;
×
590
}
×
591

592
bool test_migrate_lazy_component_client2(
×
593
    hpx::id_type source, hpx::id_type target)
594
{
595
    test_client t1 = hpx::new_<test_client>(source, 42);
×
596
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
597

598
    // the new object should live on the source locality
599
    HPX_TEST_EQ(t1.call(), source);
×
600
    HPX_TEST_EQ(t1.lazy_get_client(target).call(), target);
×
601

602
    std::size_t N = 100;
×
603

604
    try
605
    {
606
        // migrate an object back and forth between 2 localities a couple of
607
        // times
608
        for (std::size_t i = 0; i < N; ++i)
×
609
        {
610
            // migrate t1 to the target (loc2)
611
            test_client t2(hpx::components::migrate(t1, target));
×
612

613
            HPX_TEST_EQ(t1.lazy_get_client(target).call(), target);
×
614

615
            // wait for migration to be done
616
            HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
617

618
            // the migrated object should have the same id as before
619
            HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
620

621
            // the migrated object should live on the target now
622
            HPX_TEST_EQ(t2.call(), target);
×
623
            HPX_TEST_EQ(t2.lazy_get_data(), 42);
×
624
            HPX_TEST_EQ(t2.lazy_get_client(source).call(), source);
×
625

626
            hpx::cout << "." << std::flush;
×
627

628
            std::swap(source, target);
×
629
        }
×
630

631
        hpx::cout << std::endl;
×
632
    }
×
633
    catch (hpx::exception const& e)
634
    {
635
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
636
        return false;
×
637
    }
×
638

639
    return true;
×
640
}
×
641

642
bool test_migrate_busy_component2(hpx::id_type source, hpx::id_type target)
×
643
{
644
    test_client t1 = hpx::new_<test_client>(source, 42);
×
645
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
646

647
    // the new object should live on the source locality
648
    HPX_TEST_EQ(t1.call(), source);
×
649
    HPX_TEST_EQ(t1.get_data(), 42);
×
650

651
    std::size_t N = 100;
×
652

653
    // First, spawn a thread (locally) that will migrate the object between
654
    // source and target a few times
655
    hpx::future<void> migrate_future =
656
        hpx::async([source, target, t1, N]() mutable {
×
657
            for (std::size_t i = 0; i < N; ++i)
×
658
            {
659
                // migrate t1 to the target (loc2)
660
                test_client t2(hpx::components::migrate(t1, target));
×
661

662
                HPX_TEST_EQ(t1.get_data(), 42);
×
663

664
                // wait for migration to be done
665
                HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
666

667
                // the migrated object should have the same id as before
668
                HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
669

670
                // the migrated object should live on the target now
671
                HPX_TEST_EQ(t2.call(), target);
×
672
                HPX_TEST_EQ(t2.get_data(), 42);
×
673

674
                hpx::cout << "." << std::flush;
×
675

676
                std::swap(source, target);
×
677
            }
×
678

679
            hpx::cout << std::endl;
×
680
        });
×
681

682
    // Second, we generate tons of work which should automatically follow
683
    // the migration.
684
    hpx::future<void> create_work = hpx::async([t1, N]() {
×
685
        for (std::size_t i = 0; i < 2 * N; ++i)
×
686
        {
687
            hpx::cout << hpx::naming::get_locality_id_from_id(t1.call())
×
688
                      << std::flush;
×
689
            HPX_TEST_EQ(t1.get_data(), 42);
×
690
        }
×
691
    });
×
692

693
    hpx::wait_all(migrate_future, create_work);
×
694

695
    // rethrow exceptions
696
    try
697
    {
698
        migrate_future.get();
×
699
        create_work.get();
×
700
    }
×
701
    catch (hpx::exception const& e)
702
    {
703
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
704
        return false;
×
705
    }
×
706

707
    hpx::cout << std::endl;
×
708

709
    return true;
×
710
}
×
711

712
bool test_migrate_lazy_busy_component2(hpx::id_type source, hpx::id_type target)
×
713
{
714
    test_client t1 = hpx::new_<test_client>(source, 42);
×
715
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
716

717
    // the new object should live on the source locality
718
    HPX_TEST_EQ(t1.call(), source);
×
719
    HPX_TEST_EQ(t1.get_data(), 42);
×
720

721
    std::size_t N = 100;
×
722

723
    // First, spawn a thread (locally) that will migrate the object between
724
    // source and target a few times
725
    hpx::future<void> migrate_future =
726
        hpx::async([source, target, t1, N]() mutable {
×
727
            for (std::size_t i = 0; i < N; ++i)
×
728
            {
729
                // migrate t1 to the target (loc2)
730
                test_client t2(hpx::components::migrate(t1, target));
×
731

732
                HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
733

734
                // wait for migration to be done
735
                HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
736

737
                // the migrated object should have the same id as before
738
                HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
739

740
                // the migrated object should live on the target now
741
                HPX_TEST_EQ(t2.call(), target);
×
742
                HPX_TEST_EQ(t2.lazy_get_data(), 42);
×
743

744
                hpx::cout << "." << std::flush;
×
745

746
                std::swap(source, target);
×
747
            }
×
748

749
            hpx::cout << std::endl;
×
750
        });
×
751

752
    // Second, we generate tons of work which should automatically follow
753
    // the migration.
754
    hpx::future<void> create_work = hpx::async([t1, N]() {
×
755
        for (std::size_t i = 0; i < 2 * N; ++i)
×
756
        {
757
            hpx::cout << hpx::naming::get_locality_id_from_id(t1.call())
×
758
                      << std::flush;
×
759
            HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
760
        }
×
761
    });
×
762

763
    hpx::wait_all(migrate_future, create_work);
×
764

765
    // rethrow exceptions
766
    try
767
    {
768
        migrate_future.get();
×
769
        create_work.get();
×
770
    }
×
771
    catch (hpx::exception const& e)
772
    {
773
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
774
        return false;
×
775
    }
×
776

777
    hpx::cout << std::endl;
×
778

779
    return true;
×
780
}
×
781

782
bool test_migrate_lazy_busy_component_client2(
×
783
    hpx::id_type source, hpx::id_type target)
784
{
785
    test_client t1 = hpx::new_<test_client>(source, 42);
×
786
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
787

788
    // the new object should live on the source locality
789
    HPX_TEST_EQ(t1.call(), source);
×
790
    HPX_TEST_EQ(t1.get_data(), 42);
×
791

792
    std::size_t N = 100;
×
793

794
    // First, spawn a thread (locally) that will migrate the object between
795
    // source and target a few times
796
    hpx::future<void> migrate_future =
797
        hpx::async([source, target, t1, N]() mutable {
×
798
            for (std::size_t i = 0; i < N; ++i)
×
799
            {
800
                // migrate t1 to the target (loc2)
801
                test_client t2(hpx::components::migrate(t1, target));
×
802

803
                HPX_TEST_EQ(t1.lazy_get_client(target).call(), target);
×
804

805
                // wait for migration to be done
806
                HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
807

808
                // the migrated object should have the same id as before
809
                HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
810

811
                // the migrated object should live on the target now
812
                HPX_TEST_EQ(t2.call(), target);
×
813
                HPX_TEST_EQ(t2.lazy_get_client(source).call(), source);
×
814

815
                hpx::cout << "." << std::flush;
×
816

817
                std::swap(source, target);
×
818
            }
×
819

820
            hpx::cout << std::endl;
×
821
        });
×
822

823
    // Second, we generate tons of work which should automatically follow
824
    // the migration.
825
    hpx::future<void> create_work = hpx::async([t1, N, target]() {
×
826
        for (std::size_t i = 0; i < 2 * N; ++i)
×
827
        {
828
            hpx::cout << hpx::naming::get_locality_id_from_id(t1.call())
×
829
                      << std::flush;
×
830
            HPX_TEST_EQ(t1.lazy_get_client(target).call(), target);
×
831
        }
×
832
    });
×
833

834
    hpx::wait_all(migrate_future, create_work);
×
835

836
    // rethrow exceptions
837
    try
838
    {
839
        migrate_future.get();
×
840
        create_work.get();
×
841
    }
×
842
    catch (hpx::exception const& e)
843
    {
844
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
845
        return false;
×
846
    }
×
847

848
    hpx::cout << std::endl;
×
849

850
    return true;
×
851
}
×
852

853
///////////////////////////////////////////////////////////////////////////////
854
int main()
×
855
{
856
    std::vector<hpx::id_type> localities = hpx::find_all_localities();
×
857

858
    for (hpx::id_type const& id : localities)
×
859
    {
860
        hpx::cout << "test_migrate_component: ->" << id << std::endl;
×
861
        HPX_TEST(test_migrate_component(hpx::find_here(), id));
×
862
        hpx::cout << "test_migrate_component: <-" << id << std::endl;
×
863
        HPX_TEST(test_migrate_component(id, hpx::find_here()));
×
864

865
        hpx::cout << "test_migrate_lazy_component: ->" << id << std::endl;
×
866
        HPX_TEST(test_migrate_lazy_component(hpx::find_here(), id));
×
867
        hpx::cout << "test_migrate_lazy_component: <-" << id << std::endl;
×
868
        HPX_TEST(test_migrate_lazy_component(id, hpx::find_here()));
×
869

870
        hpx::cout << "test_migrate_lazy_component_client: ->" << id
×
871
                  << std::endl;
×
872
        HPX_TEST(test_migrate_lazy_component_client(hpx::find_here(), id));
×
873
        hpx::cout << "test_migrate_lazy_component_client: <-" << id
×
874
                  << std::endl;
×
875
        HPX_TEST(test_migrate_lazy_component_client(id, hpx::find_here()));
×
876
    }
877

878
    for (hpx::id_type const& id : localities)
×
879
    {
880
        hpx::cout << "test_migrate_busy_component: ->" << id << std::endl;
×
881
        HPX_TEST(test_migrate_busy_component(hpx::find_here(), id));
×
882
        hpx::cout << "test_migrate_busy_component: <-" << id << std::endl;
×
883
        HPX_TEST(test_migrate_busy_component(id, hpx::find_here()));
×
884

885
        hpx::cout << "test_migrate_lazy_busy_component: ->" << id << std::endl;
×
886
        HPX_TEST(test_migrate_lazy_busy_component(hpx::find_here(), id));
×
887
        hpx::cout << "test_migrate_lazy_busy_component: <-" << id << std::endl;
×
888
        HPX_TEST(test_migrate_lazy_busy_component(id, hpx::find_here()));
×
889

890
        hpx::cout << "test_migrate_lazy_busy_component_client: ->" << id
×
891
                  << std::endl;
×
892
        HPX_TEST(test_migrate_lazy_busy_component_client(hpx::find_here(), id));
×
893
        hpx::cout << "test_migrate_lazy_busy_component_client: <-" << id
×
894
                  << std::endl;
×
895
        HPX_TEST(test_migrate_lazy_busy_component_client(id, hpx::find_here()));
×
896
    }
897

898
    for (hpx::id_type const& id : localities)
×
899
    {
900
        hpx::cout << "test_migrate_component2: ->" << id << std::endl;
×
901
        HPX_TEST(test_migrate_component2(hpx::find_here(), id));
×
902
        hpx::cout << "test_migrate_component2: <-" << id << std::endl;
×
903
        HPX_TEST(test_migrate_component2(id, hpx::find_here()));
×
904

905
        hpx::cout << "test_migrate_lazy_component2: ->" << id << std::endl;
×
906
        HPX_TEST(test_migrate_lazy_component2(hpx::find_here(), id));
×
907
        hpx::cout << "test_migrate_lazy_component2: <-" << id << std::endl;
×
908
        HPX_TEST(test_migrate_lazy_component2(id, hpx::find_here()));
×
909

910
        hpx::cout << "test_migrate_lazy_component_client2: ->" << id
×
911
                  << std::endl;
×
912
        HPX_TEST(test_migrate_lazy_component_client2(hpx::find_here(), id));
×
913
        hpx::cout << "test_migrate_lazy_component_client2: <-" << id
×
914
                  << std::endl;
×
915
        HPX_TEST(test_migrate_lazy_component_client2(id, hpx::find_here()));
×
916
    }
917

918
    for (hpx::id_type const& id : localities)
×
919
    {
920
        hpx::cout << "test_migrate_busy_component2: ->" << id << std::endl;
×
921
        HPX_TEST(test_migrate_busy_component2(hpx::find_here(), id));
×
922
        hpx::cout << "test_migrate_busy_component2: <-" << id << std::endl;
×
923
        HPX_TEST(test_migrate_busy_component2(id, hpx::find_here()));
×
924

925
        hpx::cout << "test_migrate_lazy_busy_component2: ->" << id << std::endl;
×
926
        HPX_TEST(test_migrate_lazy_busy_component2(hpx::find_here(), id));
×
927
        hpx::cout << "test_migrate_lazy_busy_component2: <-" << id << std::endl;
×
928
        HPX_TEST(test_migrate_lazy_busy_component2(id, hpx::find_here()));
×
929

930
        hpx::cout << "test_migrate_lazy_busy_component_client2: ->" << id
×
931
                  << std::endl;
×
932
        HPX_TEST(
×
933
            test_migrate_lazy_busy_component_client2(hpx::find_here(), id));
934
        hpx::cout << "test_migrate_lazy_busy_component_client2: <-" << id
×
935
                  << std::endl;
×
936
        HPX_TEST(
×
937
            test_migrate_lazy_busy_component_client2(id, hpx::find_here()));
938
    }
939

940
    return hpx::util::report_errors();
×
941
}
×
942
#endif
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