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

Unified Diff: base/files/file_path_watcher_fsevents.cc

Issue 1046353004: Access fields from the appropriate threads in FilePathWatcherFSEvents. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 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_fsevents.cc
diff --git a/base/files/file_path_watcher_fsevents.cc b/base/files/file_path_watcher_fsevents.cc
index 6e1a927a8def71d8e5841cdde84589ea0aff9c9e..2ab78dd740416cacc6bb924e348c92994cd980fd 100644
--- a/base/files/file_path_watcher_fsevents.cc
+++ b/base/files/file_path_watcher_fsevents.cc
@@ -111,6 +111,18 @@ void FSEventsCallback(ConstFSEventStreamRef stream,
watcher->OnFilePathsChanged(paths);
}
+void FilterAndDispatchEvents(const std::vector<FilePath>& paths,
+ const FilePath& target,
+ const FilePath& resolved_target,
+ const FilePathWatcher::Callback& callback) {
+ for (const FilePath& path : paths) {
+ if (resolved_target.IsParent(path) || resolved_target == path) {
+ callback.Run(target, false);
Mattias Nissler (ping if slow) 2015/04/02 17:35:45 I think this may result in callbacks firing even a
Reilly Grant (use Gerrit) 2015/04/02 17:53:30 That's true. If it's a contract violation then I'l
+ return;
+ }
+ }
+}
+
} // namespace
FilePathWatcherFSEvents::FilePathWatcherFSEvents() : fsevent_stream_(NULL) {
@@ -118,29 +130,15 @@ FilePathWatcherFSEvents::FilePathWatcherFSEvents() : fsevent_stream_(NULL) {
void FilePathWatcherFSEvents::OnFilePathsChanged(
const std::vector<FilePath>& paths) {
- if (!message_loop()->BelongsToCurrentThread()) {
- message_loop()->PostTask(
- FROM_HERE,
- Bind(&FilePathWatcherFSEvents::OnFilePathsChanged, this, paths));
- return;
- }
-
- DCHECK(message_loop()->BelongsToCurrentThread());
- if (resolved_target_.empty())
- return;
-
- for (size_t i = 0; i < paths.size(); i++) {
- if (resolved_target_.IsParent(paths[i]) || resolved_target_ == paths[i]) {
- callback_.Run(target_, false);
- return;
- }
- }
+ DCHECK(!resolved_target_.empty());
+ message_loop()->PostTask(FROM_HERE,
+ Bind(&FilterAndDispatchEvents, paths, target_,
+ resolved_target_, callback_));
}
bool FilePathWatcherFSEvents::Watch(const FilePath& path,
bool recursive,
const FilePathWatcher::Callback& callback) {
- DCHECK(resolved_target_.empty());
DCHECK(MessageLoopForIO::current());
DCHECK(!callback.is_null());
@@ -150,38 +148,25 @@ bool FilePathWatcherFSEvents::Watch(const FilePath& path,
return false;
set_message_loop(MessageLoopProxy::current());
- callback_ = callback;
- target_ = path;
FSEventStreamEventId start_event = FSEventsGetCurrentEventId();
g_task_runner.Get().PostTask(
- FROM_HERE,
- Bind(&FilePathWatcherFSEvents::StartEventStream, this, start_event));
+ FROM_HERE, Bind(&FilePathWatcherFSEvents::StartEventStream, this,
+ start_event, path, callback));
return true;
}
void FilePathWatcherFSEvents::Cancel() {
- if (callback_.is_null()) {
- // Watch was never called, so exit.
- set_cancelled();
- return;
- }
-
- // Switch to the dispatch queue thread if necessary, so we can tear down
- // the event stream.
- if (!g_task_runner.Get().RunsTasksOnCurrentThread()) {
- g_task_runner.Get().PostTask(
- FROM_HERE,
- Bind(&FilePathWatcherFSEvents::CancelOnMessageLoopThread, this));
- } else {
- CancelOnMessageLoopThread();
- }
+ // Switch to the dispatch queue thread to tear down the event stream.
+ g_task_runner.Get().PostTask(
+ FROM_HERE,
+ Bind(&FilePathWatcherFSEvents::CancelOnMessageLoopThread, this));
}
void FilePathWatcherFSEvents::CancelOnMessageLoopThread() {
// For all other implementations, the "message loop thread" is the IO thread,
// as returned by message_loop(). This implementation, however, needs to
- // cancel pending work on the Dipatch Queue thread.
+ // cancel pending work on the Dispatch Queue thread.
DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
set_cancelled();
@@ -197,11 +182,6 @@ void FilePathWatcherFSEvents::UpdateEventStream(
FSEventStreamEventId start_event) {
DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
- // It can happen that the watcher gets canceled while tasks that call this
Mattias Nissler (ping if slow) 2015/04/02 17:35:45 I don't see why we no longer need a safeguard here
Reilly Grant (use Gerrit) 2015/04/02 17:53:30 With the cancel operation serialized onto the libd
- // function are still in flight, so abort if this situation is detected.
- if (is_cancelled() || resolved_target_.empty())
- return;
-
if (fsevent_stream_)
DestroyEventStream();
@@ -252,8 +232,14 @@ void FilePathWatcherFSEvents::DestroyEventStream() {
}
void FilePathWatcherFSEvents::StartEventStream(
- FSEventStreamEventId start_event) {
+ FSEventStreamEventId start_event,
+ const FilePath& path,
+ const FilePathWatcher::Callback& callback) {
DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
+ DCHECK(resolved_target_.empty());
+
+ callback_ = callback;
Mattias Nissler (ping if slow) 2015/04/02 17:35:45 I think you want to keep callback_ on the message_
Reilly Grant (use Gerrit) 2015/04/02 17:53:31 I don't think base::Callback is thread safe. I'll
+ target_ = path;
ResolveTargetPath();
UpdateEventStream(start_event);
}
« base/files/file_path_watcher_fsevents.h ('K') | « base/files/file_path_watcher_fsevents.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698