6#if defined(DART_HOST_OS_MACOS)
12#include <CoreServices/CoreServices.h>
25#ifndef MAC_OS_X_VERSION_10_7
26enum { kFSEventStreamCreateFlagFileEvents = 0x00000010 };
28 kFSEventStreamEventFlagItemCreated = 0x00000100,
29 kFSEventStreamEventFlagItemRemoved = 0x00000200,
30 kFSEventStreamEventFlagItemInodeMetaMod = 0x00000400,
31 kFSEventStreamEventFlagItemRenamed = 0x00000800,
32 kFSEventStreamEventFlagItemModified = 0x00001000,
33 kFSEventStreamEventFlagItemFinderInfoMod = 0x00002000,
34 kFSEventStreamEventFlagItemChangeOwner = 0x00004000,
35 kFSEventStreamEventFlagItemXattrMod = 0x00008000,
36 kFSEventStreamEventFlagItemIsFile = 0x00010000,
37 kFSEventStreamEventFlagItemIsDir = 0x00020000,
38 kFSEventStreamEventFlagItemIsSymlink = 0x00040000
54class FSEventsWatcher {
58 Node(FSEventsWatcher* watcher,
64 base_path_length_(strlen(base_path)),
65 path_ref_(CFStringCreateWithCString(nullptr,
67 kCFStringEncodingUTF8)),
70 recursive_(recursive),
86 void set_ref(FSEventStreamRef ref) { ref_ = ref; }
89 FSEventStreamContext context;
90 memset(&context, 0,
sizeof(context));
91 context.info =
reinterpret_cast<void*
>(
this);
92 context.release = [](
const void*
info) {
93 delete static_cast<const Node*
>(
info);
95 CFArrayRef array = CFArrayCreate(
96 nullptr,
reinterpret_cast<const void**
>(&path_ref_), 1,
nullptr);
97 FSEventStreamRef ref = FSEventStreamCreate(
98 nullptr, Callback, &context, array, kFSEventStreamEventIdSinceNow,
99 0.10, kFSEventStreamCreateFlagFileEvents);
104 FSEventStreamScheduleWithRunLoop(ref_, watcher_->run_loop_,
105 kCFRunLoopDefaultMode);
107 FSEventStreamStart(ref_);
108 FSEventStreamFlushSync(ref_);
112 FSEventStreamStop(ref_);
113 FSEventStreamInvalidate(ref_);
114 FSEventStreamRelease(ref_);
117 FSEventsWatcher* watcher()
const {
return watcher_; }
118 intptr_t base_path_length()
const {
return base_path_length_; }
119 int read_fd()
const {
return read_fd_; }
120 int write_fd()
const {
return write_fd_; }
121 bool recursive()
const {
return recursive_; }
124 FSEventsWatcher* watcher_;
125 intptr_t base_path_length_;
126 CFStringRef path_ref_;
130 FSEventStreamRef ref_;
135 FSEventsWatcher() : run_loop_(0) { Start(); }
138 Thread::Start(
"dart:io FileWatcher", Run,
reinterpret_cast<uword>(
this));
140 while (run_loop_ ==
nullptr) {
141 monitor_.Wait(Monitor::kNoTimeout);
146 static void Run(uword arg) {
147 FSEventsWatcher* watcher =
reinterpret_cast<FSEventsWatcher*
>(arg);
149 watcher->threadId_ = Thread::GetCurrentThreadId();
150 watcher->run_loop_ = CFRunLoopGetCurrent();
151 CFRetain(watcher->run_loop_);
154 watcher->monitor().Enter();
155 watcher->monitor().Notify();
156 watcher->monitor().Exit();
158 CFRunLoopTimerRef timer =
159 CFRunLoopTimerCreate(
nullptr, CFAbsoluteTimeGetCurrent() + 1, 1, 0, 0,
160 TimerCallback,
nullptr);
161 CFRunLoopAddTimer(watcher->run_loop_, timer, kCFRunLoopCommonModes);
166 CFRelease(watcher->run_loop_);
167 watcher->monitor_.Enter();
168 watcher->run_loop_ =
nullptr;
169 watcher->monitor_.Notify();
170 watcher->monitor_.Exit();
175 CFRunLoopTimerContext context;
176 memset(&context, 0,
sizeof(context));
178 CFRunLoopTimerRef timer =
179 CFRunLoopTimerCreate(
nullptr, 0, 0, 0, 0, StopCallback, &context);
180 CFRunLoopAddTimer(run_loop_, timer, kCFRunLoopCommonModes);
183 while (run_loop_ !=
nullptr) {
184 monitor_.Wait(Monitor::kNoTimeout);
189 static void StopCallback(CFRunLoopTimerRef timer,
void*
info) {
190 FSEventsWatcher* watcher =
reinterpret_cast<FSEventsWatcher*
>(
info);
191 ASSERT(Thread::Compare(watcher->threadId_, Thread::GetCurrentThreadId()));
192 CFRunLoopStop(watcher->run_loop_);
195 ~FSEventsWatcher() { Stop(); }
197 Monitor& monitor() {
return monitor_; }
199 bool has_run_loop()
const {
return run_loop_ !=
nullptr; }
201 static void TimerCallback(CFRunLoopTimerRef timer,
void* context) {
205 Node* AddPath(
const char* path,
int events,
bool recursive) {
208 FDUtils::SetNonBlocking(fds[0]);
209 FDUtils::SetBlocking(fds[1]);
212 realpath(path, base_path);
214 return new Node(
this, base_path, fds[0], fds[1], recursive);
218 static void Callback(ConstFSEventStreamRef ref,
222 const FSEventStreamEventFlags event_flags[],
223 const FSEventStreamEventId event_ids[]) {
224 if (FileSystemWatcher::delayed_filewatch_callback()) {
227 TimerUtils::Sleep(1000 );
229 Node* node =
static_cast<Node*
>(client);
231 ASSERT(Thread::Compare(node->watcher()->threadId_,
232 Thread::GetCurrentThreadId()));
233 for (
size_t i = 0; i < num_events; i++) {
234 char*
path =
reinterpret_cast<char**
>(event_paths)[i];
237 File::GetType(
nullptr, path,
false) != File::kDoesNotExist;
238 path += node->base_path_length();
240 if (path[0] !=
'\0') {
243 if (!node->recursive() && (strstr(path,
"/") !=
nullptr)) {
246 event.data.flags = event_flags[i];
247 memmove(
event.data.path, path, strlen(path) + 1);
253 CFRunLoopRef run_loop_;
259#define kCFCoreFoundationVersionNumber10_7 635.00
261 return kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber10_7;
265 return reinterpret_cast<intptr_t
>(
new FSEventsWatcher());
269 delete reinterpret_cast<FSEventsWatcher*
>(
id);
277 FSEventsWatcher* watcher =
reinterpret_cast<FSEventsWatcher*
>(
id);
278 return reinterpret_cast<intptr_t
>(watcher->AddPath(path, events, recursive));
283 reinterpret_cast<FSEventsWatcher::Node*
>(path_id)->Stop();
287 return reinterpret_cast<FSEventsWatcher::Node*
>(path_id)->read_fd();
293 int count = avail /
sizeof(FSEvent);
299 for (
int i = 0; i <
count; i++) {
304 size_t path_len = strlen(
e.data.path);
308 if ((
flags & kFSEventStreamEventFlagItemRenamed) != 0) {
316 if ((
flags & kFSEventStreamEventFlagItemModified) != 0) {
319 if ((
flags & kFSEventStreamEventFlagItemXattrMod) != 0) {
322 if ((
flags & kFSEventStreamEventFlagItemCreated) != 0) {
325 if ((
flags & kFSEventStreamEventFlagItemIsDir) != 0) {
328 if ((
flags & kFSEventStreamEventFlagItemRemoved) != 0) {
339 reinterpret_cast<uint8_t*
>(
e.data.path), path_len);
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static bool read(SkStream *stream, void *buffer, size_t amount)
#define RELEASE_ASSERT(cond)
static Dart_Handle NewDartOSError()
static intptr_t AvailableBytes(intptr_t fd)
static intptr_t GetSocketId(intptr_t id, intptr_t path_id)
static void Close(intptr_t id)
static void UnwatchPath(intptr_t id, intptr_t path_id)
static bool IsSupported()
static Dart_Handle ReadEvents(intptr_t id, intptr_t path_id)
static intptr_t WatchPath(intptr_t id, Namespace *namespc, const char *path, int events, bool recursive)
struct _Dart_Handle * Dart_Handle
FlutterSemanticsFlag flags
DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value)
DART_EXPORT Dart_Handle Dart_NewStringFromUTF8(const uint8_t *utf8_array, intptr_t length)
DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list, intptr_t index, Dart_Handle value)
DART_EXPORT Dart_Handle Dart_NewBoolean(bool value)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT Dart_Handle Dart_NewList(intptr_t length)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
std::function< void(MTLRenderPipelineDescriptor *)> Callback
#define VOID_NO_RETRY_EXPECTED(expression)
#define TEMP_FAILURE_RETRY(expression)
void write(SkWStream *wStream, const T &text)