boost::lockfree是boost1.53引入的無鎖數據結構,包括boost::lockfree::stack、boost::lockfree::queue和boost::lockfree::spsc_queue三種,前兩種用於多生產者/多消費者場景,第三個用於單生產者/單消費者場景,下面對它們的使用進行詳細介紹,以boost::lockfree::stack為例,其他類似。
構造
boost::lockfree::stack源代碼如下(boost 1.65):
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
template <typename T, class A0, class A1, class A2>
#else
template <typename T, typename ...Options>
#endif
class stack
{
private:
#ifndef BOOST_DOXYGEN_INVOKED
BOOST_STATIC_ASSERT(boost::is_copy_constructible<T>::value);
#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
typedef typename detail::stack_signature::bind<A0, A1, A2>::type bound_args;
#else
typedef typename detail::stack_signature::bind<Options...>::type bound_args;
#endif
static const bool has_capacity = detail::extract_capacity<bound_args>::has_capacity;
static const size_t capacity = detail::extract_capacity<bound_args>::capacity;
static const bool fixed_sized = detail::extract_fixed_sized<bound_args>::value;
static const bool node_based = !(has_capacity || fixed_sized);
static const bool compile_time_sized = has_capacity;
/* 省略 */
public:
typedef T value_type;
typedef typename implementation_defined::allocator allocator;
typedef typename implementation_defined::size_type size_type;
//! Construct stack
// @{
stack(void):
pool(node_allocator(), capacity)
{
BOOST_ASSERT(has_capacity);
initialize();
}
template <typename U>
explicit stack(typename node_allocator::template rebind<U>::other const & alloc):
pool(alloc, capacity)
{
BOOST_STATIC_ASSERT(has_capacity);
initialize();
}
explicit stack(allocator const & alloc):
pool(alloc, capacity)
{
BOOST_ASSERT(has_capacity);
initialize();
}
// @}
//! Construct stack, allocate n nodes for the freelist.
// @{
explicit stack(size_type n):
pool(node_allocator(), n)
{
BOOST_ASSERT(!has_capacity);
initialize();
}
template <typename U>
stack(size_type n, typename node_allocator::template rebind<U>::other const & alloc):
pool(alloc, n)
{
BOOST_STATIC_ASSERT(!has_capacity);
initialize();
}
boost::lockfree::stack的第一個模板參數是元素類型,后面3個參數是用來配置stack的,沒有順序要求:
- boost::lockfree::fixed_sized:是否固定大小,默認為
boost::lockfree::fixed_sized<false>
,如果為true,則內部使用數組保存元素,大小不能動態增長; - boost::lockfree::capacity:編譯時設置內部數組大小,設置了capacity意味着一定是
boost::lockfree::fixed_sized<true>
,和運行時指定大小是互斥的,見下面的例子; - boost::lockfree::allocator:設置分配器,默認
boost::lockfree::allocator<std::allocator<void>>
。
例如:
//表示動態大小,初始大小為4,用完了再動態增長;此時必須在構造函數指定初始大小,否則斷言失敗;
boost::lockfree::stack<int> s(4);
//表示大小固定,運行時指定初始大小為4,用完后再push就會失敗;此時必須在構造函數指定初始大小,否則斷言失敗;
boost::lockfree::stack<int, boost::lockfree::fixed_sized<true>> s1(4);
//表示大小固定,編譯時指定初始大小為4,用完后再push就會失敗;此時不能在構造函數指定初始大小,否則斷言失敗;
boost::lockfree::stack<int, boost::lockfree::capacity<4>> s2;
//和上面一樣,設置了capacity,fixed_size就總是true
boost::lockfree::stack<int, boost::lockfree::fixed_size<false>, boost::lockfree::capacity<4>> s3;
成員方法
- push:壓入一個元素到容器,除了unsynchronized_,都是線程安全的。所有都是非阻塞的。
bool push(T const & v)
bool bounded_push(T const & v)
template <typename ConstIterator>
ConstIterator push(ConstIterator begin, ConstIterator end)
template <typename ConstIterator>
ConstIterator bounded_push(ConstIterator begin, ConstIterator end)
bool unsynchronized_push(T const & v)
ConstIterator unsynchronized_push(ConstIterator begin, ConstIterator end)
bounded_表示不動態增長,當初始大小用完后再push就會失敗;
unsynchronized_表示非線程安全;
- pop:從容器中彈出一個元素,除了unsynchronized_,都是線程安全的。所有都是非阻塞的。
bool pop(T & ret)
template <typename U>
bool pop(U & ret)
bool unsynchronized_pop(T & ret)
template <typename U>
bool unsynchronized_pop(U & ret)
unsynchronized_表示非線程安全;
- consume_:從容器彈出1個或全部元素,並應用某個函數對象。線程安全或阻塞與否取決於函數對象。
template <typename Functor>
bool consume_one(Functor & f)
template <typename Functor>
bool consume_one(Functor const & f)
template <typename Functor>
size_t consume_all(Functor & f)
template <typename Functor>
size_t consume_all(Functor const & f)
template <typename Functor>
size_t consume_all_atomic(Functor & f)
template <typename Functor>
size_t consume_all_atomic(Functor const & f)
template <typename Functor>
size_t consume_all_atomic_reversed(Functor & f)
template <typename Functor>
size_t consume_all_atomic_reversed(Functor const & f)
_one表示只消費1個元素;
_all表示消費所有元素;
_atomic表示消費過程是原子的,其間其他操作對其是不可見的。
_reversed表示倒序消費。
- 其他
//預分配空閑節點數,和編譯時設置capacity互斥;線程安全,可能阻塞
void reserve(size_type n)
//非線程安全
void reserve_unsafe(size_type n)
//判斷是否為空
bool empty(void) const
簡單示例
#include <boost/lockfree/stack.hpp>
int main(int argc, char *argv[])
{
boost::lockfree::stack<int> s(64);
//producer
for (int i = 0; i < 1000; i++)
{
s.push(i);
}
//consumer
s.consume_all([](int i)
{
std::cout << i << std::endl;
});
return 0;
}