| 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 |