add "lock-free queue"
[model-checker-benchmarks.git] / queue / g_blocking_queue.h
diff --git a/queue/g_blocking_queue.h b/queue/g_blocking_queue.h
new file mode 100644 (file)
index 0000000..a43295d
--- /dev/null
@@ -0,0 +1,122 @@
+// ============================================================================
+// Copyright (c) 2009-2010 Faustino Frechilla
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//  1. Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//  2. Redistributions in binary form must reproduce the above copyright
+//     notice, this list of conditions and the following disclaimer in the
+//     documentation and/or other materials provided with the distribution.
+//  3. The name of the author may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+/// @file q_blocking_queue.h
+/// @brief Definition of a thread-safe queue based on glib system calls
+/// It internally contains a std::queue which is protected from concurrent
+/// access by glib mutextes and conditional variables
+///
+/// @author Faustino Frechilla
+/// @history
+/// Ref  Who                 When         What
+///      Faustino Frechilla 04-May-2009 Original development (based on pthreads)
+///      Faustino Frechilla 19-May-2010 Ported to glib. Removed pthread dependency
+/// @endhistory
+///
+// ============================================================================
+
+#ifndef _GBLOCKINGQUEUE_H_
+#define _GBLOCKINGQUEUE_H_
+
+#include <glib.h>
+#include <queue>
+#include <limits> // std::numeric_limits<>::max
+
+#define BLOCKING_QUEUE_DEFAULT_MAX_SIZE std::numeric_limits<std::size_t >::max()
+
+/// @brief blocking thread-safe queue
+/// It uses a mutex+condition variables to protect the internal queue
+/// implementation. Inserting or reading elements use the same mutex
+template <typename T>
+class BlockingQueue
+{
+public:
+    BlockingQueue(std::size_t a_maxSize = BLOCKING_QUEUE_DEFAULT_MAX_SIZE);
+    ~BlockingQueue();
+
+    /// @brief Check if the queue is empty
+    /// This call can block if another thread owns the lock that protects the
+    /// queue
+    /// @return true if the queue is empty. False otherwise
+    bool IsEmpty();
+
+    /// @brief inserts an element into queue queue
+    /// This call can block if another thread owns the lock that protects the
+    /// queue. If the queue is full The thread will be blocked in this queue
+    /// until someone else gets an element from the queue
+    /// @param element to insert into the queue
+    /// @return True if the elem was successfully inserted into the queue.
+    ///         False otherwise
+    bool Push(const T &a_elem);
+
+    /// @brief inserts an element into queue queue
+    /// This call can block if another thread owns the lock that protects the
+    /// queue. If the queue is full The call will return false and the element
+    /// won't be inserted
+    /// @param element to insert into the queue
+    /// @return True if the elem was successfully inserted into the queue.
+    ///         False otherwise
+    bool TryPush(const T &a_elem);
+
+    /// @brief extracts an element from the queue (and deletes it from the q)
+    /// If the queue is empty this call will block the thread until there is
+    /// something in the queue to be extracted
+    /// @param a reference where the element from the queue will be saved to
+    void Pop(T &out_data);
+
+    /// @brief extracts an element from the queue (and deletes it from the q)
+    /// This call gets the block that protects the queue. It will extract the
+    /// element from the queue only if there are elements in it
+    /// @param reference to the variable where the result will be saved
+    /// @return True if the element was retrieved from the queue.
+    ///         False if the queue was empty
+    bool TryPop(T &out_data);
+
+    /// @brief extracts an element from the queue (and deletes it from the q)
+    /// If the queue is empty this call will block the thread until there
+    /// is something in the queue to be extracted or until the timer
+    /// (2nd parameter) expires
+    /// @param reference to the variable where the result will be saved
+    /// @param microsecondsto wait before returning if the queue was empty
+    /// @return True if the element was retrieved from the queue.
+    ///         False if the timeout was reached
+    bool TimedWaitPop(T &data, glong microsecs);
+
+protected:
+    std::queue<T> m_theQueue;
+    /// maximum number of elements for the queue
+    std::size_t m_maximumSize;
+    /// Mutex to protect the queue
+    GMutex* m_mutex;
+    /// Conditional variable to wake up threads
+    GCond*  m_cond;
+};
+
+// include the implementation file
+#include "g_blocking_queue_impl.h"
+
+#endif /* _GBLOCKINGQUEUE_H_ */