Skip to content

Commit

Permalink
Partially port FML to Windows. (flutter#3562)
Browse files Browse the repository at this point in the history
* Partially port FML to Windows.

* Adds a message loop impl for Windows
* Ports `thread.cc` to Windows

All FML unittests are now passing on Windows.

FML as a whole does not compile on windows yet because `mapping.cc` imports `sys/mman.h`, which is not available on Windows and the replacement API for memory-mapped files is very different on Windows, see https://msdn.microsoft.com/en-us/library/windows/desktop/aa366556%28v=vs.85%29.aspx.

* update licenses

* review comments
  • Loading branch information
goderbauer authored Apr 4, 2017
1 parent 5d9a642 commit 772a0db
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 4 deletions.
7 changes: 7 additions & 0 deletions fml/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ source_set("fml") {
"platform/linux/timerfd.h",
]
}

if (is_win) {
sources += [
"platform/win/message_loop_win.cc",
"platform/win/message_loop_win.h",
]
}
}

executable("fml_unittests") {
Expand Down
5 changes: 5 additions & 0 deletions fml/message_loop_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ using PlatformMessageLoopImpl = fml::MessageLoopAndroid;
#include "flutter/fml/platform/linux/message_loop_linux.h"
using PlatformMessageLoopImpl = fml::MessageLoopLinux;

#elif OS_WIN

#include "flutter/fml/platform/win/message_loop_win.h"
using PlatformMessageLoopImpl = fml::MessageLoopWin;

#else

#error This platform does not have a message loop implementation.
Expand Down
6 changes: 3 additions & 3 deletions fml/message_loop_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ TEST(MessageLoop, TIME_SENSITIVE(MultipleDelayedTasksWithIncreasingDeltas)) {
for (int target_ms = 0 + 2; target_ms < count + 2; target_ms++) {
auto begin = ftl::TimePoint::Now();
loop.GetTaskRunner()->PostDelayedTask(
[begin, target_ms, &checked]() {
[begin, target_ms, &checked, count]() {
auto delta = ftl::TimePoint::Now() - begin;
auto ms = delta.ToMillisecondsF();
ASSERT_GE(ms, target_ms - 2);
Expand All @@ -217,10 +217,10 @@ TEST(MessageLoop, TIME_SENSITIVE(MultipleDelayedTasksWithDecreasingDeltas)) {
std::thread thread([&checked, count]() {
fml::MessageLoop::EnsureInitializedForCurrentThread();
auto& loop = fml::MessageLoop::GetCurrent();
for (int target_ms = count + 2; target_ms >= 0 + 2; target_ms--) {
for (int target_ms = count + 2; target_ms > 0 + 2; target_ms--) {
auto begin = ftl::TimePoint::Now();
loop.GetTaskRunner()->PostDelayedTask(
[begin, target_ms, &checked]() {
[begin, target_ms, &checked, count]() {
auto delta = ftl::TimePoint::Now() - begin;
auto ms = delta.ToMillisecondsF();
ASSERT_GE(ms, target_ms - 2);
Expand Down
39 changes: 39 additions & 0 deletions fml/platform/win/message_loop_win.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/fml/platform/win/message_loop_win.h"

namespace fml {

MessageLoopWin::MessageLoopWin()
: timer_(CreateWaitableTimer(NULL, FALSE, NULL)) {
FTL_CHECK(timer_.is_valid());
}

MessageLoopWin::~MessageLoopWin() = default;

void MessageLoopWin::Run() {
running_ = true;

while (running_) {
FTL_CHECK(WaitForSingleObject(timer_.get(), INFINITE) == 0);
RunExpiredTasksNow();
}
}

void MessageLoopWin::Terminate() {
running_ = false;
WakeUp(ftl::TimePoint::Now());
}

void MessageLoopWin::WakeUp(ftl::TimePoint time_point) {
LARGE_INTEGER due_time = {0};
ftl::TimePoint now = ftl::TimePoint::Now();
if (time_point > now) {
due_time.QuadPart = (time_point - now).ToNanoseconds() / -100;
}
FTL_CHECK(SetWaitableTimer(timer_.get(), &due_time, 0, NULL, NULL, FALSE));
}

} // namespace fml
46 changes: 46 additions & 0 deletions fml/platform/win/message_loop_win.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FLUTTER_FML_PLATFORM_WIN_MESSAGE_LOOP_WIN_H_
#define FLUTTER_FML_PLATFORM_WIN_MESSAGE_LOOP_WIN_H_

#include <atomic>

#include <windows.h>

#include "flutter/fml/message_loop_impl.h"
#include "lib/ftl/macros.h"
#include "lib/ftl/memory/unique_object.h"

namespace fml {

class MessageLoopWin : public MessageLoopImpl {
private:
struct UniqueHandleTraits {
static HANDLE InvalidValue() { return NULL; }
static bool IsValid(HANDLE value) { return value != NULL; }
static void Free(HANDLE value) { CloseHandle(value); }
};

bool running_;
ftl::UniqueObject<HANDLE, UniqueHandleTraits> timer_;

MessageLoopWin();

~MessageLoopWin() override;

void Run() override;

void Terminate() override;

void WakeUp(ftl::TimePoint time_point) override;

FRIEND_MAKE_REF_COUNTED(MessageLoopWin);
FRIEND_REF_COUNTED_THREAD_SAFE(MessageLoopWin);
FTL_DISALLOW_COPY_AND_ASSIGN(MessageLoopWin);
};

} // namespace fml

#endif // FLUTTER_FML_PLATFORM_GENERIC_MESSAGE_LOOP_GENERIC_H_
30 changes: 29 additions & 1 deletion fml/thread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@

#include "flutter/fml/thread.h"

#include "lib/ftl/build_config.h"

#if defined(OS_WIN)
#include <windows.h>
#else
#include <pthread.h>
#endif

#include <memory>
#include <string>

#include "flutter/fml/message_loop.h"
#include "lib/ftl/build_config.h"
#include "lib/ftl/synchronization/waitable_event.h"

namespace fml {
Expand Down Expand Up @@ -47,6 +52,18 @@ void Thread::Join() {
thread_->join();
}

#if defined(OS_WIN)
// The information on how to set the thread name comes from
// a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx
const DWORD kVCThreadNameException = 0x406D1388;
typedef struct tagTHREADNAME_INFO {
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#endif

void Thread::SetCurrentThreadName(const std::string& name) {
if (name == "") {
return;
Expand All @@ -55,6 +72,17 @@ void Thread::SetCurrentThreadName(const std::string& name) {
pthread_setname_np(name.c_str());
#elif OS_LINUX || OS_ANDROID
pthread_setname_np(pthread_self(), name.c_str());
#elif OS_WIN
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = name.c_str();
info.dwThreadID = GetCurrentThreadId();
info.dwFlags = 0;
__try {
RaiseException(kVCThreadNameException, 0, sizeof(info)/sizeof(DWORD),
reinterpret_cast<DWORD_PTR*>(&info));
} __except(EXCEPTION_CONTINUE_EXECUTION) {
}
#else
#error Unsupported Platform
#endif
Expand Down
2 changes: 2 additions & 0 deletions travis/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,8 @@ FILE: ../../../flutter/fml/platform/linux/message_loop_linux.h
FILE: ../../../flutter/fml/platform/linux/paths_linux.cc
FILE: ../../../flutter/fml/platform/linux/timerfd.cc
FILE: ../../../flutter/fml/platform/linux/timerfd.h
FILE: ../../../flutter/fml/platform/win/message_loop_win.cc
FILE: ../../../flutter/fml/platform/win/message_loop_win.h
FILE: ../../../flutter/fml/task_observer.h
FILE: ../../../flutter/fml/task_runner.cc
FILE: ../../../flutter/fml/task_runner.h
Expand Down

0 comments on commit 772a0db

Please sign in to comment.