// Copyright Microsoft and Project Verona Contributors. // SPDX-License-Identifier: MIT namespace noticeboard_weak { struct C : public V { public: int x = 0; C(int x_) : x(x_) {} }; struct Writer : public VCown { public: Noticeboard box_0; Noticeboard box_1; Writer(Object* c_0, Object* c_1) : box_0{c_0}, box_1{c_1} { #ifdef USE_SYSTEMATIC_TESTING_WEAK_NOTICEBOARDS register_noticeboard(&box_0); register_noticeboard(&box_1); #endif } void trace(ObjectStack& fields) const { box_0.trace(fields); box_1.trace(fields); } }; struct WriterLoop { Writer* writer; WriterLoop(Writer* writer) : writer(writer) {} void operator()() { auto& alloc = ThreadAlloc::get(); auto c_0 = new (RegionType::Trace) C(1); freeze(c_0); auto c_1 = new (RegionType::Trace) C(2); freeze(c_1); writer->box_0.update(alloc, c_0); writer->box_1.update(alloc, c_1); } }; struct Reader : public VCown { public: Noticeboard* box_0; Noticeboard* box_1; Reader(Noticeboard* box_0_, Noticeboard* box_1_) : box_0{box_0_}, box_1{box_1_} {} }; Reader* g_reader = nullptr; Writer* g_writer = nullptr; struct ReaderLoop { Reader* reader; ReaderLoop(Reader* reader) : reader(reader) {} void operator()() { auto& alloc = ThreadAlloc::get(); auto c_1 = (C*)reader->box_1->peek(alloc); auto c_0 = (C*)reader->box_0->peek(alloc); // expected assertion failure; write to c_1 was picked up before c_0 // if (c_1->x == 2) { // check(c_0->x == 1); // } // out of scope Immutable::release(alloc, c_0); Immutable::release(alloc, c_1); Cown::release(alloc, g_reader); Cown::release(alloc, g_writer); } }; void run_test() { auto c_0 = new (RegionType::Trace) C(0); auto c_1 = new (RegionType::Trace) C(1); freeze(c_0); freeze(c_1); g_writer = new Writer(c_0, c_1); g_reader = new Reader(&g_writer->box_0, &g_writer->box_1); Behaviour::schedule(g_reader, g_reader); Behaviour::schedule(g_writer, g_writer); } }