209 lines
5.4 KiB
C++
209 lines
5.4 KiB
C++
// Copyright (C) 2010 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
|
|
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <cstdlib>
|
|
#include <ctime>
|
|
#include <dlib/misc_api.h>
|
|
#include <dlib/threads.h>
|
|
|
|
#include "tester.h"
|
|
|
|
namespace
|
|
{
|
|
using namespace test;
|
|
using namespace dlib;
|
|
using namespace std;
|
|
|
|
logger dlog("test.read_write_mutex");
|
|
|
|
class read_write_mutex_tester : public tester, multithreaded_object
|
|
{
|
|
public:
|
|
read_write_mutex_tester (
|
|
) :
|
|
tester ("test_read_write_mutex",
|
|
"Runs tests on the read_write_mutex component.")
|
|
{
|
|
register_thread(*this, &read_write_mutex_tester::thread_write);
|
|
register_thread(*this, &read_write_mutex_tester::thread_write);
|
|
register_thread(*this, &read_write_mutex_tester::thread_write);
|
|
|
|
register_thread(*this, &read_write_mutex_tester::thread_readonly);
|
|
register_thread(*this, &read_write_mutex_tester::thread_readonly);
|
|
register_thread(*this, &read_write_mutex_tester::thread_readonly);
|
|
register_thread(*this, &read_write_mutex_tester::thread_readonly2);
|
|
register_thread(*this, &read_write_mutex_tester::thread_readonly2);
|
|
register_thread(*this, &read_write_mutex_tester::thread_readonly2);
|
|
|
|
}
|
|
|
|
read_write_mutex m;
|
|
|
|
dlib::mutex mut;
|
|
int num_write;
|
|
int num_read;
|
|
int max_read;
|
|
|
|
bool failure;
|
|
|
|
void thread_write ()
|
|
{
|
|
// do this so that the readonly threads can get into their loops first. This way
|
|
// we can see if the mutex lets many readers into their area
|
|
dlib::sleep(250);
|
|
for (int i = 0; i < 6; ++i)
|
|
{
|
|
auto_mutex lock(m);
|
|
|
|
mut.lock();
|
|
++num_write;
|
|
mut.unlock();
|
|
|
|
// only one write thread should ever be active at once
|
|
if (num_write != 1)
|
|
{
|
|
failure = true;
|
|
dlog << LERROR << "1";
|
|
}
|
|
|
|
dlib::sleep(300);
|
|
|
|
// only one write thread should ever be active at once
|
|
if (num_write != 1)
|
|
{
|
|
failure = true;
|
|
dlog << LERROR << "2";
|
|
}
|
|
|
|
mut.lock();
|
|
--num_write;
|
|
mut.unlock();
|
|
|
|
print_spinner();
|
|
}
|
|
dlog << LINFO << "exit thread_write()";
|
|
}
|
|
|
|
void do_readonly_stuff()
|
|
{
|
|
mut.lock();
|
|
++num_read;
|
|
max_read = max(num_read, max_read);
|
|
mut.unlock();
|
|
|
|
if (num_write != 0)
|
|
{
|
|
failure = true;
|
|
dlog << LERROR << "3";
|
|
}
|
|
|
|
dlib::sleep(300);
|
|
|
|
if (num_write != 0)
|
|
{
|
|
failure = true;
|
|
dlog << LERROR << "4";
|
|
}
|
|
|
|
mut.lock();
|
|
max_read = max(num_read, max_read);
|
|
--num_read;
|
|
mut.unlock();
|
|
|
|
print_spinner();
|
|
}
|
|
|
|
void thread_readonly ()
|
|
{
|
|
for (int i = 0; i < 6; ++i)
|
|
{
|
|
auto_mutex_readonly lock(m);
|
|
DLIB_TEST(lock.has_read_lock());
|
|
DLIB_TEST(!lock.has_write_lock());
|
|
do_readonly_stuff();
|
|
|
|
lock.lock_readonly();
|
|
DLIB_TEST(lock.has_read_lock());
|
|
DLIB_TEST(!lock.has_write_lock());
|
|
lock.unlock();
|
|
DLIB_TEST(!lock.has_read_lock());
|
|
DLIB_TEST(!lock.has_write_lock());
|
|
lock.lock_readonly();
|
|
DLIB_TEST(lock.has_read_lock());
|
|
DLIB_TEST(!lock.has_write_lock());
|
|
lock.lock_write();
|
|
DLIB_TEST(!lock.has_read_lock());
|
|
DLIB_TEST(lock.has_write_lock());
|
|
lock.lock_write();
|
|
DLIB_TEST(!lock.has_read_lock());
|
|
DLIB_TEST(lock.has_write_lock());
|
|
}
|
|
|
|
dlog << LINFO << "exit thread_readonly()";
|
|
}
|
|
|
|
void thread_readonly2 ()
|
|
{
|
|
for (int i = 0; i < 6; ++i)
|
|
{
|
|
m.lock_readonly();
|
|
auto_unlock_readonly unlock(m);
|
|
|
|
do_readonly_stuff();
|
|
}
|
|
dlog << LINFO << "exit thread_readonly2()";
|
|
}
|
|
|
|
|
|
void perform_test (
|
|
)
|
|
{
|
|
num_write = 0;
|
|
num_read = 0;
|
|
max_read = 0;
|
|
failure = false;
|
|
|
|
// doing this big block of weird stuff should have no effect.
|
|
{
|
|
m.unlock();
|
|
|
|
m.lock_readonly();
|
|
m.lock_readonly();
|
|
m.unlock();
|
|
m.unlock_readonly();
|
|
m.unlock();
|
|
m.unlock_readonly();
|
|
|
|
m.unlock();
|
|
m.unlock_readonly();
|
|
|
|
m.lock();
|
|
m.unlock_readonly();
|
|
m.unlock_readonly();
|
|
m.unlock();
|
|
}
|
|
|
|
|
|
// start up our testing threads
|
|
start();
|
|
|
|
// wait for the threads to finish
|
|
wait();
|
|
|
|
|
|
DLIB_TEST(failure == false);
|
|
DLIB_TEST_MSG(max_read == 6, "max_read: "<< max_read);
|
|
|
|
}
|
|
|
|
} a;
|
|
|
|
|
|
}
|
|
|
|
|
|
|