Version 2.14.0-164.0.dev
Merge commit 'ed82bb6f4c5a90b81ff91052cdedc53817488b16' into 'dev'
diff --git a/runtime/bin/file_system_watcher_macos.cc b/runtime/bin/file_system_watcher_macos.cc
index b73c0d13..88d6986 100644
--- a/runtime/bin/file_system_watcher_macos.cc
+++ b/runtime/bin/file_system_watcher_macos.cc
@@ -82,81 +82,36 @@
void set_ref(FSEventStreamRef ref) { ref_ = ref; }
void Start() {
- // Schedule StartCallback to be executed in the RunLoop.
- CFRunLoopTimerContext context;
- memset(&context, 0, sizeof(context));
- context.info = this;
- CFRunLoopTimerRef timer =
- CFRunLoopTimerCreate(NULL, 0, 0, 0, 0, Node::StartCallback, &context);
- CFRunLoopAddTimer(watcher_->run_loop_, timer, kCFRunLoopCommonModes);
- CFRelease(timer);
- watcher_->monitor_.Enter();
- while (!ready_) {
- watcher_->monitor_.Wait(Monitor::kNoTimeout);
- }
- watcher_->monitor_.Exit();
- }
-
- static void StartCallback(CFRunLoopTimerRef timer, void* info) {
- Node* node = reinterpret_cast<Node*>(info);
- ASSERT(Thread::Compare(node->watcher_->threadId_,
- Thread::GetCurrentThreadId()));
FSEventStreamContext context;
memset(&context, 0, sizeof(context));
- context.info = reinterpret_cast<void*>(node);
+ context.info = reinterpret_cast<void*>(this);
CFArrayRef array = CFArrayCreate(
- NULL, reinterpret_cast<const void**>(&node->path_ref_), 1, NULL);
+ NULL, reinterpret_cast<const void**>(&path_ref_), 1, NULL);
FSEventStreamRef ref = FSEventStreamCreate(
NULL, Callback, &context, array, kFSEventStreamEventIdSinceNow, 0.10,
kFSEventStreamCreateFlagFileEvents);
CFRelease(array);
- node->set_ref(ref);
+ set_ref(ref);
+ ready_.store(true, std::memory_order_release);
- FSEventStreamScheduleWithRunLoop(node->ref_, node->watcher_->run_loop_,
+ FSEventStreamScheduleWithRunLoop(ref_, watcher_->run_loop_,
kCFRunLoopDefaultMode);
- FSEventStreamStart(node->ref_);
- FSEventStreamFlushSync(node->ref_);
-
- node->watcher_->monitor_.Enter();
- node->ready_ = true;
- node->watcher_->monitor_.Notify();
- node->watcher_->monitor_.Exit();
+ FSEventStreamStart(ref_);
+ FSEventStreamFlushSync(ref_);
}
void Stop() {
- // Schedule StopCallback to be executed in the RunLoop.
ASSERT(ready_);
- CFRunLoopTimerContext context;
- memset(&context, 0, sizeof(context));
- context.info = this;
- CFRunLoopTimerRef timer =
- CFRunLoopTimerCreate(NULL, 0, 0, 0, 0, StopCallback, &context);
- CFRunLoopAddTimer(watcher_->run_loop_, timer, kCFRunLoopCommonModes);
- CFRelease(timer);
- watcher_->monitor_.Enter();
- while (ready_) {
- watcher_->monitor_.Wait(Monitor::kNoTimeout);
- }
- watcher_->monitor_.Exit();
- }
-
- static void StopCallback(CFRunLoopTimerRef timer, void* info) {
- Node* node = reinterpret_cast<Node*>(info);
- ASSERT(Thread::Compare(node->watcher_->threadId_,
- Thread::GetCurrentThreadId()));
- FSEventStreamStop(node->ref_);
- FSEventStreamInvalidate(node->ref_);
- FSEventStreamRelease(node->ref_);
- node->watcher_->monitor_.Enter();
- node->ready_ = false;
- node->watcher_->monitor_.Notify();
- node->watcher_->monitor_.Exit();
+ FSEventStreamStop(ref_);
+ FSEventStreamInvalidate(ref_);
+ FSEventStreamRelease(ref_);
+ ready_.store(false, std::memory_order_release);
}
FSEventsWatcher* watcher() const { return watcher_; }
- bool ready() const { return ready_; }
+ bool ready() const { return ready_.load(std::memory_order_acquire); }
intptr_t base_path_length() const { return base_path_length_; }
int read_fd() const { return read_fd_; }
int write_fd() const { return write_fd_; }
@@ -164,7 +119,7 @@
private:
FSEventsWatcher* watcher_;
- bool ready_;
+ std::atomic<bool> ready_;
intptr_t base_path_length_;
CFStringRef path_ref_;
int read_fd_;
@@ -266,8 +221,6 @@
Node* node = reinterpret_cast<Node*>(client);
ASSERT(Thread::Compare(node->watcher()->threadId_,
Thread::GetCurrentThreadId()));
- // `ready` is set on same thread as this callback is invoked, so we don't
- // need to lock here.
if (!node->ready()) {
return;
}
diff --git a/tests/language/closure/tearoff_super_default_test.dart b/tests/language/closure/tearoff_super_default_test.dart
new file mode 100644
index 0000000..1e30932
--- /dev/null
+++ b/tests/language/closure/tearoff_super_default_test.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+class A1 {
+ final int _i1;
+ A1(this._i1);
+ toString() => 'A1($_i1)';
+
+ String foo(int i, [String s = 'A1.s']) => '$this.A1.foo($i, $s)';
+}
+
+class B1 extends A1 {
+ B1() : super(100);
+ toString() => 'B1($_i1)';
+
+ String foo(int i, [String s = 'B1.s']) => '$this.B1.foo($i, $s)';
+
+ String Function(int, [String]) getsuperfoo() => super.foo;
+ String callsuperfoo1(int i) => super.foo(i);
+ String callsuperfoo2(int i, String s) => super.foo(i, s);
+}
+
+class A2 {
+ final int _i2;
+ A2(this._i2);
+ toString() => 'A2($_i2)';
+
+ String foo(int i, [String s = 'A2.s']) => '$this.A2.foo($i, $s)';
+}
+
+class B2 extends A2 {
+ B2() : super(200);
+ toString() => 'B2($_i2)';
+
+ String foo(int i, [String s = 'B2.s']) => '$this.B2.foo($i, $s)';
+
+ String Function(int, [String]) getsuperfoo() => super.foo;
+ String callsuperfoo1(int i) => super.foo(i);
+ String callsuperfoo2(int i, String s) => super.foo(i, s);
+}
+
+void main() {
+ // The A1/B1 sequence and A2/B2 sequence do similar tests but in a different
+ // order. The super-getter is called first in ths A1/B1 sequence, but after
+ // the regular getters in the A2/B2 sequence.
+
+ // -------- A1/B1
+
+ final b1superfoo = B1().getsuperfoo();
+
+ Expect.equals('B1(100).A1.foo(50, A1.s)', b1superfoo(50));
+ Expect.equals('B1(100).A1.foo(51, xxxx)', b1superfoo(51, 'xxxx'));
+
+ final a1foo = A1(20).foo;
+ final b1foo = B1().foo;
+
+ Expect.equals('A1(20).A1.foo(52, A1.s)', a1foo(52));
+ Expect.equals('A1(20).A1.foo(53, xxxx)', a1foo(53, 'xxxx'));
+ Expect.equals('B1(100).B1.foo(54, B1.s)', b1foo(54));
+ Expect.equals('B1(100).B1.foo(55, xxxx)', b1foo(55, 'xxxx'));
+
+ Expect.equals('B1(100).A1.foo(56, A1.s)', B1().callsuperfoo1(56));
+ Expect.equals('B1(100).A1.foo(57, xxxx)', B1().callsuperfoo2(57, 'xxxx'));
+
+ // -------- A2/B2
+
+ final a2foo = A2(20).foo;
+ final b2foo = B2().foo;
+
+ Expect.equals('A2(20).A2.foo(60, A2.s)', a2foo(60));
+ Expect.equals('A2(20).A2.foo(61, xxxx)', a2foo(61, 'xxxx'));
+ Expect.equals('B2(200).B2.foo(62, B2.s)', b2foo(62));
+ Expect.equals('B2(200).B2.foo(63, xxxx)', b2foo(63, 'xxxx'));
+
+ Expect.equals('B2(200).A2.foo(64, A2.s)', B2().callsuperfoo1(64));
+ Expect.equals('B2(200).A2.foo(65, xxxx)', B2().callsuperfoo2(65, 'xxxx'));
+
+ final b2superfoo = B2().getsuperfoo();
+
+ Expect.equals('B2(200).A2.foo(66, A2.s)', b2superfoo(66));
+ Expect.equals('B2(200).A2.foo(67, xxxx)', b2superfoo(67, 'xxxx'));
+}
diff --git a/tools/VERSION b/tools/VERSION
index f039084..c387783 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 163
+PRERELEASE 164
PRERELEASE_PATCH 0
\ No newline at end of file