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

Unified Diff: base/files/file_path_watcher_kqueue.cc

Issue 2353103002: Use FileDescriptorWatcher in FilePathWatcherKQueue. (Closed)
Patch Set: fix windows build error Created 4 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: base/files/file_path_watcher_kqueue.cc
diff --git a/base/files/file_path_watcher_kqueue.cc b/base/files/file_path_watcher_kqueue.cc
index 4b81bf2b31f4731cdea471e886d5a664a955ef12..8a7b5c54fd7b7e69d28aa03ae74b3bca6b312b24 100644
--- a/base/files/file_path_watcher_kqueue.cc
+++ b/base/files/file_path_watcher_kqueue.cc
@@ -36,7 +36,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 +229,70 @@ bool FilePathWatcherKQueue::UpdateWatches(bool* target_file_affected) {
return true;
}
-void FilePathWatcherKQueue::OnFileCanReadWithoutBlocking(int fd) {
- DCHECK(MessageLoopForIO::current());
- DCHECK_EQ(fd, kqueue_);
+void FilePathWatcherKQueue::WillDestroyCurrentMessageLoop() {
+ CancelOnMessageLoopThread();
+}
+
+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;
+
+ MessageLoop::current()->AddDestructionObserver(this);
+ set_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;
+ }
+
+ // This creates an ownership cycle (|this| owns |kqueue_watch_controller_|
+ // which owns a callback which owns |this|). The cycle is broken when
+ // |kqueue_watch_controller_| is reset in CancelOnMessageLoopThread().
+ kqueue_watch_controller_ = FileDescriptorWatcher::WatchReadable(
+ kqueue_, Bind(&FilePathWatcherKQueue::OnKQueueReadable, this));
+ return true;
+}
+
+void FilePathWatcherKQueue::Cancel() {
+ if (!task_runner()) {
+ set_cancelled();
+ return;
+ }
+ if (!task_runner()->BelongsToCurrentThread()) {
+ task_runner()->PostTask(FROM_HERE,
+ base::Bind(&FilePathWatcherKQueue::Cancel, this));
+ return;
+ }
+ CancelOnMessageLoopThread();
+}
+
+void FilePathWatcherKQueue::OnKQueueReadable() {
+ DCHECK(task_runner()->BelongsToCurrentThread());
DCHECK(events_.size());
// Request the file system update notifications that have occurred and return
@@ -303,86 +363,17 @@ 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());
+ DCHECK(!task_runner() || task_runner()->BelongsToCurrentThread());
if (!is_cancelled()) {
set_cancelled();
- kqueue_watcher_.StopWatchingFileDescriptor();
+ 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();
- io_task_runner_ = NULL;
MessageLoop::current()->RemoveDestructionObserver(this);
callback_.Reset();
}
« no previous file with comments | « base/files/file_path_watcher_kqueue.h ('k') | components/policy/core/common/configuration_policy_provider_test.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698