diff options
author | Hidehiko Abe <hidehiko@google.com> | 2017-12-13 18:59:30 +0900 |
---|---|---|
committer | Hidehiko Abe <hidehiko@google.com> | 2017-12-13 23:41:17 +0900 |
commit | 36040ed30c39d2106a2cd5ec033e98b71302a744 (patch) | |
tree | dc486be512fe418b1cd79a66c11556174de03c4f /base/files/file_path_watcher_kqueue.cc | |
parent | 1216c7fc80727dea7cb9c5f946688f4b98ccd23c (diff) | |
download | libchrome-36040ed30c39d2106a2cd5ec033e98b71302a744.tar.gz |
libchrome: Uprev the library to r456626 from Chromium
Pulled the latest and greatest version of libchrome from Chromium.
The merge was done against r456626 which corresponds to git commit
08266b3fca707804065a2cfd60331722ade41969 of Mar 14, 2017
Notable changes are:
- FOR_EACH_OBSERVER macro removed (replaced by use of C++ 11
range-base for loop)
- base::Values no more FundamentalValue
- stl_util moved to base namespace
- some scoped pointers removed in crypto/ in favor
of BoringSSL UniquePtr.
- path() accessor renamed to GetPath() in ScopedTempDir (and other
classes)
- introduction of base::CallbackOnce
Test: All unit-tests should still pass.
Change-Id: I1e65efb167fa708e35ed7c6492f1cb66a6a46104
Merged-In: I180f9defc7607f462389fae17701fff553c4a2d0
Diffstat (limited to 'base/files/file_path_watcher_kqueue.cc')
-rw-r--r-- | base/files/file_path_watcher_kqueue.cc | 163 |
1 files changed, 72 insertions, 91 deletions
diff --git a/base/files/file_path_watcher_kqueue.cc b/base/files/file_path_watcher_kqueue.cc index 6d034cd9a2..a28726acb0 100644 --- a/base/files/file_path_watcher_kqueue.cc +++ b/base/files/file_path_watcher_kqueue.cc @@ -12,7 +12,7 @@ #include "base/files/file_util.h" #include "base/logging.h" #include "base/strings/stringprintf.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" // On some platforms these are not defined. #if !defined(EV_RECEIPT) @@ -26,7 +26,9 @@ namespace base { FilePathWatcherKQueue::FilePathWatcherKQueue() : kqueue_(-1) {} -FilePathWatcherKQueue::~FilePathWatcherKQueue() {} +FilePathWatcherKQueue::~FilePathWatcherKQueue() { + DCHECK(!task_runner() || task_runner()->RunsTasksOnCurrentThread()); +} void FilePathWatcherKQueue::ReleaseEvent(struct kevent& event) { CloseFileDescriptor(&event.ident); @@ -36,7 +38,6 @@ void FilePathWatcherKQueue::ReleaseEvent(struct kevent& event) { } int FilePathWatcherKQueue::EventsForPath(FilePath path, EventVector* events) { - DCHECK(MessageLoopForIO::current()); // Make sure that we are working with a clean slate. DCHECK(events->empty()); @@ -230,9 +231,74 @@ bool FilePathWatcherKQueue::UpdateWatches(bool* target_file_affected) { return true; } -void FilePathWatcherKQueue::OnFileCanReadWithoutBlocking(int fd) { - DCHECK(MessageLoopForIO::current()); - DCHECK_EQ(fd, kqueue_); +bool FilePathWatcherKQueue::Watch(const FilePath& path, + bool recursive, + const FilePathWatcher::Callback& callback) { + DCHECK(target_.value().empty()); // Can only watch one path. + DCHECK(!callback.is_null()); + DCHECK_EQ(kqueue_, -1); + // Recursive watch is not supported using kqueue. + DCHECK(!recursive); + + callback_ = callback; + target_ = path; + + set_task_runner(SequencedTaskRunnerHandle::Get()); + + kqueue_ = kqueue(); + if (kqueue_ == -1) { + DPLOG(ERROR) << "kqueue"; + return false; + } + + int last_entry = EventsForPath(target_, &events_); + DCHECK_NE(last_entry, 0); + + EventVector responses(last_entry); + + int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], last_entry, + &responses[0], last_entry, NULL)); + if (!AreKeventValuesValid(&responses[0], count)) { + // Calling Cancel() here to close any file descriptors that were opened. + // This would happen in the destructor anyways, but FilePathWatchers tend to + // be long lived, and if an error has occurred, there is no reason to waste + // the file descriptors. + Cancel(); + return false; + } + + // It's safe to use Unretained() because the watch is cancelled and the + // callback cannot be invoked after |kqueue_watch_controller_| (which is a + // member of |this|) has been deleted. + kqueue_watch_controller_ = FileDescriptorWatcher::WatchReadable( + kqueue_, + Bind(&FilePathWatcherKQueue::OnKQueueReadable, Unretained(this))); + + return true; +} + +void FilePathWatcherKQueue::Cancel() { + if (!task_runner()) { + set_cancelled(); + return; + } + + DCHECK(task_runner()->RunsTasksOnCurrentThread()); + if (!is_cancelled()) { + set_cancelled(); + kqueue_watch_controller_.reset(); + if (IGNORE_EINTR(close(kqueue_)) != 0) { + DPLOG(ERROR) << "close kqueue"; + } + kqueue_ = -1; + std::for_each(events_.begin(), events_.end(), ReleaseEvent); + events_.clear(); + callback_.Reset(); + } +} + +void FilePathWatcherKQueue::OnKQueueReadable() { + DCHECK(task_runner()->RunsTasksOnCurrentThread()); DCHECK(events_.size()); // Request the file system update notifications that have occurred and return @@ -303,89 +369,4 @@ void FilePathWatcherKQueue::OnFileCanReadWithoutBlocking(int fd) { } } -void FilePathWatcherKQueue::OnFileCanWriteWithoutBlocking(int /* fd */) { - NOTREACHED(); -} - -void FilePathWatcherKQueue::WillDestroyCurrentMessageLoop() { - CancelOnMessageLoopThread(); -} - -bool FilePathWatcherKQueue::Watch(const FilePath& path, - bool recursive, - const FilePathWatcher::Callback& callback) { - DCHECK(MessageLoopForIO::current()); - DCHECK(target_.value().empty()); // Can only watch one path. - DCHECK(!callback.is_null()); - DCHECK_EQ(kqueue_, -1); - - if (recursive) { - // Recursive watch is not supported using kqueue. - NOTIMPLEMENTED(); - return false; - } - - callback_ = callback; - target_ = path; - - MessageLoop::current()->AddDestructionObserver(this); - io_task_runner_ = ThreadTaskRunnerHandle::Get(); - - kqueue_ = kqueue(); - if (kqueue_ == -1) { - DPLOG(ERROR) << "kqueue"; - return false; - } - - int last_entry = EventsForPath(target_, &events_); - DCHECK_NE(last_entry, 0); - - EventVector responses(last_entry); - - int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], last_entry, - &responses[0], last_entry, NULL)); - if (!AreKeventValuesValid(&responses[0], count)) { - // Calling Cancel() here to close any file descriptors that were opened. - // This would happen in the destructor anyways, but FilePathWatchers tend to - // be long lived, and if an error has occurred, there is no reason to waste - // the file descriptors. - Cancel(); - return false; - } - - return MessageLoopForIO::current()->WatchFileDescriptor( - kqueue_, true, MessageLoopForIO::WATCH_READ, &kqueue_watcher_, this); -} - -void FilePathWatcherKQueue::Cancel() { - SingleThreadTaskRunner* task_runner = io_task_runner_.get(); - if (!task_runner) { - set_cancelled(); - return; - } - if (!task_runner->BelongsToCurrentThread()) { - task_runner->PostTask(FROM_HERE, - base::Bind(&FilePathWatcherKQueue::Cancel, this)); - return; - } - CancelOnMessageLoopThread(); -} - -void FilePathWatcherKQueue::CancelOnMessageLoopThread() { - DCHECK(MessageLoopForIO::current()); - if (!is_cancelled()) { - set_cancelled(); - kqueue_watcher_.StopWatchingFileDescriptor(); - if (IGNORE_EINTR(close(kqueue_)) != 0) { - DPLOG(ERROR) << "close kqueue"; - } - kqueue_ = -1; - std::for_each(events_.begin(), events_.end(), ReleaseEvent); - events_.clear(); - io_task_runner_ = NULL; - MessageLoop::current()->RemoveDestructionObserver(this); - callback_.Reset(); - } -} - } // namespace base |