/** * pops the next item from the top of the queue. this may cause the calling * thread to sleep until an item is available, and will only return when an * item has been successfully retrieved or when the thread is stopping * * @param t assigned to the item at the top of the queue * @param thread_info ConsumerThread object used to manage the thread * * @return true if an item was retrieved, false if the queue is empty */ bool pop(T& t, ConsumerThread& thread_info) { boost::uint32_t last_known_version; while (thread_info.isRunning()) { // try to get the next value if ( dequeue(t, last_known_version) ) return true; // got an item // queue is empty boost::mutex::scoped_lock tail_lock(m_tail_mutex); if (m_tail_ptr->version == last_known_version) { // still empty after acquiring lock thread_info.m_next_ptr = m_idle_ptr; m_idle_ptr = & thread_info; // get wakeup time (if any) if (thread_info.hasWakeupTimer()) { // wait for an item to become available const boost::posix_time::ptime wakeup_time(boost::get_system_time() + thread_info.getWakeupTimer()); if (!thread_info.m_wakeup_event.timed_wait(tail_lock, wakeup_time)) return false; // timer expired if timed_wait() returns false } else { // wait for an item to become available thread_info.m_wakeup_event.wait(tail_lock); } } } return false; }
/** * pushes a new item into the back of the queue * * @param t the item to add to the back of the queue */ void push(const T& t) { // sleep while MaxSize is exceeded if (MaxSize > 0) { boost::system_time wakeup_time; while (size() >= MaxSize) { wakeup_time = boost::get_system_time() + boost::posix_time::millisec(SleepMilliSec); boost::thread::sleep(wakeup_time); } } // create a new list node for the queue item QueueNode *node_ptr = createNode(); node_ptr->data = t; node_ptr->next = NULL; node_ptr->version = 0; // append node to the end of the list boost::mutex::scoped_lock tail_lock(m_tail_mutex); node_ptr->version = (m_next_version += 2); m_tail_ptr->next = node_ptr; // update the tail pointer for the new node m_tail_ptr = node_ptr; // increment size ++m_size; // wake up an idle thread (if any) if (m_idle_ptr) { ConsumerThread *idle_ptr = m_idle_ptr; m_idle_ptr = m_idle_ptr->m_next_ptr; idle_ptr->m_wakeup_event.notify_one(); } }
void push(T new_value) { std::shared_ptr<T> new_data( std::make_shared<T>(std::move(new_value))); std::unique_ptr<node> p(new node()); const node* new_tail = p.get(); std::lock_guard<std::mutex> tail_lock(_tail_mutex); _tail->data = new_data; _tail->next = std::move(p); _tail = new_tail; }
/// clears the list by removing all remaining items void clear(void) { boost::mutex::scoped_lock tail_lock(m_tail_mutex); boost::mutex::scoped_lock head_lock(m_head_mutex); // also delete dummy node and reinitialize it to clear old value while (m_head_ptr) { m_tail_ptr = m_head_ptr; m_head_ptr = m_head_ptr->next; destroyNode(m_tail_ptr); if (m_head_ptr) --m_size; } initialize(); }
void push(T new_value) { std::shared_ptr<T> new_data( std::make_shared<T>(std::move(new_value))); std::unique_ptr<node> p(new node); { std::lock_guard<std::mutex> tail_lock(tail_mutex); tail->data = new_data; node *const new_tail = p.get(); tail->next = std::move(p); tail = new_tail; } data_cond.notify_one(); }
node* get_tail() { std::lock_guard<std::mutex> tail_lock(_tail_mutex); return _tail; }