Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "platform/globals.h" | 5 #include "platform/globals.h" |
| 6 #if defined(TARGET_OS_MACOS) | 6 #if defined(TARGET_OS_MACOS) |
| 7 | 7 |
| 8 #include "bin/file_system_watcher.h" | 8 #include "bin/file_system_watcher.h" |
| 9 | 9 |
| 10 #include <errno.h> // NOLINT | 10 #include <errno.h> // NOLINT |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 48 uint32_t flags; | 48 uint32_t flags; |
| 49 char path[PATH_MAX]; | 49 char path[PATH_MAX]; |
| 50 } data; | 50 } data; |
| 51 uint8_t bytes[PATH_MAX + 8]; | 51 uint8_t bytes[PATH_MAX + 8]; |
| 52 }; | 52 }; |
| 53 | 53 |
| 54 class FSEventsWatcher { | 54 class FSEventsWatcher { |
| 55 public: | 55 public: |
| 56 class Node { | 56 class Node { |
| 57 public: | 57 public: |
| 58 Node(FSEventsWatcher* watcher, intptr_t base_path_length, int read_fd, | 58 Node(FSEventsWatcher* watcher, char* base_path, int read_fd, |
| 59 int write_fd, bool recursive) | 59 int write_fd, bool recursive) |
| 60 : watcher_(watcher), | 60 : watcher_(watcher), |
| 61 ready_(false), | 61 ready_(false), |
| 62 base_path_length_(base_path_length), | 62 base_path_length_(strlen(base_path)), |
| 63 path_ref_(CFStringCreateWithCString( | |
| 64 NULL, base_path, kCFStringEncodingUTF8)), | |
| 63 read_fd_(read_fd), | 65 read_fd_(read_fd), |
| 64 write_fd_(write_fd), | 66 write_fd_(write_fd), |
| 65 recursive_(recursive), | 67 recursive_(recursive), |
| 66 ref_(NULL) {} | 68 ref_(NULL) { |
|
Søren Gjesse
2014/02/07 10:20:02
Please keep this code in the Start method and call
Anders Johnsen
2014/02/07 12:49:24
Done.
| |
| 69 CFRunLoopTimerContext context; | |
| 70 memset(&context, 0, sizeof(context)); | |
| 71 context.info = this; | |
|
Søren Gjesse
2014/02/07 10:20:02
Please add a comment that this is scheduling Start
Anders Johnsen
2014/02/07 12:49:24
Done.
| |
| 72 CFRunLoopTimerRef timer = CFRunLoopTimerCreate( | |
| 73 NULL, 0, 0, 0, 0, Node::StartCallback, &context); | |
| 74 CFRunLoopAddTimer(watcher_->run_loop_, timer, kCFRunLoopCommonModes); | |
| 75 CFRelease(timer); | |
| 76 watcher_->monitor_.Enter(); | |
| 77 while (!ready_) { | |
| 78 watcher_->monitor_.Wait(Monitor::kNoTimeout); | |
| 79 } | |
| 80 watcher_->monitor_.Exit(); | |
| 81 } | |
| 67 | 82 |
| 68 ~Node() { | 83 ~Node() { |
|
Søren Gjesse
2014/02/07 10:20:02
I am not a great fan of placing this code in the d
Anders Johnsen
2014/02/07 12:49:24
Done.
| |
| 84 ASSERT(ready_); | |
| 85 CFRunLoopTimerContext context; | |
| 86 memset(&context, 0, sizeof(context)); | |
| 87 context.info = this; | |
|
Søren Gjesse
2014/02/07 10:20:02
Please add a comment that this is scheduling StopC
Anders Johnsen
2014/02/07 12:49:24
Done.
| |
| 88 CFRunLoopTimerRef timer = CFRunLoopTimerCreate( | |
| 89 NULL, 0, 0, 0, 0, StopCallback, &context); | |
| 90 CFRunLoopAddTimer(watcher_->run_loop_, timer, kCFRunLoopCommonModes); | |
| 91 watcher_->monitor_.Enter(); | |
| 92 while (ready_) { | |
| 93 watcher_->monitor_.Wait(Monitor::kNoTimeout); | |
| 94 } | |
| 95 watcher_->monitor_.Exit(); | |
| 69 close(write_fd_); | 96 close(write_fd_); |
| 97 CFRelease(path_ref_); | |
| 70 } | 98 } |
| 71 | 99 |
| 72 void set_ref(FSEventStreamRef ref) { | 100 void set_ref(FSEventStreamRef ref) { |
| 73 ref_ = ref; | 101 ref_ = ref; |
| 74 } | 102 } |
| 75 | 103 |
| 76 static void StartCallback(CFRunLoopTimerRef timer, void* info) { | 104 static void StartCallback(CFRunLoopTimerRef timer, void* info) { |
| 77 Node* node = reinterpret_cast<Node*>(info); | 105 Node* node = reinterpret_cast<Node*>(info); |
| 106 | |
| 107 FSEventStreamContext context; | |
| 108 context.version = 0; | |
| 109 context.info = reinterpret_cast<void*>(node); | |
| 110 context.retain = NULL; | |
| 111 context.release = NULL; | |
| 112 context.copyDescription = NULL; | |
| 113 CFArrayRef array = CFArrayCreate( | |
| 114 NULL, reinterpret_cast<const void**>(&node->path_ref_), 1, NULL); | |
| 115 FSEventStreamRef ref = FSEventStreamCreate( | |
| 116 NULL, | |
| 117 Callback, | |
| 118 &context, | |
| 119 array, | |
| 120 kFSEventStreamEventIdSinceNow, | |
| 121 0.10, | |
| 122 kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents); | |
| 123 CFRelease(array); | |
| 124 | |
| 125 node->set_ref(ref); | |
| 126 | |
| 78 FSEventStreamScheduleWithRunLoop( | 127 FSEventStreamScheduleWithRunLoop( |
| 79 node->ref_, | 128 node->ref_, |
| 80 node->watcher_->run_loop_, | 129 node->watcher_->run_loop_, |
| 81 kCFRunLoopDefaultMode); | 130 kCFRunLoopDefaultMode); |
| 131 | |
| 82 FSEventStreamStart(node->ref_); | 132 FSEventStreamStart(node->ref_); |
| 83 FSEventStreamFlushSync(node->ref_); | 133 FSEventStreamFlushSync(node->ref_); |
| 134 | |
| 84 node->watcher_->monitor_.Enter(); | 135 node->watcher_->monitor_.Enter(); |
| 85 node->ready_ = true; | 136 node->ready_ = true; |
| 86 node->watcher_->monitor_.Notify(); | 137 node->watcher_->monitor_.Notify(); |
| 87 node->watcher_->monitor_.Exit(); | 138 node->watcher_->monitor_.Exit(); |
| 88 } | 139 } |
| 89 | 140 |
| 90 void Start() { | |
| 91 ASSERT(!ready_); | |
| 92 CFRunLoopTimerContext context; | |
| 93 memset(&context, 0, sizeof(context)); | |
| 94 context.info = this; | |
| 95 CFRunLoopTimerRef timer = CFRunLoopTimerCreate( | |
| 96 NULL, 0, 0, 0, 0, StartCallback, &context); | |
| 97 CFRunLoopAddTimer(watcher_->run_loop_, timer, kCFRunLoopCommonModes); | |
| 98 watcher_->monitor_.Enter(); | |
| 99 while (!ready_) { | |
| 100 watcher_->monitor_.Wait(Monitor::kNoTimeout); | |
| 101 } | |
| 102 watcher_->monitor_.Exit(); | |
| 103 } | |
| 104 | |
| 105 static void StopCallback(CFRunLoopTimerRef timer, void* info) { | 141 static void StopCallback(CFRunLoopTimerRef timer, void* info) { |
| 106 Node* node = reinterpret_cast<Node*>(info); | 142 Node* node = reinterpret_cast<Node*>(info); |
| 107 FSEventStreamStop(node->ref_); | 143 FSEventStreamStop(node->ref_); |
| 108 FSEventStreamInvalidate(node->ref_); | 144 FSEventStreamInvalidate(node->ref_); |
| 109 FSEventStreamRelease(node->ref_); | 145 FSEventStreamRelease(node->ref_); |
| 110 node->watcher_->monitor_.Enter(); | 146 node->watcher_->monitor_.Enter(); |
| 111 node->ready_ = false; | 147 node->ready_ = false; |
| 112 node->watcher_->monitor_.Notify(); | 148 node->watcher_->monitor_.Notify(); |
| 113 node->watcher_->monitor_.Exit(); | 149 node->watcher_->monitor_.Exit(); |
| 114 } | 150 } |
| 115 | 151 |
| 116 void Stop() { | |
| 117 ASSERT(ready_); | |
| 118 CFRunLoopTimerContext context; | |
| 119 memset(&context, 0, sizeof(context)); | |
| 120 context.info = this; | |
| 121 CFRunLoopTimerRef timer = CFRunLoopTimerCreate( | |
| 122 NULL, 0, 0, 0, 0, StopCallback, &context); | |
| 123 CFRunLoopAddTimer(watcher_->run_loop_, timer, kCFRunLoopCommonModes); | |
| 124 watcher_->monitor_.Enter(); | |
| 125 while (ready_) { | |
| 126 watcher_->monitor_.Wait(Monitor::kNoTimeout); | |
| 127 } | |
| 128 watcher_->monitor_.Exit(); | |
| 129 } | |
| 130 | |
| 131 bool ready() const { return ready_; } | 152 bool ready() const { return ready_; } |
| 132 intptr_t base_path_length() const { return base_path_length_; } | 153 intptr_t base_path_length() const { return base_path_length_; } |
| 133 int read_fd() const { return read_fd_; } | 154 int read_fd() const { return read_fd_; } |
| 134 int write_fd() const { return write_fd_; } | 155 int write_fd() const { return write_fd_; } |
| 135 bool recursive() const { return recursive_; } | 156 bool recursive() const { return recursive_; } |
| 136 | 157 |
| 137 private: | 158 private: |
| 138 FSEventsWatcher* watcher_; | 159 FSEventsWatcher* watcher_; |
| 139 bool ready_; | 160 bool ready_; |
| 140 intptr_t base_path_length_; | 161 intptr_t base_path_length_; |
| 162 CFStringRef path_ref_; | |
| 141 int read_fd_; | 163 int read_fd_; |
| 142 int write_fd_; | 164 int write_fd_; |
| 143 bool recursive_; | 165 bool recursive_; |
| 144 FSEventStreamRef ref_; | 166 FSEventStreamRef ref_; |
| 145 }; | 167 }; |
| 146 | 168 |
| 147 FSEventsWatcher() : run_loop_(0) { | 169 FSEventsWatcher() : run_loop_(0) { |
|
Søren Gjesse
2014/02/07 10:20:02
Please add a Start method for starting the run-loo
Anders Johnsen
2014/02/07 12:49:24
Done.
| |
| 148 Thread::Start(Run, reinterpret_cast<uword>(this)); | 170 Thread::Start(Run, reinterpret_cast<uword>(this)); |
| 149 } | 171 } |
| 150 | 172 |
| 173 static void StopCallback(CFRunLoopTimerRef timer, void* info) { | |
| 174 FSEventsWatcher* watcher = reinterpret_cast<FSEventsWatcher*>(info); | |
| 175 CFRunLoopStop(watcher->run_loop_); | |
| 176 CFRelease(watcher->run_loop_); | |
| 177 watcher->monitor_.Enter(); | |
| 178 watcher->run_loop_ = NULL; | |
| 179 watcher->monitor_.Notify(); | |
| 180 watcher->monitor_.Exit(); | |
| 181 } | |
| 182 | |
| 151 ~FSEventsWatcher() { | 183 ~FSEventsWatcher() { |
|
Søren Gjesse
2014/02/07 10:20:02
Please move this to a Stop method and call that be
Anders Johnsen
2014/02/07 12:49:24
Done.
| |
| 152 CFRunLoopStop(run_loop_); | 184 CFRunLoopTimerContext context; |
| 185 memset(&context, 0, sizeof(context)); | |
| 186 context.info = this; | |
| 187 CFRunLoopTimerRef timer = CFRunLoopTimerCreate( | |
| 188 NULL, 0, 0, 0, 0, StopCallback, &context); | |
| 189 CFRunLoopAddTimer(run_loop_, timer, kCFRunLoopCommonModes); | |
| 190 CFRelease(timer); | |
| 191 monitor_.Enter(); | |
| 192 while (run_loop_ != NULL) { | |
| 193 monitor_.Wait(Monitor::kNoTimeout); | |
| 194 } | |
| 195 monitor_.Exit(); | |
| 153 } | 196 } |
| 154 | 197 |
| 155 Monitor& monitor() { return monitor_; } | 198 Monitor& monitor() { return monitor_; } |
| 156 | 199 |
| 157 bool has_run_loop() const { return run_loop_ != NULL; } | 200 bool has_run_loop() const { return run_loop_ != NULL; } |
| 158 | 201 |
| 159 static void TimerCallback(CFRunLoopTimerRef timer, void* context) { | 202 static void TimerCallback(CFRunLoopTimerRef timer, void* context) { |
| 160 // Dummy callback to keep RunLoop alive. | 203 // Dummy callback to keep RunLoop alive. |
| 161 } | 204 } |
| 162 | 205 |
| 163 static void Run(uword arg) { | 206 static void Run(uword arg) { |
|
Søren Gjesse
2014/02/07 10:20:02
We should consider in debug mode to get the thread
Anders Johnsen
2014/02/07 12:49:24
Done.
| |
| 164 FSEventsWatcher* watcher = reinterpret_cast<FSEventsWatcher*>(arg); | 207 FSEventsWatcher* watcher = reinterpret_cast<FSEventsWatcher*>(arg); |
| 165 watcher->run_loop_ = CFRunLoopGetCurrent(); | 208 watcher->run_loop_ = CFRunLoopGetCurrent(); |
| 209 CFRetain(watcher->run_loop_); | |
| 166 | 210 |
| 167 // Notify, as the run-loop is set. | 211 // Notify, as the run-loop is set. |
| 168 watcher->monitor().Enter(); | 212 watcher->monitor().Enter(); |
| 169 watcher->monitor().Notify(); | 213 watcher->monitor().Notify(); |
| 170 watcher->monitor().Exit(); | 214 watcher->monitor().Exit(); |
| 171 | 215 |
| 172 CFRunLoopTimerRef timer = CFRunLoopTimerCreate( | 216 CFRunLoopTimerRef timer = CFRunLoopTimerCreate( |
| 173 NULL, | 217 NULL, |
| 174 CFAbsoluteTimeGetCurrent() + 1, | 218 CFAbsoluteTimeGetCurrent() + 1, |
| 175 1, | 219 1, |
| 176 0, | 220 0, |
| 177 0, | 221 0, |
| 178 TimerCallback, | 222 TimerCallback, |
| 179 NULL); | 223 NULL); |
| 180 | |
| 181 CFRunLoopAddTimer(watcher->run_loop_, timer, kCFRunLoopCommonModes); | 224 CFRunLoopAddTimer(watcher->run_loop_, timer, kCFRunLoopCommonModes); |
| 225 CFRelease(timer); | |
| 182 | 226 |
| 183 CFRunLoopRun(); | 227 CFRunLoopRun(); |
| 184 } | 228 } |
| 185 | 229 |
| 186 Node* AddPath(const char* path, int events, bool recursive) { | 230 Node* AddPath(const char* path, int events, bool recursive) { |
| 187 int fds[2]; | 231 int fds[2]; |
| 188 VOID_TEMP_FAILURE_RETRY(pipe(fds)); | 232 VOID_TEMP_FAILURE_RETRY(pipe(fds)); |
| 189 Socket::SetNonBlocking(fds[0]); | 233 Socket::SetNonBlocking(fds[0]); |
| 190 Socket::SetBlocking(fds[1]); | 234 Socket::SetBlocking(fds[1]); |
| 191 | 235 |
| 192 char base_path[PATH_MAX]; | 236 char base_path[PATH_MAX]; |
| 193 realpath(path, base_path); | 237 realpath(path, base_path); |
| 194 CFStringRef path_ref = CFStringCreateWithCString( | |
| 195 NULL, base_path, kCFStringEncodingUTF8); | |
| 196 | 238 |
| 197 Node* node = new Node(this, strlen(base_path), fds[0], fds[1], recursive); | 239 return new Node(this, base_path, fds[0], fds[1], recursive); |
| 198 | |
| 199 FSEventStreamContext context; | |
| 200 context.version = 0; | |
| 201 context.info = reinterpret_cast<void*>(node); | |
| 202 context.retain = NULL; | |
| 203 context.release = NULL; | |
| 204 context.copyDescription = NULL; | |
| 205 FSEventStreamRef ref = FSEventStreamCreate( | |
| 206 NULL, | |
| 207 Callback, | |
| 208 &context, | |
| 209 CFArrayCreate(NULL, reinterpret_cast<const void**>(&path_ref), 1, NULL), | |
| 210 kFSEventStreamEventIdSinceNow, | |
| 211 0.10, | |
| 212 kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents); | |
| 213 | |
| 214 node->set_ref(ref); | |
| 215 | |
| 216 return node; | |
| 217 } | 240 } |
| 218 | 241 |
| 219 private: | 242 private: |
| 220 static void Callback(ConstFSEventStreamRef ref, | 243 static void Callback(ConstFSEventStreamRef ref, |
| 221 void* client, | 244 void* client, |
| 222 size_t num_events, | 245 size_t num_events, |
| 223 void* event_paths, | 246 void* event_paths, |
| 224 const FSEventStreamEventFlags event_flags[], | 247 const FSEventStreamEventFlags event_flags[], |
| 225 const FSEventStreamEventId event_ids[]) { | 248 const FSEventStreamEventId event_ids[]) { |
| 226 Node* node = reinterpret_cast<Node*>(client); | 249 Node* node = reinterpret_cast<Node*>(client); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 delete watcher; | 291 delete watcher; |
| 269 } | 292 } |
| 270 | 293 |
| 271 | 294 |
| 272 intptr_t FileSystemWatcher::WatchPath(intptr_t id, | 295 intptr_t FileSystemWatcher::WatchPath(intptr_t id, |
| 273 const char* path, | 296 const char* path, |
| 274 int events, | 297 int events, |
| 275 bool recursive) { | 298 bool recursive) { |
| 276 FSEventsWatcher* watcher = reinterpret_cast<FSEventsWatcher*>(id); | 299 FSEventsWatcher* watcher = reinterpret_cast<FSEventsWatcher*>(id); |
| 277 FSEventsWatcher::Node* node = watcher->AddPath(path, events, recursive); | 300 FSEventsWatcher::Node* node = watcher->AddPath(path, events, recursive); |
| 278 node->Start(); | |
| 279 return reinterpret_cast<intptr_t>(node); | 301 return reinterpret_cast<intptr_t>(node); |
| 280 } | 302 } |
| 281 | 303 |
| 282 | 304 |
| 283 void FileSystemWatcher::UnwatchPath(intptr_t id, intptr_t path_id) { | 305 void FileSystemWatcher::UnwatchPath(intptr_t id, intptr_t path_id) { |
| 284 USE(id); | 306 USE(id); |
| 285 FSEventsWatcher::Node* node = | 307 FSEventsWatcher::Node* node = |
| 286 reinterpret_cast<FSEventsWatcher::Node*>(path_id); | 308 reinterpret_cast<FSEventsWatcher::Node*>(path_id); |
| 287 node->Stop(); | |
| 288 delete node; | 309 delete node; |
| 289 } | 310 } |
| 290 | 311 |
| 291 | 312 |
| 292 intptr_t FileSystemWatcher::GetSocketId(intptr_t id, intptr_t path_id) { | 313 intptr_t FileSystemWatcher::GetSocketId(intptr_t id, intptr_t path_id) { |
| 293 return reinterpret_cast<FSEventsWatcher::Node*>(path_id)->read_fd(); | 314 return reinterpret_cast<FSEventsWatcher::Node*>(path_id)->read_fd(); |
| 294 } | 315 } |
| 295 | 316 |
| 296 | 317 |
| 297 Dart_Handle FileSystemWatcher::ReadEvents(intptr_t id, intptr_t path_id) { | 318 Dart_Handle FileSystemWatcher::ReadEvents(intptr_t id, intptr_t path_id) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 340 } | 361 } |
| 341 return events; | 362 return events; |
| 342 } | 363 } |
| 343 | 364 |
| 344 } // namespace bin | 365 } // namespace bin |
| 345 } // namespace dart | 366 } // namespace dart |
| 346 | 367 |
| 347 #endif // defined(TARGET_OS_MACOS) | 368 #endif // defined(TARGET_OS_MACOS) |
| 348 | 369 |
| 349 | 370 |
| OLD | NEW |