212 lines
5.8 KiB
C++
212 lines
5.8 KiB
C++
#ifndef BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_QUEUE_BASE_HPP
|
|
#define BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_QUEUE_BASE_HPP
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// (C) Copyright Vicente J. Botet Escriba 2013-2017. 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/thread for documentation.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <boost/bind/bind.hpp>
|
|
|
|
#include <boost/thread/detail/config.hpp>
|
|
#include <boost/thread/condition_variable.hpp>
|
|
#include <boost/thread/detail/move.hpp>
|
|
#include <boost/thread/mutex.hpp>
|
|
#include <boost/thread/concurrent_queues/queue_op_status.hpp>
|
|
|
|
#include <boost/chrono/time_point.hpp>
|
|
#include <boost/throw_exception.hpp>
|
|
|
|
#include <boost/config/abi_prefix.hpp>
|
|
|
|
namespace boost
|
|
{
|
|
namespace concurrent
|
|
{
|
|
namespace detail
|
|
{
|
|
|
|
template <class ValueType, class Queue>
|
|
class sync_queue_base
|
|
{
|
|
public:
|
|
typedef ValueType value_type;
|
|
typedef Queue underlying_queue_type;
|
|
typedef typename Queue::size_type size_type;
|
|
typedef queue_op_status op_status;
|
|
|
|
// Constructors/Assignment/Destructors
|
|
BOOST_THREAD_NO_COPYABLE(sync_queue_base)
|
|
inline sync_queue_base();
|
|
//template <typename Range>
|
|
//inline explicit sync_queue(Range range);
|
|
inline ~sync_queue_base();
|
|
|
|
// Observers
|
|
inline bool empty() const;
|
|
inline bool full() const;
|
|
inline size_type size() const;
|
|
inline bool closed() const;
|
|
|
|
// Modifiers
|
|
inline void close();
|
|
|
|
inline underlying_queue_type underlying_queue() {
|
|
lock_guard<mutex> lk(mtx_);
|
|
return boost::move(data_);
|
|
}
|
|
|
|
protected:
|
|
mutable mutex mtx_;
|
|
condition_variable cond_;
|
|
underlying_queue_type data_;
|
|
bool closed_;
|
|
|
|
inline bool empty(unique_lock<mutex>& ) const BOOST_NOEXCEPT
|
|
{
|
|
return data_.empty();
|
|
}
|
|
inline bool empty(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
|
{
|
|
return data_.empty();
|
|
}
|
|
|
|
inline size_type size(lock_guard<mutex>& ) const BOOST_NOEXCEPT
|
|
{
|
|
return data_.size();
|
|
}
|
|
inline bool closed(unique_lock<mutex>& lk) const;
|
|
inline bool closed(lock_guard<mutex>& lk) const;
|
|
|
|
inline void throw_if_closed(unique_lock<mutex>&);
|
|
inline void throw_if_closed(lock_guard<mutex>&);
|
|
|
|
inline bool not_empty_or_closed(unique_lock<mutex>& ) const;
|
|
|
|
inline bool wait_until_not_empty_or_closed(unique_lock<mutex>& lk);
|
|
template <class WClock, class Duration>
|
|
queue_op_status wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp);
|
|
|
|
inline void notify_elem_added(unique_lock<mutex>& )
|
|
{
|
|
cond_.notify_all();
|
|
}
|
|
inline void notify_elem_added(lock_guard<mutex>& )
|
|
{
|
|
cond_.notify_all();
|
|
}
|
|
|
|
};
|
|
|
|
template <class ValueType, class Queue>
|
|
sync_queue_base<ValueType, Queue>::sync_queue_base() :
|
|
data_(), closed_(false)
|
|
{
|
|
BOOST_ASSERT(data_.empty());
|
|
}
|
|
|
|
template <class ValueType, class Queue>
|
|
sync_queue_base<ValueType, Queue>::~sync_queue_base()
|
|
{
|
|
}
|
|
|
|
template <class ValueType, class Queue>
|
|
void sync_queue_base<ValueType, Queue>::close()
|
|
{
|
|
{
|
|
lock_guard<mutex> lk(mtx_);
|
|
closed_ = true;
|
|
}
|
|
cond_.notify_all();
|
|
}
|
|
|
|
template <class ValueType, class Queue>
|
|
bool sync_queue_base<ValueType, Queue>::closed() const
|
|
{
|
|
lock_guard<mutex> lk(mtx_);
|
|
return closed(lk);
|
|
}
|
|
template <class ValueType, class Queue>
|
|
bool sync_queue_base<ValueType, Queue>::closed(unique_lock<mutex>&) const
|
|
{
|
|
return closed_;
|
|
}
|
|
template <class ValueType, class Queue>
|
|
bool sync_queue_base<ValueType, Queue>::closed(lock_guard<mutex>&) const
|
|
{
|
|
return closed_;
|
|
}
|
|
|
|
template <class ValueType, class Queue>
|
|
bool sync_queue_base<ValueType, Queue>::empty() const
|
|
{
|
|
lock_guard<mutex> lk(mtx_);
|
|
return empty(lk);
|
|
}
|
|
template <class ValueType, class Queue>
|
|
bool sync_queue_base<ValueType, Queue>::full() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
template <class ValueType, class Queue>
|
|
typename sync_queue_base<ValueType, Queue>::size_type sync_queue_base<ValueType, Queue>::size() const
|
|
{
|
|
lock_guard<mutex> lk(mtx_);
|
|
return size(lk);
|
|
}
|
|
|
|
template <class ValueType, class Queue>
|
|
void sync_queue_base<ValueType, Queue>::throw_if_closed(unique_lock<mutex>& lk)
|
|
{
|
|
if (closed(lk))
|
|
{
|
|
BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
|
|
}
|
|
}
|
|
template <class ValueType, class Queue>
|
|
void sync_queue_base<ValueType, Queue>::throw_if_closed(lock_guard<mutex>& lk)
|
|
{
|
|
if (closed(lk))
|
|
{
|
|
BOOST_THROW_EXCEPTION( sync_queue_is_closed() );
|
|
}
|
|
}
|
|
|
|
template <class ValueType, class Queue>
|
|
bool sync_queue_base<ValueType, Queue>::not_empty_or_closed(unique_lock<mutex>& ) const
|
|
{
|
|
return ! data_.empty() || closed_;
|
|
}
|
|
|
|
template <class ValueType, class Queue>
|
|
bool sync_queue_base<ValueType, Queue>::wait_until_not_empty_or_closed(unique_lock<mutex>& lk)
|
|
{
|
|
cond_.wait(lk, boost::bind(&sync_queue_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk)));
|
|
if (! empty(lk)) return false; // success
|
|
return true; // closed
|
|
}
|
|
|
|
template <class ValueType, class Queue>
|
|
template <class WClock, class Duration>
|
|
queue_op_status sync_queue_base<ValueType, Queue>::wait_until_not_empty_or_closed_until(unique_lock<mutex>& lk, chrono::time_point<WClock,Duration> const&tp)
|
|
{
|
|
if (! cond_.wait_until(lk, tp, boost::bind(&sync_queue_base<ValueType, Queue>::not_empty_or_closed, boost::ref(*this), boost::ref(lk))))
|
|
return queue_op_status::timeout;
|
|
if (! empty(lk)) return queue_op_status::success;
|
|
return queue_op_status::closed;
|
|
}
|
|
|
|
} // detail
|
|
} // concurrent
|
|
} // boost
|
|
|
|
#include <boost/config/abi_suffix.hpp>
|
|
|
|
#endif
|