libcruft-util/test/thread/monitor.cpp

70 lines
1.6 KiB
C++
Raw Normal View History

/*
2018-08-04 15:14:06 +10:00
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
*/
#include <cruft/util/thread/event.hpp>
#include <cruft/util/thread/monitor.hpp>
#include <cruft/util/thread/semaphore.hpp>
#include <cruft/util/tap.hpp>
#include <atomic>
#include <thread>
///////////////////////////////////////////////////////////////////////////////
// a single atomic integer wrapper that allows precise ordering of thread
// entrance and exit for exact testing of thread interleavings.
struct foo {
foo ():
enter (0),
leave (0)
{ ; }
void
inc (void) {
enter.acquire ();
++value;
leave.release ();
}
std::atomic<int> value = 0;
cruft::thread::semaphore enter;
cruft::thread::semaphore leave;
};
///////////////////////////////////////////////////////////////////////////////
int
main ()
{
cruft::TAP::logger tap;
cruft::thread::monitor<foo> obj;
const auto &value = obj->value;
auto &enter = obj->enter;
auto &leave = obj->leave;
std::thread t1 ([&] () { obj->inc (); });
std::thread t2 ([&] () { obj->inc (); });
tap.expect_eq (value, 0, "wrapped class was left initialised");
enter.release ();
leave.acquire ();
tap.expect_eq (value, 1, "only one thread had access");
enter.release ();
leave.acquire ();
tap.expect_eq (value, 2, "second thread got access");
t1.join ();
t2.join ();
return tap.status ();
}