Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #pragma once
00027
00028 #include <boost/circular_buffer.hpp>
00029 #include <boost/noncopyable.hpp>
00030 #include "cinder/Thread.h"
00031
00032 namespace cinder {
00033
00034 template<typename T>
00035 class ConcurrentCircularBuffer : public boost::noncopyable {
00036 public:
00037 typedef boost::circular_buffer<T> container_type;
00038 typedef typename container_type::size_type size_type;
00039 typedef typename container_type::value_type value_type;
00040 typedef typename boost::call_traits<value_type>::param_type param_type;
00041
00042 explicit ConcurrentCircularBuffer( size_type capacity )
00043 : mNumUnread( 0 ), mContainer( capacity ), mCanceled( false )
00044 {}
00045
00046 void pushFront( param_type item ) {
00047
00048 std::unique_lock<std::mutex> lock( mMutex );
00049 while( ! is_not_full_impl() && ! mCanceled ) {
00050 mNotFullCond.wait( lock );
00051 }
00052 if( mCanceled )
00053 return;
00054 mContainer.push_front( item );
00055 ++mNumUnread;
00056 mNotEmptyCond.notify_one();
00057 }
00058
00059 void popBack(value_type* pItem) {
00060 std::unique_lock<std::mutex> lock( mMutex );
00061 while( ! is_not_empty_impl() && ! mCanceled ) {
00062 mNotEmptyCond.wait( lock );
00063 }
00064 if( mCanceled )
00065 return;
00066 *pItem = mContainer[--mNumUnread];
00067 mNotFullCond.notify_one();
00068 }
00069
00071 bool tryPushFront( param_type item ) {
00072
00073 std::unique_lock<std::mutex> lock( mMutex );
00074 if( ! is_not_full_impl() )
00075 return false;
00076 mContainer.push_front( item );
00077 ++mNumUnread;
00078 mNotEmptyCond.notify_one();
00079 return true;
00080 }
00081
00083 bool tryPopBack( value_type* pItem ) {
00084 std::unique_lock<std::mutex> lock( mMutex );
00085 if( ! is_not_empty_impl() )
00086 return false;
00087 *pItem = mContainer[--mNumUnread];
00088 mNotFullCond.notify_one();
00089 return true;
00090 }
00091
00092 bool isNotEmpty() {
00093 std::unique_lock<std::mutex> lock( mMutex );
00094 return is_not_empty_impl();
00095 }
00096
00097 bool isNotFull() {
00098 std::unique_lock<std::mutex> lock( mMutex );
00099 return is_not_full_impl();
00100 }
00101
00102 void cancel() {
00103 std::lock_guard<std::mutex> lock( mMutex );
00104 mCanceled = true;
00105 mNotFullCond.notify_all();
00106 mNotEmptyCond.notify_all();
00107 }
00108
00110 size_t size() const { return (size_t)mContainer.capacity(); }
00111
00112 private:
00113 bool is_not_empty_impl() const { return mNumUnread > 0; }
00114 bool is_not_full_impl() const { return mNumUnread < mContainer.capacity(); }
00115
00116 size_type mNumUnread;
00117 container_type mContainer;
00118 std::mutex mMutex;
00119 std::condition_variable mNotEmptyCond;
00120 std::condition_variable mNotFullCond;
00121 bool mCanceled;
00122 };
00123
00124 }