condition_test_template.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 413 行
HPP
413 行
// Copyright (C) 2001-2003// William E. Kempf//// Permission to use, copy, modify, distribute and sell this software// and its documentation for any purpose is hereby granted without fee,// provided that the above copyright notice appear in all copies and// that both that copyright notice and this permission notice appear// in supporting documentation. William E. Kempf makes no representations// about the suitability of this software for any purpose.// It is provided "as is" without express or implied warranty.////////////////////////////////////////////////////////////////////////////////// (C) Copyright Ion Gaztanaga 2005-2007. 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)//// See http://www.boost.org/libs/interprocess for documentation.////////////////////////////////////////////////////////////////////////////////#ifndef BOOST_INTERPROCESS_CONDITION_TEST_TEMPLATE_HPP#define BOOST_INTERPROCESS_CONDITION_TEST_TEMPLATE_HPP#include <boost/interprocess/detail/config_begin.hpp>#include <boost/interprocess/detail/workaround.hpp>#include <boost/thread/detail/config.hpp>#include <boost/interprocess/sync/interprocess_condition.hpp>#include <boost/thread/thread.hpp>#include <boost/date_time/posix_time/posix_time_types.hpp>#include <boost/thread/xtime.hpp>#include <boost/interprocess/sync/interprocess_mutex.hpp>namespace boost{namespace interprocess{namespace test {boost::posix_time::ptime ptime_delay(int secs){ return microsec_clock::universal_time() + boost::posix_time::time_duration(0, 0, secs);}inline boost::xtime delay(int secs, int msecs=0, int nsecs=0){ const int MILLISECONDS_PER_SECOND = 1000; const int NANOSECONDS_PER_SECOND = 1000000000; const int NANOSECONDS_PER_MILLISECOND = 1000000; boost::xtime xt; int ret = boost::xtime_get(&xt, boost::TIME_UTC); assert(ret == static_cast<int>(boost::TIME_UTC));(void)ret; nsecs += xt.nsec; msecs += nsecs / NANOSECONDS_PER_MILLISECOND; secs += msecs / MILLISECONDS_PER_SECOND; nsecs += (msecs % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; xt.nsec = nsecs % NANOSECONDS_PER_SECOND; xt.sec += secs + (nsecs / NANOSECONDS_PER_SECOND); return xt;}template <typename F, typename T>class binder{public: binder(const F& func, const T& param) : func(func), param(param) { } void operator()() const { func(param); }private: F func; T param;};template <typename F, typename T>binder<F, T> bind_function(F func, T param){ return binder<F, T>(func, param);}template <class Condition, class Mutex>struct condition_test_data{ condition_test_data() : notified(0), awoken(0) { } ~condition_test_data() {} Mutex mutex; Condition condition; int notified; int awoken;};template <class Condition, class Mutex>void condition_test_thread(condition_test_data<Condition, Mutex>* data){ boost::interprocess::scoped_lock<Mutex> lock(data->mutex); assert(lock ? true : false); while (!(data->notified > 0)) data->condition.wait(lock); assert(lock ? true : false); data->awoken++;}struct cond_predicate{ cond_predicate(int& var, int val) : _var(var), _val(val) { } bool operator()() { return _var == _val; } int& _var; int _val;};template <class Condition, class Mutex>void condition_test_waits(condition_test_data<Condition, Mutex>* data){ boost::interprocess::scoped_lock<Mutex> lock(data->mutex); assert(lock ? true : false); // Test wait. while (data->notified != 1) data->condition.wait(lock); assert(lock ? true : false); assert(data->notified == 1); data->awoken++; data->condition.notify_one(); // Test predicate wait. data->condition.wait(lock, cond_predicate(data->notified, 2)); assert(lock ? true : false); assert(data->notified == 2); data->awoken++; data->condition.notify_one(); // Test timed_wait. while (data->notified != 3) data->condition.timed_wait(lock, ptime_delay(5)); assert(lock ? true : false); assert(data->notified == 3); data->awoken++; data->condition.notify_one(); // Test predicate timed_wait. cond_predicate pred(data->notified, 4); bool ret = data->condition.timed_wait(lock, ptime_delay(5), pred); assert(ret);(void)ret; assert(lock ? true : false); assert(pred()); assert(data->notified == 4); data->awoken++; data->condition.notify_one();}template <class Condition, class Mutex>void do_test_condition_notify_one(){ condition_test_data<Condition, Mutex> data; boost::thread thread(bind_function(&condition_test_thread<Condition, Mutex>, &data)); { boost::interprocess::scoped_lock<Mutex> lock(data.mutex); assert(lock ? true : false); data.notified++; data.condition.notify_one(); } thread.join(); assert(data.awoken == 1);}template <class Condition, class Mutex>void do_test_condition_notify_all(){ const int NUMTHREADS = 3; boost::thread_group threads; condition_test_data<Condition, Mutex> data; for (int i = 0; i < NUMTHREADS; ++i) threads.create_thread(bind_function(&condition_test_thread<Condition, Mutex>, &data)); { boost::interprocess::scoped_lock<Mutex> lock(data.mutex); assert(lock ? true : false); data.notified++; data.condition.notify_all(); } threads.join_all(); assert(data.awoken == NUMTHREADS);}template <class Condition, class Mutex>void do_test_condition_waits(){ condition_test_data<Condition, Mutex> data; boost::thread thread(bind_function(&condition_test_waits<Condition, Mutex>, &data)); { boost::interprocess::scoped_lock<Mutex> lock(data.mutex); assert(lock ? true : false); boost::thread::sleep(delay(1)); data.notified++; data.condition.notify_one(); while (data.awoken != 1) data.condition.wait(lock); assert(lock ? true : false); assert(data.awoken == 1); boost::thread::sleep(delay(1)); data.notified++; data.condition.notify_one(); while (data.awoken != 2) data.condition.wait(lock); assert(lock ? true : false); assert(data.awoken == 2); boost::thread::sleep(delay(1)); data.notified++; data.condition.notify_one(); while (data.awoken != 3) data.condition.wait(lock); assert(lock ? true : false); assert(data.awoken == 3); boost::thread::sleep(delay(1)); data.notified++; data.condition.notify_one(); while (data.awoken != 4) data.condition.wait(lock); assert(lock ? true : false); assert(data.awoken == 4); } thread.join(); assert(data.awoken == 4);}/*//Message queue simulation testtemplate <class Condition>inline Condition &cond_empty(){ static Condition cond_empty; return cond_empty;}template <class Condition>inline Condition &cond_full(){ static Condition cond_full; return cond_full;}template <class Mutex>inline Mutex &mutex(){ static Mutex mut; return mut;}*/static volatile int count = 0;static volatile int waiting_readers = 0;static volatile int waiting_writer = 0;const int queue_size = 3;const int thread_factor = 10;const int NumThreads = thread_factor*queue_size;//Function that removes items from queuetemplate <class Condition, class Mutex>struct condition_func{ condition_func(Condition &cond_full, Condition &cond_empty, Mutex &mutex) : cond_full_(cond_full), cond_empty_(cond_empty), mutex_(mutex) {} void operator()() { boost::interprocess::scoped_lock<Mutex>lock(mutex_); while(count == 0){ ++waiting_readers; cond_empty_.wait(lock); --waiting_readers; } --count; if(waiting_writer) cond_full_.notify_one(); } Condition &cond_full_; Condition &cond_empty_; Mutex &mutex_;};//Queue functionstemplate <class Condition, class Mutex>void do_test_condition_queue_notify_one(void){ //Force mutex and condition creation Condition cond_empty; Condition cond_full; Mutex mutex; //Create threads that will decrease count { //Initialize counters count = 0; waiting_readers = 0; waiting_writer = 0; boost::thread_group thgroup; int i; for(i = 0; i< NumThreads; ++i){ condition_func<Condition, Mutex> func(cond_full, cond_empty, mutex); thgroup.create_thread(func); } //Add 20 elements one by one in the queue simulation //The sender will block if it fills the queue for(i = 0; i < NumThreads; ++i){ boost::interprocess::scoped_lock<Mutex> lock(mutex); while(count == queue_size){ ++waiting_writer; cond_full.wait(lock); --waiting_writer; } count++; if(waiting_readers) cond_empty.notify_one(); } thgroup.join_all(); assert(count == 0); assert(waiting_readers == 0); assert(waiting_writer == 0); }}//Queue functionstemplate <class Condition, class Mutex>void do_test_condition_queue_notify_all(void){ //Force mutex and condition creation Condition cond_empty; Condition cond_full; Mutex mutex; //Create threads that will decrease count { //Initialize counters count = 0; waiting_readers = 0; waiting_writer = 0; boost::thread_group thgroup; int i; for(i = 0; i< NumThreads; ++i){ condition_func<Condition, Mutex> func(cond_full, cond_empty, mutex); thgroup.create_thread(func); } //Fill queue to the max size and notify all several times for(i = 0; i < NumThreads; ++i){ boost::interprocess::scoped_lock<Mutex>lock(mutex); while(count == queue_size){ ++waiting_writer; cond_full.wait(lock); --waiting_writer; } count++; if(waiting_readers) cond_empty.notify_all(); } thgroup.join_all(); assert(count == 0); assert(waiting_readers == 0); assert(waiting_writer == 0); }}template <class Condition, class Mutex>bool do_test_condition(){ std::cout << "do_test_condition_notify_one<" << typeid(Condition).name() << "," << typeid(Mutex).name() << std::endl; do_test_condition_notify_one<Condition, Mutex>(); std::cout << "do_test_condition_notify_all<" << typeid(Condition).name() << "," << typeid(Mutex).name() << std::endl; do_test_condition_notify_all<Condition, Mutex>(); std::cout << "do_test_condition_waits<" << typeid(Condition).name() << "," << typeid(Mutex).name() << std::endl; do_test_condition_waits<Condition, Mutex>(); //std::cout << "do_test_condition_queue_notify_one<" << typeid(Condition).name() << "," << typeid(Mutex).name() << std::endl; //do_test_condition_queue_notify_one<Condition, Mutex>(); //std::cout << "do_test_condition_queue_notify_all<" << typeid(Condition).name() << "," << typeid(Mutex).name() << std::endl; //do_test_condition_queue_notify_all<Condition, Mutex>(); return true;}} //namespace test} //namespace interprocess{} //namespace boost{#include <boost/interprocess/detail/config_end.hpp>#endif //#ifndef BOOST_INTERPROCESS_CONDITION_TEST_TEMPLATE_HPP
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?