]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - wtf/MessageQueue.h
JavaScriptCore-554.1.tar.gz
[apple/javascriptcore.git] / wtf / MessageQueue.h
index 19c5c10fede9649a519bb480ba00b2212a0bc85f..7721dba512187e7c05a2ba18aa3e57e2f32cdfb8 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,6 +30,7 @@
 #ifndef MessageQueue_h
 #define MessageQueue_h
 
+#include <limits>
 #include <wtf/Assertions.h>
 #include <wtf/Deque.h>
 #include <wtf/Noncopyable.h>
@@ -45,12 +47,14 @@ namespace WTF {
     template<typename DataType>
     class MessageQueue : Noncopyable {
     public:
-        MessageQueue() : m_killed(false) {}
+        MessageQueue() : m_killed(false) { }
         
         void append(const DataType&);
+        bool appendAndCheckEmpty(const DataType&);
         void prepend(const DataType&);
         bool waitForMessage(DataType&);
-        MessageQueueWaitResult waitForMessageTimed(DataType&, double absoluteTime);
+        template<typename Predicate>
+        MessageQueueWaitResult waitForMessageFilteredWithTimeout(DataType&, Predicate&, double absoluteTime);
         void kill();
 
         bool tryGetMessage(DataType&);
@@ -59,7 +63,11 @@ namespace WTF {
         // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
         bool isEmpty();
 
+        static double infiniteTime() { return std::numeric_limits<double>::max(); }
+
     private:
+        static bool alwaysTruePredicate(DataType&) { return true; }
+
         mutable Mutex m_mutex;
         ThreadCondition m_condition;
         Deque<DataType> m_queue;
@@ -74,6 +82,17 @@ namespace WTF {
         m_condition.signal();
     }
 
+    // Returns true if the queue was empty before the item was added.
+    template<typename DataType>
+    inline bool MessageQueue<DataType>::appendAndCheckEmpty(const DataType& message)
+    {
+        MutexLocker lock(m_mutex);
+        bool wasEmpty = m_queue.isEmpty();
+        m_queue.append(message);
+        m_condition.signal();
+        return wasEmpty;
+    }
+
     template<typename DataType>
     inline void MessageQueue<DataType>::prepend(const DataType& message)
     {
@@ -85,38 +104,33 @@ namespace WTF {
     template<typename DataType>
     inline bool MessageQueue<DataType>::waitForMessage(DataType& result)
     {
-        MutexLocker lock(m_mutex);
-
-        while (!m_killed && m_queue.isEmpty())
-            m_condition.wait(m_mutex);
-
-        if (m_killed)
-            return false;
-
-        ASSERT(!m_queue.isEmpty());
-        result = m_queue.first();
-        m_queue.removeFirst();
-        return true;
+        MessageQueueWaitResult exitReason = waitForMessageFilteredWithTimeout(result, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime());
+        ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived);
+        return exitReason == MessageQueueMessageReceived;
     }
 
     template<typename DataType>
-    inline MessageQueueWaitResult MessageQueue<DataType>::waitForMessageTimed(DataType& result, double absoluteTime)
+    template<typename Predicate>
+    inline MessageQueueWaitResult MessageQueue<DataType>::waitForMessageFilteredWithTimeout(DataType& result, Predicate& predicate, double absoluteTime)
     {
         MutexLocker lock(m_mutex);
         bool timedOut = false;
 
-        while (!m_killed && !timedOut && m_queue.isEmpty())
+        DequeConstIterator<DataType> found = m_queue.end();
+        while (!m_killed && !timedOut && (found = m_queue.findIf(predicate)) == m_queue.end())
             timedOut = !m_condition.timedWait(m_mutex, absoluteTime);
 
+        ASSERT(!timedOut || absoluteTime != infiniteTime());
+
         if (m_killed)
             return MessageQueueTerminated;
 
         if (timedOut)
             return MessageQueueTimeout;
 
-        ASSERT(!m_queue.isEmpty());
-        result = m_queue.first();
-        m_queue.removeFirst();
+        ASSERT(found != m_queue.end());
+        result = *found;
+        m_queue.remove(found);
         return MessageQueueMessageReceived;
     }
 
@@ -157,7 +171,7 @@ namespace WTF {
         MutexLocker lock(m_mutex);
         return m_killed;
     }
-}
+} // namespace WTF
 
 using WTF::MessageQueue;
 // MessageQueueWaitResult enum and all its values.