Bug 1361259. P4 - enforce copy in NonExclusive mode for each listener must get a copy. r=gerald
authorJW Wang <jwwang@mozilla.com>
Fri, 28 Apr 2017 17:56:57 +0800
changeset 355992 d0d6b7a2b75d1bf4559534c9f1551510efc977bd
parent 355991 cf5321dca675249a420ad59b2301a9890f74bd9c
child 355993 f79e3e648100b57899044227624e7f5d874664ab
push id31754
push userkwierso@gmail.com
push dateWed, 03 May 2017 00:28:51 +0000
treeherdermozilla-central@5eaf2d70eded [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgerald
bugs1361259
milestone55.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 1361259. P4 - enforce copy in NonExclusive mode for each listener must get a copy. r=gerald MozReview-Commit-ID: Mqt0N2erP6
dom/media/MediaEventSource.h
dom/media/gtest/TestMediaEventSource.cpp
--- a/dom/media/MediaEventSource.h
+++ b/dom/media/MediaEventSource.h
@@ -400,17 +400,18 @@ using MediaEventSourceExc =
  * and event publisher. Mostly used as a member variable to publish events
  * to the listeners.
  */
 template <typename... Es>
 class MediaEventProducer : public MediaEventSource<Es...> {
 public:
   template <typename... Ts>
   void Notify(Ts&&... aEvents) {
-    this->NotifyInternal(Forward<Ts>(aEvents)...);
+    // Pass lvalues to prevent move in NonExclusive mode.
+    this->NotifyInternal(aEvents...);
   }
 };
 
 /**
  * Specialization for void type. A dummy bool is passed to NotifyInternal
  * since there is no way to pass a void value.
  */
 template <>
--- a/dom/media/gtest/TestMediaEventSource.cpp
+++ b/dom/media/gtest/TestMediaEventSource.cpp
@@ -330,8 +330,47 @@ TEST(MediaEventSource, MoveOnly)
   // It is an error to pass an lvalue which is move-only.
   // UniquePtr<int> event(new int(30));
   // source.Notify(event);
 
   queue->BeginShutdown();
   queue->AwaitShutdownAndIdle();
   listener.Disconnect();
 }
+
+struct RefCounter
+{
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCounter)
+  explicit RefCounter(int aVal) : mVal(aVal) { }
+  int mVal;
+private:
+  ~RefCounter() { }
+};
+
+/*
+ * Test we should copy instead of move in NonExclusive mode
+ * for each listener must get a copy.
+ */
+TEST(MediaEventSource, NoMove)
+{
+  RefPtr<TaskQueue> queue = new TaskQueue(
+    GetMediaThreadPool(MediaThreadType::PLAYBACK));
+
+  MediaEventProducer<RefPtr<RefCounter>> source;
+
+  auto func1 = [] (RefPtr<RefCounter>&& aEvent) {
+    EXPECT_EQ(aEvent->mVal, 20);
+  };
+  auto func2 = [] (RefPtr<RefCounter>&& aEvent) {
+    EXPECT_EQ(aEvent->mVal, 20);
+  };
+  MediaEventListener listener1 = source.Connect(queue, func1);
+  MediaEventListener listener2 = source.Connect(queue, func2);
+
+  // We should copy this rvalue instead of move it in NonExclusive mode.
+  RefPtr<RefCounter> val = new RefCounter(20);
+  source.Notify(Move(val));
+
+  queue->BeginShutdown();
+  queue->AwaitShutdownAndIdle();
+  listener1.Disconnect();
+  listener2.Disconnect();
+}