test_generic_locks.cpp

来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 524 行

CPP
524
字号
// (C) Copyright 2008 Anthony Williams// Distributed under the Boost Software License, Version 1.0. (See// accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)#include <boost/test/unit_test.hpp>#include <boost/thread/mutex.hpp>#include <boost/thread/thread.hpp>#include <boost/thread/locks.hpp>#include <boost/thread/condition_variable.hpp>void test_lock_two_uncontended(){    boost::mutex m1,m2;    boost::mutex::scoped_lock l1(m1,boost::defer_lock),        l2(m2,boost::defer_lock);    BOOST_CHECK(!l1.owns_lock());    BOOST_CHECK(!l2.owns_lock());        boost::lock(l1,l2);        BOOST_CHECK(l1.owns_lock());    BOOST_CHECK(l2.owns_lock());}struct wait_data{    boost::mutex m;    bool flag;    boost::condition_variable cond;        wait_data():        flag(false)    {}        void wait()    {        boost::mutex::scoped_lock l(m);        while(!flag)        {            cond.wait(l);        }    }    template<typename Duration>    bool timed_wait(Duration d)    {        boost::system_time const target=boost::get_system_time()+d;                boost::mutex::scoped_lock l(m);        while(!flag)        {            if(!cond.timed_wait(l,target))            {                return flag;            }        }        return true;    }        void signal()    {        boost::mutex::scoped_lock l(m);        flag=true;        cond.notify_all();    }};       void lock_mutexes_slowly(boost::mutex* m1,boost::mutex* m2,wait_data* locked,wait_data* quit){    boost::lock_guard<boost::mutex> l1(*m1);    boost::this_thread::sleep(boost::posix_time::milliseconds(500));    boost::lock_guard<boost::mutex> l2(*m2);    locked->signal();    quit->wait();}void lock_pair(boost::mutex* m1,boost::mutex* m2){    boost::lock(*m1,*m2);    boost::mutex::scoped_lock l1(*m1,boost::adopt_lock),        l2(*m2,boost::adopt_lock);}void test_lock_two_other_thread_locks_in_order(){    boost::mutex m1,m2;    wait_data locked;    wait_data release;        boost::thread t(lock_mutexes_slowly,&m1,&m2,&locked,&release);    boost::this_thread::sleep(boost::posix_time::milliseconds(10));    boost::thread t2(lock_pair,&m1,&m2);    BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(1)));    release.signal();        BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(1)));    t.join();}void test_lock_two_other_thread_locks_in_opposite_order(){    boost::mutex m1,m2;    wait_data locked;    wait_data release;        boost::thread t(lock_mutexes_slowly,&m1,&m2,&locked,&release);    boost::this_thread::sleep(boost::posix_time::milliseconds(10));    boost::thread t2(lock_pair,&m2,&m1);    BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(1)));    release.signal();        BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(1)));    t.join();}void test_lock_five_uncontended(){    boost::mutex m1,m2,m3,m4,m5;    boost::mutex::scoped_lock l1(m1,boost::defer_lock),        l2(m2,boost::defer_lock),        l3(m3,boost::defer_lock),        l4(m4,boost::defer_lock),        l5(m5,boost::defer_lock);    BOOST_CHECK(!l1.owns_lock());    BOOST_CHECK(!l2.owns_lock());    BOOST_CHECK(!l3.owns_lock());    BOOST_CHECK(!l4.owns_lock());    BOOST_CHECK(!l5.owns_lock());        boost::lock(l1,l2,l3,l4,l5);        BOOST_CHECK(l1.owns_lock());    BOOST_CHECK(l2.owns_lock());    BOOST_CHECK(l3.owns_lock());    BOOST_CHECK(l4.owns_lock());    BOOST_CHECK(l5.owns_lock());}void lock_five_mutexes_slowly(boost::mutex* m1,boost::mutex* m2,boost::mutex* m3,boost::mutex* m4,boost::mutex* m5,                              wait_data* locked,wait_data* quit){    boost::lock_guard<boost::mutex> l1(*m1);    boost::this_thread::sleep(boost::posix_time::milliseconds(500));    boost::lock_guard<boost::mutex> l2(*m2);    boost::this_thread::sleep(boost::posix_time::milliseconds(500));    boost::lock_guard<boost::mutex> l3(*m3);    boost::this_thread::sleep(boost::posix_time::milliseconds(500));    boost::lock_guard<boost::mutex> l4(*m4);    boost::this_thread::sleep(boost::posix_time::milliseconds(500));    boost::lock_guard<boost::mutex> l5(*m5);    locked->signal();    quit->wait();}void lock_five(boost::mutex* m1,boost::mutex* m2,boost::mutex* m3,boost::mutex* m4,boost::mutex* m5){    boost::lock(*m1,*m2,*m3,*m4,*m5);    m1->unlock();    m2->unlock();    m3->unlock();    m4->unlock();    m5->unlock();}void test_lock_five_other_thread_locks_in_order(){    boost::mutex m1,m2,m3,m4,m5;    wait_data locked;    wait_data release;        boost::thread t(lock_five_mutexes_slowly,&m1,&m2,&m3,&m4,&m5,&locked,&release);    boost::this_thread::sleep(boost::posix_time::milliseconds(10));    boost::thread t2(lock_five,&m1,&m2,&m3,&m4,&m5);    BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3)));    release.signal();        BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3)));    t.join();}void test_lock_five_other_thread_locks_in_different_order(){    boost::mutex m1,m2,m3,m4,m5;    wait_data locked;    wait_data release;        boost::thread t(lock_five_mutexes_slowly,&m1,&m2,&m3,&m4,&m5,&locked,&release);    boost::this_thread::sleep(boost::posix_time::milliseconds(10));    boost::thread t2(lock_five,&m5,&m1,&m4,&m2,&m3);    BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3)));    release.signal();        BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3)));    t.join();}void lock_n(boost::mutex* mutexes,unsigned count){    boost::lock(mutexes,mutexes+count);    for(unsigned i=0;i<count;++i)    {        mutexes[i].unlock();    }}void test_lock_ten_other_thread_locks_in_different_order(){    unsigned const num_mutexes=10;        boost::mutex mutexes[num_mutexes];    wait_data locked;    wait_data release;        boost::thread t(lock_five_mutexes_slowly,&mutexes[6],&mutexes[3],&mutexes[8],&mutexes[0],&mutexes[2],&locked,&release);    boost::this_thread::sleep(boost::posix_time::milliseconds(10));    boost::thread t2(lock_n,mutexes,num_mutexes);    BOOST_CHECK(locked.timed_wait(boost::posix_time::seconds(3)));    release.signal();    BOOST_CHECK(t2.timed_join(boost::posix_time::seconds(3)));    t.join();}struct dummy_mutex{    bool is_locked;        dummy_mutex():        is_locked(false)    {}        void lock()    {        is_locked=true;    }        bool try_lock()    {        if(is_locked)        {            return false;        }        is_locked=true;        return true;    }        void unlock()    {        is_locked=false;    }};namespace boost{    template<>    struct is_mutex_type<dummy_mutex>    {        BOOST_STATIC_CONSTANT(bool, value = true);    };}void test_lock_five_in_range(){    unsigned const num_mutexes=5;    dummy_mutex mutexes[num_mutexes];    boost::lock(mutexes,mutexes+num_mutexes);        for(unsigned i=0;i<num_mutexes;++i)    {        BOOST_CHECK(mutexes[i].is_locked);    }}void test_lock_ten_in_range(){    unsigned const num_mutexes=10;    dummy_mutex mutexes[num_mutexes];    boost::lock(mutexes,mutexes+num_mutexes);        for(unsigned i=0;i<num_mutexes;++i)    {        BOOST_CHECK(mutexes[i].is_locked);    }}void test_try_lock_two_uncontended(){    dummy_mutex m1,m2;    int const res=boost::try_lock(m1,m2);        BOOST_CHECK(res==-1);    BOOST_CHECK(m1.is_locked);    BOOST_CHECK(m2.is_locked);}void test_try_lock_two_first_locked(){    dummy_mutex m1,m2;    m1.lock();    boost::unique_lock<dummy_mutex> l1(m1,boost::defer_lock),        l2(m2,boost::defer_lock);    int const res=boost::try_lock(l1,l2);        BOOST_CHECK(res==0);    BOOST_CHECK(m1.is_locked);    BOOST_CHECK(!m2.is_locked);    BOOST_CHECK(!l1.owns_lock());    BOOST_CHECK(!l2.owns_lock());}void test_try_lock_two_second_locked(){    dummy_mutex m1,m2;    m2.lock();    boost::unique_lock<dummy_mutex> l1(m1,boost::defer_lock),        l2(m2,boost::defer_lock);    int const res=boost::try_lock(l1,l2);        BOOST_CHECK(res==1);    BOOST_CHECK(!m1.is_locked);    BOOST_CHECK(m2.is_locked);    BOOST_CHECK(!l1.owns_lock());    BOOST_CHECK(!l2.owns_lock());}void test_try_lock_three(){    int const num_mutexes=3;        for(int i=-1;i<num_mutexes;++i)    {        dummy_mutex mutexes[num_mutexes];        if(i>=0)        {            mutexes[i].lock();        }        boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock),            l2(mutexes[1],boost::defer_lock),            l3(mutexes[2],boost::defer_lock);        int const res=boost::try_lock(l1,l2,l3);            BOOST_CHECK(res==i);        for(int j=0;j<num_mutexes;++j)        {            if((i==j) || (i==-1))            {                BOOST_CHECK(mutexes[j].is_locked);            }            else            {                BOOST_CHECK(!mutexes[j].is_locked);            }        }        if(i==-1)        {            BOOST_CHECK(l1.owns_lock());            BOOST_CHECK(l2.owns_lock());            BOOST_CHECK(l3.owns_lock());        }        else        {            BOOST_CHECK(!l1.owns_lock());            BOOST_CHECK(!l2.owns_lock());            BOOST_CHECK(!l3.owns_lock());        }    }}void test_try_lock_four(){    int const num_mutexes=4;        for(int i=-1;i<num_mutexes;++i)    {        dummy_mutex mutexes[num_mutexes];        if(i>=0)        {            mutexes[i].lock();        }        boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock),            l2(mutexes[1],boost::defer_lock),            l3(mutexes[2],boost::defer_lock),            l4(mutexes[3],boost::defer_lock);        int const res=boost::try_lock(l1,l2,l3,l4);            BOOST_CHECK(res==i);        for(int j=0;j<num_mutexes;++j)        {            if((i==j) || (i==-1))            {                BOOST_CHECK(mutexes[j].is_locked);            }            else            {                BOOST_CHECK(!mutexes[j].is_locked);            }        }        if(i==-1)        {            BOOST_CHECK(l1.owns_lock());            BOOST_CHECK(l2.owns_lock());            BOOST_CHECK(l3.owns_lock());            BOOST_CHECK(l4.owns_lock());        }        else        {            BOOST_CHECK(!l1.owns_lock());            BOOST_CHECK(!l2.owns_lock());            BOOST_CHECK(!l3.owns_lock());            BOOST_CHECK(!l4.owns_lock());        }    }}void test_try_lock_five(){    int const num_mutexes=5;        for(int i=-1;i<num_mutexes;++i)    {        dummy_mutex mutexes[num_mutexes];        if(i>=0)        {            mutexes[i].lock();        }        boost::unique_lock<dummy_mutex> l1(mutexes[0],boost::defer_lock),            l2(mutexes[1],boost::defer_lock),            l3(mutexes[2],boost::defer_lock),            l4(mutexes[3],boost::defer_lock),            l5(mutexes[4],boost::defer_lock);        int const res=boost::try_lock(l1,l2,l3,l4,l5);            BOOST_CHECK(res==i);        for(int j=0;j<num_mutexes;++j)        {            if((i==j) || (i==-1))            {                BOOST_CHECK(mutexes[j].is_locked);            }            else            {                BOOST_CHECK(!mutexes[j].is_locked);            }        }        if(i==-1)        {            BOOST_CHECK(l1.owns_lock());            BOOST_CHECK(l2.owns_lock());            BOOST_CHECK(l3.owns_lock());            BOOST_CHECK(l4.owns_lock());            BOOST_CHECK(l5.owns_lock());        }        else        {            BOOST_CHECK(!l1.owns_lock());            BOOST_CHECK(!l2.owns_lock());            BOOST_CHECK(!l3.owns_lock());            BOOST_CHECK(!l4.owns_lock());            BOOST_CHECK(!l5.owns_lock());        }    }}boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]){    boost::unit_test_framework::test_suite* test =        BOOST_TEST_SUITE("Boost.Threads: generic locks test suite");    test->add(BOOST_TEST_CASE(&test_lock_two_uncontended));    test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_order));    test->add(BOOST_TEST_CASE(&test_lock_two_other_thread_locks_in_opposite_order));    test->add(BOOST_TEST_CASE(&test_lock_five_uncontended));    test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_order));    test->add(BOOST_TEST_CASE(&test_lock_five_other_thread_locks_in_different_order));    test->add(BOOST_TEST_CASE(&test_lock_five_in_range));    test->add(BOOST_TEST_CASE(&test_lock_ten_in_range));    test->add(BOOST_TEST_CASE(&test_lock_ten_other_thread_locks_in_different_order));    test->add(BOOST_TEST_CASE(&test_try_lock_two_uncontended));    test->add(BOOST_TEST_CASE(&test_try_lock_two_first_locked));    test->add(BOOST_TEST_CASE(&test_try_lock_two_second_locked));    test->add(BOOST_TEST_CASE(&test_try_lock_three));    test->add(BOOST_TEST_CASE(&test_try_lock_four));    test->add(BOOST_TEST_CASE(&test_try_lock_five));    return test;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?