initial code repo
[stor4nfv.git] / src / ceph / src / rbd_replay / BoundedBuffer.hpp
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #ifndef _INCLUDED_BOUNDED_BUFFER_HPP
5 #define _INCLUDED_BOUNDED_BUFFER_HPP
6
7 #include <boost/bind.hpp>
8 #include <boost/circular_buffer.hpp>
9 #include <boost/thread/condition.hpp>
10 #include <boost/thread/mutex.hpp>
11
12 /**
13    Blocking, fixed-capacity, thread-safe FIFO queue useful for communicating between threads.
14    This code was taken from the Boost docs: http://www.boost.org/doc/libs/1_55_0/libs/circular_buffer/example/circular_buffer_bound_example.cpp
15  */
16 template <class T>
17 class BoundedBuffer {
18 public:
19   typedef boost::circular_buffer<T> container_type;
20   typedef typename container_type::size_type size_type;
21   typedef typename container_type::value_type value_type;
22   typedef typename boost::call_traits<value_type>::param_type param_type;
23
24   explicit BoundedBuffer(size_type capacity) : m_unread(0), m_container(capacity) {
25   }
26
27   /**
28      Inserts an element into the queue.
29      Blocks if the queue is full.
30    */
31   void push_front(typename boost::call_traits<value_type>::param_type item) {
32     // `param_type` represents the "best" way to pass a parameter of type `value_type` to a method.
33     boost::mutex::scoped_lock lock(m_mutex);
34     m_not_full.wait(lock, boost::bind(&BoundedBuffer<value_type>::is_not_full, this));
35     m_container.push_front(item);
36     ++m_unread;
37     lock.unlock();
38     m_not_empty.notify_one();
39   }
40
41   /**
42      Removes an element from the queue.
43      Blocks if the queue is empty.
44   */
45   void pop_back(value_type* pItem) {
46     boost::mutex::scoped_lock lock(m_mutex);
47     m_not_empty.wait(lock, boost::bind(&BoundedBuffer<value_type>::is_not_empty, this));
48     *pItem = m_container[--m_unread];
49     lock.unlock();
50     m_not_full.notify_one();
51   }
52
53 private:
54   BoundedBuffer(const BoundedBuffer&);             // Disabled copy constructor.
55   BoundedBuffer& operator= (const BoundedBuffer&); // Disabled assign operator.
56
57   bool is_not_empty() const {
58     return m_unread > 0;
59   }
60   bool is_not_full() const {
61     return m_unread < m_container.capacity();
62   }
63
64   size_type m_unread;
65   container_type m_container;
66   boost::mutex m_mutex;
67   boost::condition m_not_empty;
68   boost::condition m_not_full;
69 };
70
71 #endif