void link_nodes_unsafe(node * new_top_node, node * end_node) { tagged_node_handle old_tos = tos.load(detail::memory_order_relaxed); tagged_node_handle new_tos (pool.get_handle(new_top_node), old_tos.get_tag()); end_node->next = pool.get_pointer(old_tos); tos.store(new_tos, memory_order_relaxed); }
void link_nodes_atomic(node * new_top_node, node * end_node) { tagged_node_handle old_tos = tos.load(detail::memory_order_relaxed); for (;;) { tagged_node_handle new_tos (pool.get_handle(new_top_node), old_tos.get_tag()); end_node->next = pool.get_handle(old_tos); if (tos.compare_exchange_weak(old_tos, new_tos)) break; } }
/** Pops object from stack. * * If pop operation is successful, * object is written to memory location denoted by ret. * * \returns true, if the pop operation is successful, false if stack was empty. * * \note Not thread-safe * * */ bool pop_unsafe(T & ret) { tagged_node_ptr old_tos = tos.load(detail::memory_order_relaxed); if (!old_tos.get_ptr()) return false; node * new_tos_ptr = old_tos->next.get_ptr(); tagged_node_ptr new_tos(new_tos_ptr, old_tos.get_tag() + 1); tos.store(new_tos, memory_order_relaxed); ret = old_tos->v; pool.destruct_unsafe(old_tos.get_ptr()); return true; }
/** Pushes object t to the queue. * May fail, if the freelist is not able to allocate a new queue node. * * \returns true, if the push operation is successful. * * \note Not thread-safe * \warning \b Warning: * May block if node needs to be allocated from the operating system * */ bool push_unsafe(T const & v) { node * newnode = pool.construct_unsafe(v); if (newnode == 0) return false; tagged_node_ptr old_tos = tos.load(detail::memory_order_relaxed); tagged_node_ptr new_tos (newnode, old_tos.get_tag()); newnode->next.set_ptr(old_tos.get_ptr()); tos.store(new_tos, memory_order_relaxed); return true; }
bool unsynchronized_pop(U & ret) { BOOST_STATIC_ASSERT((boost::is_convertible<T, U>::value)); tagged_node_handle old_tos = tos.load(detail::memory_order_relaxed); node * old_tos_pointer = pool.get_pointer(old_tos); if (!pool.get_pointer(old_tos)) return false; node * new_tos_ptr = pool.get_pointer(old_tos_pointer->next); tagged_node_handle new_tos(pool.get_handle(new_tos_ptr), old_tos.get_tag() + 1); tos.store(new_tos, memory_order_relaxed); detail::copy_payload(old_tos_pointer->v, ret); pool.template destruct<false>(old_tos); return true; }
/** Pushes object t to the queue. * May fail, if the freelist is not able to allocate a new queue node. * * \returns true, if the push operation is successful. * * \note Thread-safe and non-blocking * \warning \b Warning: * May block if node needs to be allocated from the operating system * */ bool push(T const & v) { node * newnode = pool.construct(v); if (newnode == 0) return false; tagged_node_ptr old_tos = tos.load(detail::memory_order_relaxed); for (;;) { tagged_node_ptr new_tos (newnode, old_tos.get_tag()); newnode->next.set_ptr(old_tos.get_ptr()); if (tos.compare_exchange_weak(old_tos, new_tos)) return true; } }
/** Pops object from stack. * * If pop operation is successful, * object is written to memory location denoted by ret. * * \returns true, if the pop operation is successful, false if stack was empty. * * \note Thread-safe and non-blocking * * */ bool pop(T & ret) { tagged_node_ptr old_tos = tos.load(detail::memory_order_consume); for (;;) { if (!old_tos.get_ptr()) return false; node * new_tos_ptr = old_tos->next.get_ptr(); tagged_node_ptr new_tos(new_tos_ptr, old_tos.get_tag() + 1); if (tos.compare_exchange_weak(old_tos, new_tos)) { ret = old_tos->v; pool.destruct(old_tos.get_ptr()); return true; } } }
bool consume_one(Functor const & f) { tagged_node_handle old_tos = tos.load(detail::memory_order_consume); for (;;) { node * old_tos_pointer = pool.get_pointer(old_tos); if (!old_tos_pointer) return false; tagged_node_handle new_tos(old_tos_pointer->next, old_tos.get_next_tag()); if (tos.compare_exchange_weak(old_tos, new_tos)) { f(old_tos_pointer->v); pool.template destruct<true>(old_tos); return true; } } }
bool pop(U & ret) { BOOST_STATIC_ASSERT((boost::is_convertible<T, U>::value)); tagged_node_handle old_tos = tos.load(detail::memory_order_consume); for (;;) { node * old_tos_pointer = pool.get_pointer(old_tos); if (!old_tos_pointer) return false; tagged_node_handle new_tos(old_tos_pointer->next, old_tos.get_tag() + 1); if (tos.compare_exchange_weak(old_tos, new_tos)) { detail::copy_payload(old_tos_pointer->v, ret); pool.template destruct<true>(old_tos); return true; } } }