#include #include #include #include #include #include #if defined(BOOST_HAS_PTHREADS) # include #endif namespace { const int ITERS = 100; boost::mutex io_mutex; } template class buffer_t : public M, public boost::condition { public: typedef typename M::lock lock; buffer_t(int n) : p(0), c(0), full(0), buf(n) { } void send(int m) { lock lk(*this); while (full == buf.size()) wait(lk); buf[p] = m; p = (p+1) % buf.size(); ++full; notify_all(); } int receive() { lock lk(*this); while (full == 0) wait(lk); int i = buf[c]; c = (c+1) % buf.size(); --full; notify_all(); return i; } static buffer_t& get_buffer() { static buffer_t buf(2); return buf; } static void do_sender_thread() { for (int n = 0; n < ITERS; ++n) { get_buffer().send(n); { volatile boost::mutex::lock lock(io_mutex); std::cout << "sent: " << n << std::endl; } } } static void do_receiver_thread() { int n; do { n = get_buffer().receive(); { volatile boost::mutex::lock lock(io_mutex); std::cout << "received: " << n << std::endl; } } while (n < ITERS - 1); } private: unsigned int p, c, full; std::vector buf; }; class void_invoker_t { public: void_invoker_t(void (*f)()) : func(f) {} void operator()() { func(); } private: void (*func)(); }; #if defined(BOOST_HAS_WINTHREADS) #include #include unsigned __stdcall do_thread(void* param) { typedef void_invoker_t* call; call f = (call)param; (*f)(); return 0; } template void do_test(M* dummy=0) { typedef buffer_t buffer_type; static void_invoker_t sender_thread(&buffer_type::do_sender_thread); static void_invoker_t receiver_thread(&buffer_type::do_receiver_thread); buffer_type::get_buffer(); HANDLE thrd[2]; unsigned id; thrd[0] = (HANDLE)_beginthreadex(0, 0, &do_thread, &sender_thread, 0, &id); thrd[1] = (HANDLE)_beginthreadex(0, 0, &do_thread, &receiver_thread, 0, &id); WaitForMultipleObjects(2, thrd, TRUE, INFINITE); CloseHandle(thrd[0]); CloseHandle(thrd[1]); } #else void* do_thread(void* param) { typedef void_invoker_t* call; call f = (call)param; (*f)(); return 0; } template void do_test() { typedef buffer_t buffer_type; static void_invoker_t sender_thread(&buffer_type::do_sender_thread); static void_invoker_t receiver_thread(&buffer_type::do_receiver_thread); buffer_type::get_buffer(); pthread_t thrd1, thrd2; pthread_create(&thrd1, 0, &do_thread, &sender_thread); pthread_create(&thrd2, 0, &do_thread, &receiver_thread); pthread_join(thrd1, 0); pthread_join(thrd2, 0); } #endif void test_buffer() { do_test(); do_test(); do_test(); } int main() { test_buffer(); return 0; }