libcruft-util/test/thread/monitor.cpp

77 lines
1.9 KiB
C++
Raw Normal View History

/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
*/
#include "tap.hpp"
#include "thread/monitor.hpp"
#include "thread/event.hpp"
#include "thread/semaphore.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;
util::thread::semaphore enter;
util::thread::semaphore leave;
};
///////////////////////////////////////////////////////////////////////////////
int
main ()
{
util::TAP::logger tap;
util::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 ();
}