dlib C++ Library - read_write_mutex.cpp

// 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;
}

AltStyle によって変換されたページ (->オリジナル) /