Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(600)

Side by Side Diff: runtime/bin/file_system_watcher_macos.cc

Issue 140183004: Move all run-loop calls into the run-loop thread, and use correct memory handling (retain/release). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698