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

STEllAR-GROUP / hpx / #853

19 Dec 2022 01:01AM UTC coverage: 86.287% (+0.4%) from 85.912%
#853

push

StellarBot
Merge #6109

6109: Modernize serialization module r=hkaiser a=hkaiser

- flyby separate serialization of Boost types

working towards https://github.com/STEllAR-GROUP/hpx/issues/5497

Co-authored-by: Hartmut Kaiser <hartmut.kaiser@gmail.com>

53 of 53 new or added lines in 6 files covered. (100.0%)

173939 of 201582 relevant lines covered (86.29%)

1931657.12 hits per line

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

19.69
/libs/full/runtime_components/tests/unit/components/migrate_polymorphic_component.cpp
1
//  Copyright (c) 2019 Maximilian Bremer
2
//  Copyright (c) 2019 Hartmut Kaiser
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 <cstddef>
20
#include <cstdint>
21
#include <type_traits>
22
#include <utility>
23
#include <vector>
24

25
///////////////////////////////////////////////////////////////////////////////
26
struct test_server_base
27
  : hpx::components::abstract_base_migration_support<
28
        hpx::components::abstract_component_base<test_server_base>>
29
{
30
    test_server_base(int base_data = 0)
330✔
31
      : base_data_(base_data)
330✔
32
    {
660✔
33
    }
330✔
34
    virtual ~test_server_base() = default;
330✔
35

36
    hpx::id_type call() const
551✔
37
    {
38
        return hpx::find_here();
551✔
39
    }
40
    HPX_DEFINE_COMPONENT_ACTION(test_server_base, call, call_action)
41

42
    void busy_work() const
1✔
43
    {
44
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
1✔
45
        hpx::this_thread::sleep_for(std::chrono::seconds(1));
1✔
46
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
1✔
47
    }
1✔
48
    HPX_DEFINE_COMPONENT_ACTION(test_server_base, busy_work, busy_work_action)
49

50
    hpx::future<void> lazy_busy_work() const
×
51
    {
52
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
×
53

54
        auto f = hpx::make_ready_future_after(std::chrono::seconds(1));
×
55

56
        return f.then([this](hpx::future<void>&& f) -> void {
×
57
            HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
×
58
            f.get();
×
59
            HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
×
60
        });
×
61
    }
×
62
    HPX_DEFINE_COMPONENT_ACTION(
63
        test_server_base, lazy_busy_work, lazy_busy_work_action)
64

65
    int get_base_data() const
553✔
66
    {
67
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
553✔
68
        return base_data_;
553✔
69
    }
70
    HPX_DEFINE_COMPONENT_ACTION(
71
        test_server_base, get_base_data, get_base_data_action)
72

73
    hpx::future<int> lazy_get_base_data() const
287✔
74
    {
75
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
287✔
76

77
        auto f = hpx::make_ready_future(base_data_);
287✔
78

79
        return f.then([this](hpx::future<int>&& f) -> int {
574✔
80
            HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
287✔
81
            auto result = f.get();
287✔
82
            HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
287✔
83
            return result;
287✔
84
        });
85
    }
287✔
86
    HPX_DEFINE_COMPONENT_ACTION(
87
        test_server_base, lazy_get_base_data, lazy_get_base_data_action)
88

89
    virtual int get_data() const
×
90
    {
91
        return get_base_data();
×
92
    }
93
    int get_data_nonvirt() const
533✔
94
    {
95
        return get_data();
533✔
96
    }
97
    HPX_DEFINE_COMPONENT_ACTION(
98
        test_server_base, get_data_nonvirt, get_data_action)
99

100
    virtual hpx::future<int> lazy_get_data() const
×
101
    {
102
        return lazy_get_base_data();
×
103
    }
104
    hpx::future<int> lazy_get_data_nonvirt() const
248✔
105
    {
106
        return lazy_get_data();
248✔
107
    }
108
    HPX_DEFINE_COMPONENT_ACTION(
109
        test_server_base, lazy_get_data_nonvirt, lazy_get_data_action)
110

111
    // Components which should be migrated using hpx::migrate<> need to
112
    // be Serializable and CopyConstructable. Components can be
113
    // MoveConstructable in which case the serialized data is moved into the
114
    // component's constructor.
115
    test_server_base(test_server_base&& rhs)
323✔
116
      : base_data_(std::move(rhs.base_data_))
323✔
117
    {
646✔
118
    }
323✔
119

120
    test_server_base& operator=(test_server_base&& rhs)
121
    {
122
        base_data_ = std::move(rhs.base_data_);
123
        return *this;
124
    }
125

126
    template <typename Archive>
127
    void serialize(Archive& ar, unsigned)
1,292✔
128
    {
129
        // clang-format off
130
        ar & base_data_;
1,292✔
131
        // clang-format on
132
    }
1,292✔
133

134
    hpx::naming::address get_current_address() const override
×
135
    {
136
        return hpx::naming::address(
×
137
            hpx::naming::get_gid_from_locality_id(hpx::get_locality_id()),
×
138
            hpx::components::get_component_type<test_server_base>(),
×
139
            const_cast<test_server_base*>(this));
×
140
    }
141

142
private:
143
    int base_data_;
144
};
145

146
HPX_DEFINE_GET_COMPONENT_TYPE(test_server_base)
3,501✔
147

148
typedef test_server_base::call_action call_action;
149
HPX_REGISTER_ACTION_DECLARATION(call_action)
150
HPX_REGISTER_ACTION(call_action)
1,107✔
151

152
typedef test_server_base::busy_work_action busy_work_action;
153
HPX_REGISTER_ACTION_DECLARATION(busy_work_action)
154
HPX_REGISTER_ACTION(busy_work_action)
4✔
155

156
typedef test_server_base::lazy_busy_work_action lazy_busy_work_action;
157
HPX_REGISTER_ACTION_DECLARATION(lazy_busy_work_action)
158
HPX_REGISTER_ACTION(lazy_busy_work_action)
6✔
159

160
typedef test_server_base::get_base_data_action get_base_data_action;
161
HPX_REGISTER_ACTION_DECLARATION(get_base_data_action)
162
HPX_REGISTER_ACTION(get_base_data_action)
1,333✔
163

164
typedef test_server_base::lazy_get_base_data_action lazy_get_base_data_action;
165
HPX_REGISTER_ACTION_DECLARATION(lazy_get_base_data_action)
166
HPX_REGISTER_ACTION(lazy_get_base_data_action)
587✔
167

168
typedef test_server_base::get_data_action get_data_action;
169
HPX_REGISTER_ACTION_DECLARATION(get_data_action)
170
HPX_REGISTER_ACTION(get_data_action)
1,283✔
171

172
typedef test_server_base::lazy_get_data_action lazy_get_data_action;
173
HPX_REGISTER_ACTION_DECLARATION(lazy_get_data_action)
174
HPX_REGISTER_ACTION(lazy_get_data_action)
533✔
175

176
///////////////////////////////////////////////////////////////////////////////
177
struct test_server
653✔
178
  : hpx::components::abstract_migration_support<
179
        hpx::components::component_base<test_server>, test_server_base>
180
{
181
    using base_type = hpx::components::abstract_migration_support<
182
        hpx::components::component_base<test_server>, test_server_base>;
183

184
    test_server(int base_data = 0, int data = 0)
330✔
185
      : base_type(base_data)
330✔
186
      , data_(data)
330✔
187
    {
660✔
188
    }
330✔
189

190
    int get_data() const override
533✔
191
    {
192
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
533✔
193
        return data_;
533✔
194
    }
195

196
    hpx::future<int> lazy_get_data() const override
248✔
197
    {
198
        HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
248✔
199

200
        auto f = hpx::make_ready_future(data_);
248✔
201

202
        return f.then([this](hpx::future<int>&& f) -> int {
496✔
203
            HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
248✔
204
            auto result = f.get();
248✔
205
            HPX_TEST_NEQ(pin_count(), std::uint32_t(0));
248✔
206
            return result;
248✔
207
        });
208
    }
248✔
209

210
    // Components that should be migrated using hpx::migrate<> need to
211
    // be Serializable and CopyConstructable. Components can be
212
    // MoveConstructable in which case the serialized data is moved into the
213
    // component's constructor.
214
    test_server(test_server&& rhs)
323✔
215
      : base_type(std::move(rhs))
323✔
216
      , data_(rhs.data_)
323✔
217
    {
646✔
218
    }
323✔
219

220
    test_server& operator=(test_server&& rhs)
221
    {
222
        this->test_server_base::operator=(
223
            std::move(static_cast<test_server_base&>(rhs)));
224
        data_ = rhs.data_;
225
        return *this;
226
    }
227

228
    template <typename Archive>
229
    void serialize(Archive& ar, unsigned)
1,292✔
230
    {
231
        // clang-format off
232
        ar & hpx::serialization::base_object<test_server_base>(*this);
1,292✔
233
        ar & data_;
1,292✔
234
        // clang-format on
235
    }
1,292✔
236

237
    hpx::naming::address get_current_address() const override
330✔
238
    {
239
        return hpx::naming::address(
330✔
240
            hpx::naming::get_gid_from_locality_id(hpx::get_locality_id()),
330✔
241
            hpx::components::get_component_type<test_server>(),
330✔
242
            const_cast<test_server*>(this));
330✔
243
    }
244

245
private:
246
    int data_;
247
};
248

249
typedef hpx::components::component<test_server> server_type;
250
HPX_REGISTER_DERIVED_COMPONENT_FACTORY(
2,003✔
251
    server_type, test_server, "test_server_base")
252

253
///////////////////////////////////////////////////////////////////////////////
254
struct test_client : hpx::components::client_base<test_client, test_server_base>
×
255
{
256
    using base_type =
257
        hpx::components::client_base<test_client, test_server_base>;
258

259
    test_client() = default;
260
    test_client(hpx::shared_future<hpx::id_type> const& id)
×
261
      : base_type(id)
×
262
    {
×
263
    }
×
264
    test_client(hpx::id_type&& id)
265
      : base_type(std::move(id))
266
    {
267
    }
268

269
    hpx::id_type call() const
×
270
    {
271
        return call_action()(this->get_id());
×
272
    }
273

274
    hpx::future<void> busy_work() const
×
275
    {
276
        return hpx::async<busy_work_action>(this->get_id());
×
277
    }
278

279
    hpx::future<void> lazy_busy_work() const
×
280
    {
281
        return hpx::async<lazy_busy_work_action>(this->get_id());
×
282
    }
283

284
    int get_data() const
×
285
    {
286
        return get_data_action()(this->get_id());
×
287
    }
288

289
    int lazy_get_data() const
×
290
    {
291
        return lazy_get_data_action()(this->get_id()).get();
×
292
    }
×
293

294
    int get_base_data() const
×
295
    {
296
        return get_base_data_action()(this->get_id());
×
297
    }
298

299
    int lazy_get_base_data() const
×
300
    {
301
        return lazy_get_base_data_action()(this->get_id()).get();
×
302
    }
×
303
};
304

305
///////////////////////////////////////////////////////////////////////////////
306
bool test_migrate_polymorphic_component(
×
307
    hpx::id_type source, hpx::id_type target)
308
{
309
    // create component on given locality
310
    test_client t1(hpx::new_<test_server>(source, 7, 42));
×
311
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
312

313
    // the new object should live on the source locality
314
    HPX_TEST_EQ(t1.call(), source);
×
315
    HPX_TEST_EQ(t1.get_data(), 42);
×
316
    HPX_TEST_EQ(t1.get_base_data(), 7);
×
317

318
    try
319
    {
320
        hpx::cout << "Migrating..." << std::endl;
×
321
        // migrate t1 to the target
322
        test_client t2(hpx::components::migrate<test_server>(t1, target));
×
323

324
        // wait for migration to be done
325
        HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
326
        hpx::cout << "...completed migrating..." << std::endl;
×
327

328
        // the migrated object should have the same id as before
329
        HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
330

331
        // the migrated object should live on the target now
332
        HPX_TEST_EQ(t2.call(), target);
×
333
        HPX_TEST_EQ(t2.get_data(), 42);
×
334
        HPX_TEST_EQ(t2.get_base_data(), 7);
×
335

336
        hpx::cout << "...pass all tests!" << std::endl;
×
337
    }
×
338
    catch (hpx::exception const& e)
339
    {
340
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
341
        return false;
×
342
    }
×
343

344
    return true;
×
345
}
×
346

347
///////////////////////////////////////////////////////////////////////////////
348
bool test_migrate_lazy_polymorphic_component(
×
349
    hpx::id_type source, hpx::id_type target)
350
{
351
    // create component on given locality
352
    test_client t1(hpx::new_<test_server>(source, 7, 42));
×
353
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
354

355
    // the new object should live on the source locality
356
    HPX_TEST_EQ(t1.call(), source);
×
357
    HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
358
    HPX_TEST_EQ(t1.lazy_get_base_data(), 7);
×
359

360
    try
361
    {
362
        // migrate t1 to the target
363
        test_client t2(hpx::components::migrate<test_server>(t1, target));
×
364

365
        // wait for migration to be done
366
        HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
367

368
        // the migrated object should have the same id as before
369
        HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
370

371
        // the migrated object should live on the target now
372
        HPX_TEST_EQ(t2.call(), target);
×
373
        HPX_TEST_EQ(t2.lazy_get_data(), 42);
×
374
        HPX_TEST_EQ(t2.lazy_get_base_data(), 7);
×
375
    }
×
376
    catch (hpx::exception const& e)
377
    {
378
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
379
        return false;
×
380
    }
×
381

382
    return true;
×
383
}
×
384

385
///////////////////////////////////////////////////////////////////////////////
386
bool test_migrate_busy_polymorphic_component(
×
387
    hpx::id_type source, hpx::id_type target)
388
{
389
    // create component on given locality
390
    test_client t1(hpx::new_<test_server>(source, 7, 42));
×
391
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
392

393
    // the new object should live on the source locality
394
    HPX_TEST_EQ(t1.call(), source);
×
395
    HPX_TEST_EQ(t1.get_data(), 42);
×
396
    HPX_TEST_EQ(t1.get_base_data(), 7);
×
397

398
    // add some concurrent busy work
399
    hpx::future<void> busy_work = t1.busy_work();
×
400

401
    try
402
    {
403
        // migrate t1 to the target
404
        test_client t2(hpx::components::migrate<test_server>(t1, target));
×
405

406
        HPX_TEST_EQ(t1.get_data(), 42);
×
407
        HPX_TEST_EQ(t1.get_base_data(), 7);
×
408

409
        // wait for migration to be done
410
        HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
411

412
        // the migrated object should have the same id as before
413
        HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
414

415
        // the migrated object should live on the target now
416
        HPX_TEST_EQ(t2.call(), target);
×
417
        HPX_TEST_EQ(t2.get_data(), 42);
×
418
        HPX_TEST_EQ(t2.get_base_data(), 7);
×
419
    }
×
420
    catch (hpx::exception const& e)
421
    {
422
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
423
        return false;
×
424
    }
×
425

426
    // the busy work should be finished by now, wait anyways
427
    busy_work.wait();
×
428

429
    return true;
×
430
}
×
431

432
///////////////////////////////////////////////////////////////////////////////
433
bool test_migrate_lazy_busy_polymorphic_component(
×
434
    hpx::id_type source, hpx::id_type target)
435
{
436
    // create component on given locality
437
    test_client t1(hpx::new_<test_server>(source, 7, 42));
×
438
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
439

440
    // the new object should live on the source locality
441
    HPX_TEST_EQ(t1.call(), source);
×
442
    HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
443
    HPX_TEST_EQ(t1.lazy_get_base_data(), 7);
×
444

445
    // add some concurrent busy work
446
    hpx::future<void> lazy_busy_work = t1.lazy_busy_work();
×
447

448
    try
449
    {
450
        // migrate t1 to the target
451
        test_client t2(hpx::components::migrate<test_server>(t1, target));
×
452

453
        HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
454
        HPX_TEST_EQ(t1.lazy_get_base_data(), 7);
×
455

456
        // wait for migration to be done
457
        HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
458

459
        // the migrated object should have the same id as before
460
        HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
461

462
        // the migrated object should live on the target now
463
        HPX_TEST_EQ(t2.call(), target);
×
464
        HPX_TEST_EQ(t2.lazy_get_data(), 42);
×
465
        HPX_TEST_EQ(t2.lazy_get_base_data(), 7);
×
466
    }
×
467
    catch (hpx::exception const& e)
468
    {
469
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
470
        return false;
×
471
    }
×
472

473
    // the busy work should be finished by now, wait anyways
474
    lazy_busy_work.wait();
×
475

476
    return true;
×
477
}
×
478

479
///////////////////////////////////////////////////////////////////////////////
480
bool test_migrate_polymorphic_component2(
×
481
    hpx::id_type source, hpx::id_type target)
482
{
483
    test_client t1(hpx::new_<test_server>(source, 7, 42));
×
484
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
485

486
    // the new object should live on the source locality
487
    HPX_TEST_EQ(t1.call(), source);
×
488
    HPX_TEST_EQ(t1.get_data(), 42);
×
489
    HPX_TEST_EQ(t1.get_base_data(), 7);
×
490

491
    std::size_t N = 100;
×
492

493
    try
494
    {
495
        // migrate an object back and forth between 2 localities a couple of
496
        // times
497
        for (std::size_t i = 0; i < N; ++i)
×
498
        {
499
            // migrate t1 to the target (loc2)
500
            test_client t2(hpx::components::migrate<test_server>(t1, target));
×
501

502
            HPX_TEST_EQ(t1.get_data(), 42);
×
503
            HPX_TEST_EQ(t1.get_base_data(), 7);
×
504

505
            // wait for migration to be done
506
            HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
507

508
            // the migrated object should have the same id as before
509
            HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
510

511
            // the migrated object should live on the target now
512
            HPX_TEST_EQ(t2.call(), target);
×
513
            HPX_TEST_EQ(t2.get_data(), 42);
×
514
            HPX_TEST_EQ(t2.get_base_data(), 7);
×
515

516
            hpx::cout << "." << std::flush;
×
517

518
            std::swap(source, target);
×
519
        }
×
520

521
        hpx::cout << std::endl;
×
522
    }
×
523
    catch (hpx::exception const& e)
524
    {
525
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
526
        return false;
×
527
    }
×
528

529
    return true;
×
530
}
×
531

532
bool test_migrate_lazy_polymorphic_component2(
×
533
    hpx::id_type source, hpx::id_type target)
534
{
535
    test_client t1(hpx::new_<test_server>(source, 7, 42));
×
536
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
537

538
    // the new object should live on the source locality
539
    HPX_TEST_EQ(t1.call(), source);
×
540
    HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
541
    HPX_TEST_EQ(t1.lazy_get_base_data(), 7);
×
542

543
    std::size_t N = 100;
×
544

545
    try
546
    {
547
        // migrate an object back and forth between 2 localities a couple of
548
        // times
549
        for (std::size_t i = 0; i < N; ++i)
×
550
        {
551
            // migrate t1 to the target (loc2)
552
            test_client t2(hpx::components::migrate<test_server>(t1, target));
×
553

554
            HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
555
            HPX_TEST_EQ(t1.lazy_get_base_data(), 7);
×
556

557
            // wait for migration to be done
558
            HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
559

560
            // the migrated object should have the same id as before
561
            HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
562

563
            // the migrated object should live on the target now
564
            HPX_TEST_EQ(t2.call(), target);
×
565
            HPX_TEST_EQ(t2.lazy_get_data(), 42);
×
566
            HPX_TEST_EQ(t2.lazy_get_base_data(), 7);
×
567

568
            hpx::cout << "." << std::flush;
×
569

570
            std::swap(source, target);
×
571
        }
×
572

573
        hpx::cout << std::endl;
×
574
    }
×
575
    catch (hpx::exception const& e)
576
    {
577
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
578
        return false;
×
579
    }
×
580

581
    return true;
×
582
}
×
583

584
///////////////////////////////////////////////////////////////////////////////
585
bool test_migrate_busy_polymorphic_component2(
×
586
    hpx::id_type source, hpx::id_type target)
587
{
588
    test_client t1(hpx::new_<test_server>(source, 7, 42));
×
589
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
590

591
    // the new object should live on the source locality
592
    HPX_TEST_EQ(t1.call(), source);
×
593
    HPX_TEST_EQ(t1.get_data(), 42);
×
594
    HPX_TEST_EQ(t1.get_base_data(), 7);
×
595

596
    std::size_t N = 100;
×
597

598
    // First, spawn a thread (locally) that will migrate the object between
599
    // source and target a few times
600
    hpx::future<void> migrate_future = hpx::async([source, target, t1,
×
601
                                                      N]() mutable {
×
602
        for (std::size_t i = 0; i < N; ++i)
×
603
        {
604
            // migrate t1 to the target (loc2)
605
            test_client t2(hpx::components::migrate<test_server>(t1, target));
×
606

607
            HPX_TEST_EQ(t1.get_data(), 42);
×
608
            HPX_TEST_EQ(t1.get_base_data(), 7);
×
609

610
            // wait for migration to be done
611
            HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
612

613
            // the migrated object should have the same id as before
614
            HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
615

616
            // the migrated object should live on the target now
617
            HPX_TEST_EQ(t2.call(), target);
×
618
            HPX_TEST_EQ(t2.get_data(), 42);
×
619
            HPX_TEST_EQ(t2.get_base_data(), 7);
×
620

621
            hpx::cout << "." << std::flush;
×
622

623
            std::swap(source, target);
×
624
        }
×
625

626
        hpx::cout << std::endl;
×
627
    });
×
628

629
    // Second, we generate tons of work which should automatically follow
630
    // the migration.
631
    hpx::future<void> create_work = hpx::async([t1, N]() {
×
632
        for (std::size_t i = 0; i < 2 * N; ++i)
×
633
        {
634
            hpx::cout << hpx::naming::get_locality_id_from_id(t1.call())
×
635
                      << std::flush;
×
636
            HPX_TEST_EQ(t1.get_data(), 42);
×
637
            HPX_TEST_EQ(t1.get_base_data(), 7);
×
638
        }
×
639
    });
×
640

641
    hpx::wait_all(migrate_future, create_work);
×
642

643
    // rethrow exceptions
644
    try
645
    {
646
        migrate_future.get();
×
647
        create_work.get();
×
648
    }
×
649
    catch (hpx::exception const& e)
650
    {
651
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
652
        return false;
×
653
    }
×
654

655
    return true;
×
656
}
×
657

658
bool test_migrate_lazy_busy_polymorphic_component2(
×
659
    hpx::id_type source, hpx::id_type target)
660
{
661
    test_client t1(hpx::new_<test_server>(source, 7, 42));
×
662
    HPX_TEST_NEQ(hpx::invalid_id, t1.get_id());
×
663

664
    // the new object should live on the source locality
665
    HPX_TEST_EQ(t1.call(), source);
×
666
    HPX_TEST_EQ(t1.get_data(), 42);
×
667
    HPX_TEST_EQ(t1.get_base_data(), 7);
×
668

669
    std::size_t N = 100;
×
670

671
    // First, spawn a thread (locally) that will migrate the object between
672
    // source and target a few times
673
    hpx::future<void> migrate_future = hpx::async([source, target, t1,
×
674
                                                      N]() mutable {
×
675
        for (std::size_t i = 0; i < N; ++i)
×
676
        {
677
            // migrate t1 to the target (loc2)
678
            test_client t2(hpx::components::migrate<test_server>(t1, target));
×
679

680
            HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
681
            HPX_TEST_EQ(t1.lazy_get_base_data(), 7);
×
682

683
            // wait for migration to be done
684
            HPX_TEST_NEQ(hpx::invalid_id, t2.get_id());
×
685

686
            // the migrated object should have the same id as before
687
            HPX_TEST_EQ(t1.get_id(), t2.get_id());
×
688

689
            // the migrated object should live on the target now
690
            HPX_TEST_EQ(t2.call(), target);
×
691
            HPX_TEST_EQ(t2.lazy_get_data(), 42);
×
692
            HPX_TEST_EQ(t2.lazy_get_base_data(), 7);
×
693

694
            hpx::cout << "." << std::flush;
×
695

696
            std::swap(source, target);
×
697
        }
×
698

699
        hpx::cout << std::endl;
×
700
    });
×
701

702
    // Second, we generate tons of work which should automatically follow
703
    // the migration.
704
    hpx::future<void> create_work = hpx::async([t1, N]() {
×
705
        for (std::size_t i = 0; i < 2 * N; ++i)
×
706
        {
707
            hpx::cout << hpx::naming::get_locality_id_from_id(t1.call())
×
708
                      << std::flush;
×
709
            HPX_TEST_EQ(t1.lazy_get_data(), 42);
×
710
            HPX_TEST_EQ(t1.lazy_get_base_data(), 7);
×
711
        }
×
712
    });
×
713

714
    hpx::wait_all(migrate_future, create_work);
×
715

716
    // rethrow exceptions
717
    try
718
    {
719
        migrate_future.get();
×
720
        create_work.get();
×
721
    }
×
722
    catch (hpx::exception const& e)
723
    {
724
        hpx::cout << hpx::get_error_what(e) << std::endl;
×
725
        return false;
×
726
    }
×
727

728
    return true;
×
729
}
×
730

731
///////////////////////////////////////////////////////////////////////////////
732
int main()
×
733
{
734
    std::vector<hpx::id_type> localities = hpx::find_remote_localities();
×
735

736
    for (hpx::id_type const& id : localities)
×
737
    {
738
        hpx::cout << "test migrate polymorphic component: ->" << id
×
739
                  << std::endl;
×
740
        HPX_TEST(test_migrate_polymorphic_component(hpx::find_here(), id));
×
741
        hpx::cout << "test migrate polymorphic component: <-" << id
×
742
                  << std::endl;
×
743
        HPX_TEST(test_migrate_polymorphic_component(id, hpx::find_here()));
×
744

745
        hpx::cout << "test migrate lazy polymorphic component: ->" << id
×
746
                  << std::endl;
×
747
        HPX_TEST(test_migrate_lazy_polymorphic_component(hpx::find_here(), id));
×
748
        hpx::cout << "test migrate lazy polymorphic component: <-" << id
×
749
                  << std::endl;
×
750
        HPX_TEST(test_migrate_lazy_polymorphic_component(id, hpx::find_here()));
×
751
    }
752

753
    for (hpx::id_type const& id : localities)
×
754
    {
755
        hpx::cout << "test migrate busy polymorphic component: ->" << id
×
756
                  << std::endl;
×
757
        HPX_TEST(test_migrate_busy_polymorphic_component(hpx::find_here(), id));
×
758
        hpx::cout << "test migrate busy polymorphic component: <-" << id
×
759
                  << std::endl;
×
760
        HPX_TEST(test_migrate_busy_polymorphic_component(id, hpx::find_here()));
×
761

762
        hpx::cout << "test migrate lazy busy polymorphic component: ->" << id
×
763
                  << std::endl;
×
764
        HPX_TEST(
×
765
            test_migrate_lazy_busy_polymorphic_component(hpx::find_here(), id));
766
        hpx::cout << "test migrate lazy busy polymorphic component: <-" << id
×
767
                  << std::endl;
×
768
        HPX_TEST(
×
769
            test_migrate_lazy_busy_polymorphic_component(id, hpx::find_here()));
770
    }
771

772
    for (hpx::id_type const& id : localities)
×
773
    {
774
        hpx::cout << "test migrate polymorphic component2: ->" << id
×
775
                  << std::endl;
×
776
        HPX_TEST(test_migrate_polymorphic_component2(hpx::find_here(), id));
×
777
        hpx::cout << "test migrate polymorphic component2: <-" << id
×
778
                  << std::endl;
×
779
        HPX_TEST(test_migrate_polymorphic_component2(id, hpx::find_here()));
×
780

781
        hpx::cout << "test migrate lazy polymorphic component2: ->" << id
×
782
                  << std::endl;
×
783
        HPX_TEST(
×
784
            test_migrate_lazy_polymorphic_component2(hpx::find_here(), id));
785
        hpx::cout << "test migrate lazy polymorphic component2: <-" << id
×
786
                  << std::endl;
×
787
        HPX_TEST(
×
788
            test_migrate_lazy_polymorphic_component2(id, hpx::find_here()));
789
    }
790

791
    for (hpx::id_type const& id : localities)
×
792
    {
793
        hpx::cout << "test migrate busy polymorphic component2: ->" << id
×
794
                  << std::endl;
×
795
        HPX_TEST(
×
796
            test_migrate_busy_polymorphic_component2(hpx::find_here(), id));
797
        hpx::cout << "test migrate busy polymorphic component2: <-" << id
×
798
                  << std::endl;
×
799
        HPX_TEST(
×
800
            test_migrate_busy_polymorphic_component2(id, hpx::find_here()));
801

802
        hpx::cout << "test migrate lazy busy polymorphic component2: ->" << id
×
803
                  << std::endl;
×
804
        HPX_TEST(test_migrate_lazy_busy_polymorphic_component2(
×
805
            hpx::find_here(), id));
806
        hpx::cout << "test migrate lazy busy polymorphic component2: <-" << id
×
807
                  << std::endl;
×
808
        HPX_TEST(test_migrate_lazy_busy_polymorphic_component2(
×
809
            id, hpx::find_here()));
810
    }
811

812
    return hpx::util::report_errors();
×
813
}
×
814
#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