test_tss.cpp

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

CPP
325
字号
// Copyright (C) 2001-2003// William E. Kempf// Copyright (C) 2007 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/thread/detail/config.hpp>#include <boost/thread/tss.hpp>#include <boost/thread/mutex.hpp>#include <boost/thread/thread.hpp>#include <boost/test/unit_test.hpp>#include <libs/thread/test/util.inl>#include <iostream>#if defined(BOOST_HAS_WINTHREADS)    #define WIN32_LEAN_AND_MEAN    #include <windows.h>    #endifboost::mutex check_mutex;boost::mutex tss_mutex;int tss_instances = 0;int tss_total = 0;struct tss_value_t{    tss_value_t()    {        boost::mutex::scoped_lock lock(tss_mutex);        ++tss_instances;        ++tss_total;        value = 0;    }    ~tss_value_t()    {        boost::mutex::scoped_lock lock(tss_mutex);        --tss_instances;    }    int value;};boost::thread_specific_ptr<tss_value_t> tss_value;void test_tss_thread(){    tss_value.reset(new tss_value_t());    for (int i=0; i<1000; ++i)    {        int& n = tss_value->value;        // Don't call BOOST_CHECK_EQUAL directly, as it doesn't appear to        // be thread safe. Must evaluate further.        if (n != i)        {            boost::mutex::scoped_lock lock(check_mutex);            BOOST_CHECK_EQUAL(n, i);        }        ++n;    }}#if defined(BOOST_THREAD_PLATFORM_WIN32)    typedef HANDLE native_thread_t;    DWORD WINAPI test_tss_thread_native(LPVOID /*lpParameter*/)    {        test_tss_thread();        return 0;    }    native_thread_t create_native_thread(void)    {        native_thread_t const res=CreateThread(            0, //security attributes (0 = not inheritable)            0, //stack size (0 = default)             &test_tss_thread_native, //function to execute            0, //parameter to pass to function            0, //creation flags (0 = run immediately)            0  //thread id (0 = thread id not returned)            );        BOOST_CHECK(res!=0);        return res;    }    void join_native_thread(native_thread_t thread)    {        DWORD res = WaitForSingleObject(thread, INFINITE);        BOOST_CHECK(res == WAIT_OBJECT_0);        res = CloseHandle(thread);        BOOST_CHECK(SUCCEEDED(res));    }#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)    typedef pthread_t native_thread_t;extern "C"{    void* test_tss_thread_native(void* lpParameter)    {        test_tss_thread();        return 0;    }}    native_thread_t create_native_thread()    {        native_thread_t thread_handle;                int const res = pthread_create(&thread_handle, 0, &test_tss_thread_native, 0);        BOOST_CHECK(!res);        return thread_handle;    }    void join_native_thread(native_thread_t thread)    {        void* result=0;        int const res=pthread_join(thread,&result);        BOOST_CHECK(!res);    }#endifvoid do_test_tss(){    tss_instances = 0;    tss_total = 0;    const int NUMTHREADS=5;    boost::thread_group threads;    try    {        for (int i=0; i<NUMTHREADS; ++i)            threads.create_thread(&test_tss_thread);        threads.join_all();    }    catch(...)    {        threads.interrupt_all();        threads.join_all();        throw;    }    std::cout        << "tss_instances = " << tss_instances        << "; tss_total = " << tss_total        << "\n";    std::cout.flush();    BOOST_CHECK_EQUAL(tss_instances, 0);    BOOST_CHECK_EQUAL(tss_total, 5);    tss_instances = 0;    tss_total = 0;    native_thread_t thread1 = create_native_thread();    native_thread_t thread2 = create_native_thread();    native_thread_t thread3 = create_native_thread();    native_thread_t thread4 = create_native_thread();    native_thread_t thread5 = create_native_thread();    join_native_thread(thread5);    join_native_thread(thread4);    join_native_thread(thread3);    join_native_thread(thread2);    join_native_thread(thread1);    std::cout        << "tss_instances = " << tss_instances        << "; tss_total = " << tss_total        << "\n";    std::cout.flush();    // The following is not really an error. TSS cleanup support still is available for boost threads.    // Also this usually will be triggered only when bound to the static version of thread lib.    // 2006-10-02 Roland Schwarz    //BOOST_CHECK_EQUAL(tss_instances, 0);    BOOST_CHECK_MESSAGE(tss_instances == 0, "Support of automatic tss cleanup for native threading API not available");    BOOST_CHECK_EQUAL(tss_total, 5);}void test_tss(){    timed_test(&do_test_tss, 2);}bool tss_cleanup_called=false;struct Dummy{};void tss_custom_cleanup(Dummy* d){    delete d;    tss_cleanup_called=true;}boost::thread_specific_ptr<Dummy> tss_with_cleanup(tss_custom_cleanup);void tss_thread_with_custom_cleanup(){    tss_with_cleanup.reset(new Dummy);}void do_test_tss_with_custom_cleanup(){    boost::thread t(tss_thread_with_custom_cleanup);    try    {        t.join();    }    catch(...)    {        t.interrupt();        t.join();        throw;    }    BOOST_CHECK(tss_cleanup_called);}void test_tss_with_custom_cleanup(){    timed_test(&do_test_tss_with_custom_cleanup, 2);}Dummy* tss_object=new Dummy;void tss_thread_with_custom_cleanup_and_release(){    tss_with_cleanup.reset(tss_object);    tss_with_cleanup.release();}void do_test_tss_does_no_cleanup_after_release(){    tss_cleanup_called=false;    boost::thread t(tss_thread_with_custom_cleanup_and_release);    try    {        t.join();    }    catch(...)    {        t.interrupt();        t.join();        throw;    }    BOOST_CHECK(!tss_cleanup_called);    if(!tss_cleanup_called)    {        delete tss_object;    }}struct dummy_class_tracks_deletions{    static unsigned deletions;        ~dummy_class_tracks_deletions()    {        ++deletions;    }    };unsigned dummy_class_tracks_deletions::deletions=0;boost::thread_specific_ptr<dummy_class_tracks_deletions> tss_with_null_cleanup(NULL);void tss_thread_with_null_cleanup(dummy_class_tracks_deletions* delete_tracker){    tss_with_null_cleanup.reset(delete_tracker);}void do_test_tss_does_no_cleanup_with_null_cleanup_function(){    dummy_class_tracks_deletions* delete_tracker=new dummy_class_tracks_deletions;    boost::thread t(tss_thread_with_null_cleanup,delete_tracker);    try    {        t.join();    }    catch(...)    {        t.interrupt();        t.join();        throw;    }    BOOST_CHECK(!dummy_class_tracks_deletions::deletions);    if(!dummy_class_tracks_deletions::deletions)    {        delete delete_tracker;    }}void test_tss_does_no_cleanup_after_release(){    timed_test(&do_test_tss_does_no_cleanup_after_release, 2);}void test_tss_does_no_cleanup_with_null_cleanup_function(){    timed_test(&do_test_tss_does_no_cleanup_with_null_cleanup_function, 2);}boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]){    boost::unit_test_framework::test_suite* test =        BOOST_TEST_SUITE("Boost.Threads: tss test suite");    test->add(BOOST_TEST_CASE(test_tss));    test->add(BOOST_TEST_CASE(test_tss_with_custom_cleanup));    test->add(BOOST_TEST_CASE(test_tss_does_no_cleanup_after_release));    test->add(BOOST_TEST_CASE(test_tss_does_no_cleanup_with_null_cleanup_function));    return test;}

⌨️ 快捷键说明

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