Bug 1161405 - Part 2: Test case for parallelism of the thread pool. r=nfroyd, a=lizzard
☠☠ backed out by 94832733e36b ☠ ☠
authorJW Wang <jwwang@mozilla.com>
Sat, 09 May 2015 07:32:27 +0800
changeset 267492 5f5e1ff2d8a473a2876e523eaf69f84ed370e19d
parent 267491 4e1782f281d55e3fe399be05e48936c6cb0c40ab
child 267493 8c5b0f20b703a0eaee0ca2028423bde2261d5bb7
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnfroyd, lizzard
bugs1161405
milestone39.0
Bug 1161405 - Part 2: Test case for parallelism of the thread pool. r=nfroyd, a=lizzard
xpcom/tests/gtest/TestThreadPool.cpp
--- a/xpcom/tests/gtest/TestThreadPool.cpp
+++ b/xpcom/tests/gtest/TestThreadPool.cpp
@@ -8,16 +8,17 @@
 #include <stdlib.h>
 #include "nsXPCOM.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsIThreadPool.h"
 #include "nsComponentManagerUtils.h"
 #include "nsCOMPtr.h"
 #include "nsIRunnable.h"
 #include "mozilla/Atomics.h"
+#include "mozilla/Monitor.h"
 #include "gtest/gtest.h"
 
 class Task final : public nsIRunnable
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   explicit Task(int i) : mIndex(i) {}
@@ -53,8 +54,68 @@ TEST(ThreadPool, Main)
     EXPECT_TRUE(task);
 
     pool->Dispatch(task, NS_DISPATCH_NORMAL);
   }
 
   pool->Shutdown();
   EXPECT_EQ(Task::sCount, 100);
 }
+
+TEST(ThreadPool, Parallelism)
+{
+  nsCOMPtr<nsIThreadPool> pool = do_CreateInstance(NS_THREADPOOL_CONTRACTID);
+  EXPECT_TRUE(pool);
+
+  // Dispatch and sleep to ensure we have an idle thread
+  nsCOMPtr<nsIRunnable> r0 = new nsRunnable();
+  pool->Dispatch(r0, NS_DISPATCH_SYNC);
+  PR_Sleep(PR_SecondsToInterval(2));
+
+  class Runnable1 : public nsRunnable {
+  public:
+    Runnable1(Monitor& aMonitor, bool& aDone)
+      : mMonitor(aMonitor), mDone(aDone) {}
+
+    NS_IMETHOD Run() override {
+      MonitorAutoLock mon(mMonitor);
+      if (!mDone) {
+        // Wait for a reasonable timeout since we don't want to block gtests
+        // forever should any regression happen.
+        mon.Wait(PR_SecondsToInterval(300));
+      }
+      EXPECT_TRUE(mDone);
+      return NS_OK;
+    }
+  private:
+    Monitor& mMonitor;
+    bool& mDone;
+  };
+
+  class Runnable2 : public nsRunnable {
+  public:
+    Runnable2(Monitor& aMonitor, bool& aDone)
+      : mMonitor(aMonitor), mDone(aDone) {}
+
+    NS_IMETHOD Run() override {
+      MonitorAutoLock mon(mMonitor);
+      mDone = true;
+      mon.NotifyAll();
+      return NS_OK;
+    }
+  private:
+    Monitor& mMonitor;
+    bool& mDone;
+  };
+
+  // Dispatch 2 events in a row. Since we are still within the thread limit,
+  // We should wake up the idle thread and spawn a new thread so these 2 events
+  // can run in parallel. We will time out if r1 and r2 run in sequence for r1
+  // won't finish until r2 finishes.
+  Monitor mon("ThreadPool::Parallelism");
+  bool done = false;
+  nsCOMPtr<nsIRunnable> r1 = new Runnable1(mon, done);
+  nsCOMPtr<nsIRunnable> r2 = new Runnable2(mon, done);
+  pool->Dispatch(r1, NS_DISPATCH_NORMAL);
+  pool->Dispatch(r2, NS_DISPATCH_NORMAL);
+
+  pool->Shutdown();
+}