Bug 1161405. Part 2 - test case for parallelism of the thread pool. r=nfroyd.
authorJW Wang <jwwang@mozilla.com>
Sat, 09 May 2015 07:32:27 +0800
changeset 243327 a4700f2b25fca71e6e35a0e4c1c09897b8ad5ad8
parent 243326 eac3aa030c4e6ae109f16b342e3c4440d2cc5651
child 243328 651e2c2015f61b930e1fa36b6fa2457c51f99f41
push id28738
push usercbook@mozilla.com
push dateTue, 12 May 2015 14:11:31 +0000
treeherderautoland@bedce1b405a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnfroyd
bugs1161405
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1161405. Part 2 - test case for parallelism of the thread pool. r=nfroyd.
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();
+}