Commit 314619d1 authored by Andreas Pehrson's avatar Andreas Pehrson
Browse files

Bug 1826530 - Implement MessagePumpForNonMainUIThreads for mac....

Bug 1826530 - Implement MessagePumpForNonMainUIThreads for mac. r=xpcom-reviewers,ipc-reviewers,mstange,nika

The MessagePump implemented here is a MessagePumpCFRunLoopBase that also handles
xpcom events.

Differential Revision: https://phabricator.services.mozilla.com/D175101
parent 92e5f593
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -250,12 +250,11 @@ MessageLoop::MessageLoop(Type type, nsISerialEventTarget* aEventTarget)
    case TYPE_MOZILLA_NONMAINTHREAD:
      pump_ = new mozilla::ipc::MessagePumpForNonMainThreads(aEventTarget);
      return;
#if defined(OS_WIN)
#if defined(OS_WIN) || defined(OS_MACOSX)
    case TYPE_MOZILLA_NONMAINUITHREAD:
      pump_ = new mozilla::ipc::MessagePumpForNonMainUIThreads(aEventTarget);
      return;
#endif
#if defined(MOZ_WIDGET_ANDROID)
#elif defined(MOZ_WIDGET_ANDROID)
    case TYPE_MOZILLA_ANDROID_UI:
      MOZ_RELEASE_ASSERT(aEventTarget);
      pump_ = new mozilla::ipc::MessagePumpForAndroidUI(aEventTarget);
+38 −4
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@
#include "base/message_pump_default.h"
#if defined(XP_WIN)
#  include "base/message_pump_win.h"
#elif defined(XP_MACOSX)
#  include "base/message_pump_mac.h"
#endif

#include "base/time.h"
@@ -90,8 +92,7 @@ class MessagePumpForNonMainThreads final : public MessagePump {
};

#if defined(XP_WIN)
// Extends the TYPE_UI message pump to process xpcom events. Currently only
// implemented for Win.
// Extends the TYPE_UI message pump to process xpcom events.
class MessagePumpForNonMainUIThreads final : public base::MessagePumpForUI,
                                             public nsIThreadObserver {
 public:
@@ -99,7 +100,7 @@ class MessagePumpForNonMainUIThreads final : public base::MessagePumpForUI,
  NS_DECL_NSITHREADOBSERVER

 public:
  explicit MessagePumpForNonMainUIThreads(nsIEventTarget* aEventTarget)
  explicit MessagePumpForNonMainUIThreads(nsISerialEventTarget* aEventTarget)
      : mInWait(false), mWaitLock("mInWait") {}

  // The main run loop for this thread.
@@ -131,7 +132,40 @@ class MessagePumpForNonMainUIThreads final : public base::MessagePumpForUI,
  bool mInWait MOZ_GUARDED_BY(mWaitLock);
  mozilla::Mutex mWaitLock;
};
#endif  // defined(XP_WIN)
#elif defined(XP_MACOSX)
// Extends the CFRunLoopBase message pump to process xpcom events. Based on
// MessagePumpNSRunLoop.
class MessagePumpForNonMainUIThreads final
    : public base::MessagePumpCFRunLoopBase,
      public nsIThreadObserver {
 public:
  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_NSITHREADOBSERVER

 public:
  explicit MessagePumpForNonMainUIThreads(nsISerialEventTarget* aEventTarget);

  void DoRun(base::MessagePump::Delegate* aDelegate) override;
  void Quit() override;

  nsISerialEventTarget* GetXPCOMThread() override { return mEventTarget; }

 private:
  ~MessagePumpForNonMainUIThreads();

  nsISerialEventTarget* mEventTarget;

  // A source that doesn't do anything but provide something signalable
  // attached to the run loop.  This source will be signalled when Quit
  // is called, to cause the loop to wake up so that it can stop.
  CFRunLoopSourceRef quit_source_;

  // False after Quit is called.
  bool keep_running_;

  DISALLOW_COPY_AND_ASSIGN(MessagePumpForNonMainUIThreads);
};
#endif  // defined(XP_MACOSX)

#if defined(MOZ_WIDGET_ANDROID)
/*`
+95 −0
Original line number Diff line number Diff line
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "MessagePump.h"

#include <Foundation/Foundation.h>

#include "base/scoped_nsautorelease_pool.h"
#include "mozilla/ProfilerMarkers.h"
#include "nsISupportsImpl.h"

using namespace mozilla::ipc;

static void NoOp(void* info) {}

NS_IMPL_ADDREF_INHERITED(MessagePumpForNonMainUIThreads, MessagePump)
NS_IMPL_RELEASE_INHERITED(MessagePumpForNonMainUIThreads, MessagePump)
NS_IMPL_QUERY_INTERFACE(MessagePumpForNonMainUIThreads, nsIThreadObserver)

MessagePumpForNonMainUIThreads::MessagePumpForNonMainUIThreads(nsISerialEventTarget* aEventTarget)
    : mEventTarget(aEventTarget), keep_running_(true) {
  MOZ_ASSERT(mEventTarget);
  CFRunLoopSourceContext source_context = CFRunLoopSourceContext();
  source_context.perform = NoOp;
  quit_source_ = CFRunLoopSourceCreate(nullptr,  // allocator
                                       0,        // priority
                                       &source_context);
  CFRunLoopAddSource(run_loop(), quit_source_, kCFRunLoopCommonModes);
}

MessagePumpForNonMainUIThreads::~MessagePumpForNonMainUIThreads() {
  CFRunLoopRemoveSource(run_loop(), quit_source_, kCFRunLoopCommonModes);
  CFRelease(quit_source_);
}

void MessagePumpForNonMainUIThreads::DoRun(base::MessagePump::Delegate* aDelegate) {
  // If this is a chromium thread and no nsThread is associated with it, this call will create a
  // new nsThread.
  nsIThread* thread = NS_GetCurrentThread();
  MOZ_ASSERT(thread);

  // Set the main thread observer so we can wake up when xpcom events need to get processed.
  nsCOMPtr<nsIThreadInternal> ti(do_QueryInterface(thread));
  MOZ_ASSERT(ti);
  ti->SetObserver(this);

  base::ScopedNSAutoreleasePool autoReleasePool;

  while (keep_running_) {
    // Drain the xpcom event loop first.
    if (NS_ProcessNextEvent(nullptr, false)) {
      continue;
    }

    autoReleasePool.Recycle();

    if (!keep_running_) {
      break;
    }

    // Now process the CFRunLoop. It exits after running once.
    // NSRunLoop manages autorelease pools itself.
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
  }

  ti->SetObserver(nullptr);
  keep_running_ = true;
}

void MessagePumpForNonMainUIThreads::Quit() {
  keep_running_ = false;
  CFRunLoopSourceSignal(quit_source_);
  CFRunLoopWakeUp(run_loop());
}

NS_IMETHODIMP MessagePumpForNonMainUIThreads::OnDispatchedEvent() {
  // ScheduleWork will signal an input source to the run loop, making it exit so it can process the
  // xpcom event.
  ScheduleWork();
  return NS_OK;
}

NS_IMETHODIMP
MessagePumpForNonMainUIThreads::OnProcessNextEvent(nsIThreadInternal* thread, bool mayWait) {
  return NS_OK;
}

NS_IMETHODIMP
MessagePumpForNonMainUIThreads::AfterProcessNextEvent(nsIThreadInternal* thread,
                                                      bool eventWasProcessed) {
  return NS_OK;
}
+2 −0
Original line number Diff line number Diff line
@@ -221,6 +221,8 @@ else:

if CONFIG["OS_ARCH"] == "WINNT":
    UNIFIED_SOURCES += ["MessagePump_windows.cpp"]
elif CONFIG["OS_ARCH"] == "Darwin":
    UNIFIED_SOURCES += ["MessagePump_mac.mm"]
elif CONFIG["OS_TARGET"] == "Android":
    UNIFIED_SOURCES += ["MessagePump_android.cpp"]

+1 −1
Original line number Diff line number Diff line
@@ -383,7 +383,7 @@ TEST(Threads, UnregisteredShutdownTask)
  thread->Shutdown();
}

#if defined(XP_WIN) || !defined(DEBUG)
#if (defined(XP_WIN) || !defined(DEBUG)) && !defined(XP_MACOSX)
TEST(Threads, OptionsIsUiThread)
{
  // On Windows, test that the isUiThread flag results in a GUI thread.
Loading