/
zOMGdev
/
cppcms
Обзор
Документация
Войти
/
zOMGdev
/
cppcms
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
booster/lib/thread/test/test_thread.cpp
464 строки
10 KB
Artyom Beilis
Fixed test to represet actual issue
06 дек 2015, 22:53
06 дек 2015, 22:53
707e638
Код
Авторство
О чём код?
// // Copyright (C) 2009-2012 Artyom Beilis (Tonkikh) // // 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 <booster/thread.h> #include <booster/posix_time.h> #include "test.h" #include <iostream> #include <stdlib.h> #ifndef BOOSTER_WIN32 #include <unistd.h> #endif bool called_ = false; void caller() { called_=true; } int variable = 0; template<typename MutexType> struct incrementer { MutexType *mutex_; void operator()() { for(int i=0;i<5;i++) { { booster::unique_lock<MutexType> ul(*mutex_); int tmp = variable; booster::ptime::millisleep(20); variable = tmp + 1; } } } }; bool tls_ok = true; booster::mutex dtor_called_mutex; int dtor_called = 0; struct counted_functor { counted_functor() { add(1); } counted_functor(counted_functor const &) { add(1); } counted_functor const &operator=(counted_functor const &) { return *this; } ~counted_functor() { add(-1); } void operator()() const { booster::ptime::millisleep(200); } static void add(int v) { booster::unique_lock<booster::mutex> g(lock); objects+= v; } static booster::mutex lock; static int objects; }; booster::mutex counted_functor::lock; int counted_functor::objects; struct tls_object { int counter; tls_object() : counter(0) {} ~tls_object() { booster::unique_lock<booster::mutex> guard(dtor_called_mutex); dtor_called++; } }; struct tls_functor2 { booster::thread_specific_ptr<tls_object> *ptr; tls_functor2(booster::thread_specific_ptr<tls_object> &p) : ptr(&p) {} void operator()() const { ptr->reset(new tls_object()); booster::ptime::millisleep(600); } }; struct tls_functor { booster::thread_specific_ptr<tls_object> *ptr; tls_functor(booster::thread_specific_ptr<tls_object> &p) : ptr(&p) {} void operator()() const { try { booster::thread_specific_ptr<tls_object> &p=*ptr; if(p.get()==0) p.reset(new tls_object()); for(int i=0;i<10;i++) { int v1 = p->counter; booster::ptime::millisleep(25); p->counter = v1+1; TEST(p->counter == i+1); } TEST(p->counter == 10); } catch(...) { tls_ok=false; } } }; struct cond_incrementer { int *counter; booster::mutex *m; booster::condition_variable *c; void operator()() const { booster::unique_lock<booster::mutex> l(*m); c->wait(l); ++*counter; } }; template<typename ShM> struct rw_executor { bool *flag; bool read; booster::mutex *flags_mutex; ShM *mutex; void operator()() const { for(int i=0;i<20;i++) { if(read) { mutex->shared_lock(); { flags_mutex->lock(); *flag = true; flags_mutex->unlock(); } booster::ptime::millisleep(5); { flags_mutex->lock(); *flag = false; flags_mutex->unlock(); } mutex->unlock(); } else { mutex->unique_lock(); *flag = true; booster::ptime::millisleep(5); *flag = false; mutex->unlock(); } } } }; struct rw_shared_thread { booster::recursive_shared_mutex *lp; bool *done; void operator()() const { lp->shared_lock(); booster::ptime::millisleep(500); booster::ptime start = booster::ptime::now(); lp->shared_lock(); booster::ptime end = booster::ptime::now(); booster::ptime::millisleep(200); lp->unlock(); lp->unlock(); TEST(end-start < booster::ptime::milliseconds(100)); *done = true; } }; struct rw_unique_thread { booster::recursive_shared_mutex *lp; bool *done; void operator()() const { booster::ptime::millisleep(250); booster::ptime start = booster::ptime::now(); lp->unique_lock(); booster::ptime end = booster::ptime::now(); lp->unlock(); TEST((end - start) > booster::ptime::milliseconds(100)); *done = true; } }; int main() { try { { std::cout << "Test execution" << std::endl; TEST(!called_); booster::thread t(caller); t.join(); TEST(called_); } { std::cout << "Functor destruction" << std::endl; TEST(counted_functor::objects==0); { counted_functor f; booster::thread t(f); TEST(counted_functor::objects>=2); t.join(); TEST(counted_functor::objects==1); } TEST(counted_functor::objects==0); { { counted_functor f; booster::thread t(f); TEST(counted_functor::objects>=2); t.detach(); } TEST(counted_functor::objects>=1); booster::ptime::millisleep(400); TEST(counted_functor::objects==0); } } std::cout << "Test recursive mutex" << std::endl; { booster::recursive_mutex m; m.lock(); m.lock(); TEST("Double lock works"); m.unlock(); m.unlock(); TEST("Got there"); } { variable = 0; booster::recursive_mutex m; incrementer<booster::recursive_mutex> inc = { &m }; booster::thread t1(inc); booster::thread t2(inc); t1.join(); t2.join(); TEST(variable == 10); } std::cout << "Test mutex" << std::endl; { variable = 0; booster::mutex m; incrementer<booster::mutex> inc = { &m }; booster::thread t1(inc); booster::thread t2(inc); t1.join(); t2.join(); TEST(variable == 10); } std::cout << "Test thread specific" << std::endl; { booster::thread_specific_ptr<tls_object> p; tls_functor f1(p); tls_functor f2(p); tls_functor f3(p); booster::thread t1(f1); booster::thread t2(f2); booster::thread t3(f3); t1.join(); t2.join(); t3.join(); TEST(tls_ok); TEST(dtor_called == 3); } std::cout << "Non synchronous thread specific" << std::endl; { dtor_called = 0; booster::thread_specific_ptr<tls_object> *p = new booster::thread_specific_ptr<tls_object>(); tls_functor2 f1(*p); tls_functor2 f2(*p); tls_functor2 f3(*p); booster::thread t1(f1); booster::thread t2(f2); booster::thread t3(f3); booster::ptime::millisleep(300); delete p; t1.join(); t2.join(); t3.join(); TEST(dtor_called == 3); } std::cout << "Thest conditional variable notify one" << std::endl; { int counter = 0; booster::mutex m; booster::condition_variable c; cond_incrementer inc = { &counter, &m , &c }; booster::thread t1(inc); booster::thread t2(inc); booster::thread t3(inc); booster::ptime::millisleep(100); TEST(counter == 0); c.notify_one(); booster::ptime::millisleep(100); TEST(counter == 1); c.notify_one(); booster::ptime::millisleep(100); TEST(counter == 2); c.notify_one(); booster::ptime::millisleep(100); TEST(counter == 3); t1.join(); t2.join(); t3.join(); } std::cout << "Thest conditional variable notify all" << std::endl; { int counter[3] = { 0, 0 , 0 }; booster::mutex m; booster::condition_variable c; cond_incrementer inc = { counter, &m , &c }; booster::thread t1(inc); inc.counter++; booster::thread t2(inc); inc.counter++; booster::thread t3(inc); booster::ptime::millisleep(100); TEST(counter[0]==0 && counter[1]==0 && counter[2]==0); c.notify_all(); booster::ptime::millisleep(100); TEST(counter[0]==1 && counter[1]==1 && counter[2]==1); t1.join(); t2.join(); t3.join(); } std::cout << "Test shared_mutex write lock" << std::endl; { variable = 0; booster::shared_mutex m; incrementer<booster::shared_mutex> inc = { &m }; booster::thread t1(inc); booster::thread t2(inc); t1.join(); t2.join(); TEST(variable == 10); } std::cout << "Test recursive_shared_mutex write lock" << std::endl; { variable = 0; booster::shared_mutex m; incrementer<booster::shared_mutex> inc = { &m }; booster::thread t1(inc); booster::thread t2(inc); t1.join(); t2.join(); TEST(variable == 10); } std::cout << "Test shared_mutex shared/write lock" << std::endl; { booster::mutex fm; booster::shared_mutex sm; bool flags[3] = {false,false,false}; bool mread_happened = false; bool write_happened = false; bool error_occured = false ; rw_executor<booster::shared_mutex> exec1 = { flags + 0, true, &fm, &sm }; rw_executor<booster::shared_mutex> exec2 = { flags + 1, true, &fm, &sm }; rw_executor<booster::shared_mutex> exec3 = { flags + 2, true, &fm, &sm }; booster::thread t1(exec1); booster::thread t2(exec2); booster::thread t3(exec3); for(int i=0;i<100;i++) { booster::ptime::millisleep(1); { booster::unique_lock<booster::mutex> l(fm); if(flags[0] && flags[1]) mread_happened = true; if(flags[2]) write_happened = true; if((flags[0] || flags[1]) && flags[2]) error_occured = true; } } t1.join(); t2.join(); t3.join(); TEST(mread_happened); TEST(write_happened); TEST(error_occured); } std::cout << "Test recursive_shared_mutex shared/write lock" << std::endl; { booster::mutex fm; booster::recursive_shared_mutex sm; bool flags[3] = {false,false,false}; bool mread_happened = false; bool write_happened = false; bool error_occured = false ; rw_executor<booster::recursive_shared_mutex> exec1 = { flags + 0, true, &fm, &sm }; rw_executor<booster::recursive_shared_mutex> exec2 = { flags + 1, true, &fm, &sm }; rw_executor<booster::recursive_shared_mutex> exec3 = { flags + 2, true, &fm, &sm }; booster::thread t1(exec1); booster::thread t2(exec2); booster::thread t3(exec3); for(int i=0;i<100;i++) { booster::ptime::millisleep(1); { booster::unique_lock<booster::mutex> l(fm); if(flags[0] && flags[1]) mread_happened = true; if(flags[2]) write_happened = true; if((flags[0] || flags[1]) && flags[2]) error_occured = true; } } t1.join(); t2.join(); t3.join(); TEST(mread_happened); TEST(write_happened); TEST(error_occured); } std::cout << "Test recursive_shared_mutex recursive shared lock" << std::endl; { booster::recursive_shared_mutex l; bool read = false; bool write = false; rw_shared_thread t1c = { &l, &read }; rw_unique_thread t2c = { &l, &write }; booster::thread t1(t1c); booster::thread t2(t2c); t1.join(); t2.join(); TEST(read); TEST(write); } } catch(std::exception const &e) { std::cerr << "Fail:" <<e.what(); return EXIT_FAILURE; } std::cout << "Ok" << std::endl; return EXIT_SUCCESS; }