OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/files/file_path_watcher_kqueue.h" | 5 #include "base/files/file_path_watcher_kqueue.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <sys/param.h> | 8 #include <sys/param.h> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 14 #include "base/thread_task_runner_handle.h" |
14 | 15 |
15 // On some platforms these are not defined. | 16 // On some platforms these are not defined. |
16 #if !defined(EV_RECEIPT) | 17 #if !defined(EV_RECEIPT) |
17 #define EV_RECEIPT 0 | 18 #define EV_RECEIPT 0 |
18 #endif | 19 #endif |
19 #if !defined(O_EVTONLY) | 20 #if !defined(O_EVTONLY) |
20 #define O_EVTONLY O_RDONLY | 21 #define O_EVTONLY O_RDONLY |
21 #endif | 22 #endif |
22 | 23 |
23 namespace base { | 24 namespace base { |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 if (recursive) { | 321 if (recursive) { |
321 // Recursive watch is not supported using kqueue. | 322 // Recursive watch is not supported using kqueue. |
322 NOTIMPLEMENTED(); | 323 NOTIMPLEMENTED(); |
323 return false; | 324 return false; |
324 } | 325 } |
325 | 326 |
326 callback_ = callback; | 327 callback_ = callback; |
327 target_ = path; | 328 target_ = path; |
328 | 329 |
329 MessageLoop::current()->AddDestructionObserver(this); | 330 MessageLoop::current()->AddDestructionObserver(this); |
330 io_message_loop_ = base::MessageLoopProxy::current(); | 331 io_task_runner_ = ThreadTaskRunnerHandle::Get(); |
331 | 332 |
332 kqueue_ = kqueue(); | 333 kqueue_ = kqueue(); |
333 if (kqueue_ == -1) { | 334 if (kqueue_ == -1) { |
334 DPLOG(ERROR) << "kqueue"; | 335 DPLOG(ERROR) << "kqueue"; |
335 return false; | 336 return false; |
336 } | 337 } |
337 | 338 |
338 int last_entry = EventsForPath(target_, &events_); | 339 int last_entry = EventsForPath(target_, &events_); |
339 DCHECK_NE(last_entry, 0); | 340 DCHECK_NE(last_entry, 0); |
340 | 341 |
341 EventVector responses(last_entry); | 342 EventVector responses(last_entry); |
342 | 343 |
343 int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], last_entry, | 344 int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], last_entry, |
344 &responses[0], last_entry, NULL)); | 345 &responses[0], last_entry, NULL)); |
345 if (!AreKeventValuesValid(&responses[0], count)) { | 346 if (!AreKeventValuesValid(&responses[0], count)) { |
346 // Calling Cancel() here to close any file descriptors that were opened. | 347 // Calling Cancel() here to close any file descriptors that were opened. |
347 // This would happen in the destructor anyways, but FilePathWatchers tend to | 348 // This would happen in the destructor anyways, but FilePathWatchers tend to |
348 // be long lived, and if an error has occurred, there is no reason to waste | 349 // be long lived, and if an error has occurred, there is no reason to waste |
349 // the file descriptors. | 350 // the file descriptors. |
350 Cancel(); | 351 Cancel(); |
351 return false; | 352 return false; |
352 } | 353 } |
353 | 354 |
354 return MessageLoopForIO::current()->WatchFileDescriptor( | 355 return MessageLoopForIO::current()->WatchFileDescriptor( |
355 kqueue_, true, MessageLoopForIO::WATCH_READ, &kqueue_watcher_, this); | 356 kqueue_, true, MessageLoopForIO::WATCH_READ, &kqueue_watcher_, this); |
356 } | 357 } |
357 | 358 |
358 void FilePathWatcherKQueue::Cancel() { | 359 void FilePathWatcherKQueue::Cancel() { |
359 base::MessageLoopProxy* proxy = io_message_loop_.get(); | 360 SingleThreadTaskRunner* task_runner = io_task_runner_.get(); |
360 if (!proxy) { | 361 if (!task_runner) { |
361 set_cancelled(); | 362 set_cancelled(); |
362 return; | 363 return; |
363 } | 364 } |
364 if (!proxy->BelongsToCurrentThread()) { | 365 if (!task_runner->BelongsToCurrentThread()) { |
365 proxy->PostTask(FROM_HERE, | 366 task_runner->PostTask(FROM_HERE, |
366 base::Bind(&FilePathWatcherKQueue::Cancel, this)); | 367 base::Bind(&FilePathWatcherKQueue::Cancel, this)); |
367 return; | 368 return; |
368 } | 369 } |
369 CancelOnMessageLoopThread(); | 370 CancelOnMessageLoopThread(); |
370 } | 371 } |
371 | 372 |
372 void FilePathWatcherKQueue::CancelOnMessageLoopThread() { | 373 void FilePathWatcherKQueue::CancelOnMessageLoopThread() { |
373 DCHECK(MessageLoopForIO::current()); | 374 DCHECK(MessageLoopForIO::current()); |
374 if (!is_cancelled()) { | 375 if (!is_cancelled()) { |
375 set_cancelled(); | 376 set_cancelled(); |
376 kqueue_watcher_.StopWatchingFileDescriptor(); | 377 kqueue_watcher_.StopWatchingFileDescriptor(); |
377 if (IGNORE_EINTR(close(kqueue_)) != 0) { | 378 if (IGNORE_EINTR(close(kqueue_)) != 0) { |
378 DPLOG(ERROR) << "close kqueue"; | 379 DPLOG(ERROR) << "close kqueue"; |
379 } | 380 } |
380 kqueue_ = -1; | 381 kqueue_ = -1; |
381 std::for_each(events_.begin(), events_.end(), ReleaseEvent); | 382 std::for_each(events_.begin(), events_.end(), ReleaseEvent); |
382 events_.clear(); | 383 events_.clear(); |
383 io_message_loop_ = NULL; | 384 io_task_runner_ = NULL; |
384 MessageLoop::current()->RemoveDestructionObserver(this); | 385 MessageLoop::current()->RemoveDestructionObserver(this); |
385 callback_.Reset(); | 386 callback_.Reset(); |
386 } | 387 } |
387 } | 388 } |
388 | 389 |
389 } // namespace base | 390 } // namespace base |
OLD | NEW |