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

Side by Side Diff: base/files/file_path_watcher_linux.cc

Issue 369703003: Reduce usage of MessageLoopProxy in base/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased Created 6 years, 2 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/files/file_path_watcher_kqueue.cc ('k') | base/files/file_path_watcher_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.h" 5 #include "base/files/file_path_watcher.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <string.h> 8 #include <string.h>
9 #include <sys/inotify.h> 9 #include <sys/inotify.h>
10 #include <sys/ioctl.h> 10 #include <sys/ioctl.h>
(...skipping 10 matching lines...) Expand all
21 #include "base/containers/hash_tables.h" 21 #include "base/containers/hash_tables.h"
22 #include "base/debug/trace_event.h" 22 #include "base/debug/trace_event.h"
23 #include "base/files/file_enumerator.h" 23 #include "base/files/file_enumerator.h"
24 #include "base/files/file_path.h" 24 #include "base/files/file_path.h"
25 #include "base/files/file_util.h" 25 #include "base/files/file_util.h"
26 #include "base/lazy_instance.h" 26 #include "base/lazy_instance.h"
27 #include "base/location.h" 27 #include "base/location.h"
28 #include "base/logging.h" 28 #include "base/logging.h"
29 #include "base/memory/scoped_ptr.h" 29 #include "base/memory/scoped_ptr.h"
30 #include "base/message_loop/message_loop.h" 30 #include "base/message_loop/message_loop.h"
31 #include "base/message_loop/message_loop_proxy.h"
32 #include "base/posix/eintr_wrapper.h" 31 #include "base/posix/eintr_wrapper.h"
33 #include "base/synchronization/lock.h" 32 #include "base/synchronization/lock.h"
33 #include "base/thread_task_runner_handle.h"
34 #include "base/threading/thread.h" 34 #include "base/threading/thread.h"
35 35
36 namespace base { 36 namespace base {
37 37
38 namespace { 38 namespace {
39 39
40 class FilePathWatcherImpl; 40 class FilePathWatcherImpl;
41 41
42 // Singleton to manage all inotify watches. 42 // Singleton to manage all inotify watches.
43 // TODO(tony): It would be nice if this wasn't a singleton. 43 // TODO(tony): It would be nice if this wasn't a singleton.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 private: 110 private:
111 // Start watching |path| for changes and notify |delegate| on each change. 111 // Start watching |path| for changes and notify |delegate| on each change.
112 // Returns true if watch for |path| has been added successfully. 112 // Returns true if watch for |path| has been added successfully.
113 virtual bool Watch(const FilePath& path, 113 virtual bool Watch(const FilePath& path,
114 bool recursive, 114 bool recursive,
115 const FilePathWatcher::Callback& callback) override; 115 const FilePathWatcher::Callback& callback) override;
116 116
117 // Cancel the watch. This unregisters the instance with InotifyReader. 117 // Cancel the watch. This unregisters the instance with InotifyReader.
118 virtual void Cancel() override; 118 virtual void Cancel() override;
119 119
120 // Cleans up and stops observing the message_loop() thread. 120 // Cleans up and stops observing the task_runner() thread.
121 virtual void CancelOnMessageLoopThread() override; 121 virtual void CancelOnMessageLoopThread() override;
122 122
123 // Deletion of the FilePathWatcher will call Cancel() to dispose of this 123 // Deletion of the FilePathWatcher will call Cancel() to dispose of this
124 // object in the right thread. This also observes destruction of the required 124 // object in the right thread. This also observes destruction of the required
125 // cleanup thread, in case it quits before Cancel() is called. 125 // cleanup thread, in case it quits before Cancel() is called.
126 virtual void WillDestroyCurrentMessageLoop() override; 126 virtual void WillDestroyCurrentMessageLoop() override;
127 127
128 // Inotify watches are installed for all directory components of |target_|. A 128 // Inotify watches are installed for all directory components of |target_|. A
129 // WatchEntry instance holds the watch descriptor for a component and the 129 // WatchEntry instance holds the watch descriptor for a component and the
130 // subdirectory for that identifies the next component. If a symbolic link 130 // subdirectory for that identifies the next component. If a symbolic link
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 339
340 FilePathWatcherImpl::FilePathWatcherImpl() 340 FilePathWatcherImpl::FilePathWatcherImpl()
341 : recursive_(false) { 341 : recursive_(false) {
342 } 342 }
343 343
344 void FilePathWatcherImpl::OnFilePathChanged(InotifyReader::Watch fired_watch, 344 void FilePathWatcherImpl::OnFilePathChanged(InotifyReader::Watch fired_watch,
345 const FilePath::StringType& child, 345 const FilePath::StringType& child,
346 bool created, 346 bool created,
347 bool deleted, 347 bool deleted,
348 bool is_dir) { 348 bool is_dir) {
349 if (!message_loop()->BelongsToCurrentThread()) { 349 if (!task_runner()->RunsTasksOnCurrentThread()) {
350 // Switch to message_loop() to access |watches_| safely. 350 // Switch to task_runner() to access |watches_| safely.
351 message_loop()->PostTask( 351 task_runner()->PostTask(FROM_HERE,
352 FROM_HERE, 352 Bind(&FilePathWatcherImpl::OnFilePathChanged,
353 Bind(&FilePathWatcherImpl::OnFilePathChanged, this, 353 this,
354 fired_watch, child, created, deleted, is_dir)); 354 fired_watch,
355 child,
356 created,
357 deleted,
358 is_dir));
355 return; 359 return;
356 } 360 }
357 361
358 // Check to see if CancelOnMessageLoopThread() has already been called. 362 // Check to see if CancelOnMessageLoopThread() has already been called.
359 // May happen when code flow reaches here from the PostTask() above. 363 // May happen when code flow reaches here from the PostTask() above.
360 if (watches_.empty()) { 364 if (watches_.empty()) {
361 DCHECK(target_.empty()); 365 DCHECK(target_.empty());
362 return; 366 return;
363 } 367 }
364 368
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 callback_.Run(target_, false /* error */); 426 callback_.Run(target_, false /* error */);
423 } 427 }
424 } 428 }
425 429
426 bool FilePathWatcherImpl::Watch(const FilePath& path, 430 bool FilePathWatcherImpl::Watch(const FilePath& path,
427 bool recursive, 431 bool recursive,
428 const FilePathWatcher::Callback& callback) { 432 const FilePathWatcher::Callback& callback) {
429 DCHECK(target_.empty()); 433 DCHECK(target_.empty());
430 DCHECK(MessageLoopForIO::current()); 434 DCHECK(MessageLoopForIO::current());
431 435
432 set_message_loop(MessageLoopProxy::current()); 436 set_task_runner(ThreadTaskRunnerHandle::Get());
433 callback_ = callback; 437 callback_ = callback;
434 target_ = path; 438 target_ = path;
435 recursive_ = recursive; 439 recursive_ = recursive;
436 MessageLoop::current()->AddDestructionObserver(this); 440 MessageLoop::current()->AddDestructionObserver(this);
437 441
438 std::vector<FilePath::StringType> comps; 442 std::vector<FilePath::StringType> comps;
439 target_.GetComponents(&comps); 443 target_.GetComponents(&comps);
440 DCHECK(!comps.empty()); 444 DCHECK(!comps.empty());
441 for (size_t i = 1; i < comps.size(); ++i) 445 for (size_t i = 1; i < comps.size(); ++i)
442 watches_.push_back(WatchEntry(comps[i])); 446 watches_.push_back(WatchEntry(comps[i]));
443 watches_.push_back(WatchEntry(FilePath::StringType())); 447 watches_.push_back(WatchEntry(FilePath::StringType()));
444 UpdateWatches(); 448 UpdateWatches();
445 return true; 449 return true;
446 } 450 }
447 451
448 void FilePathWatcherImpl::Cancel() { 452 void FilePathWatcherImpl::Cancel() {
449 if (callback_.is_null()) { 453 if (callback_.is_null()) {
450 // Watch was never called, or the message_loop() thread is already gone. 454 // Watch was never called, or the task_runner() thread is already gone.
451 set_cancelled(); 455 set_cancelled();
452 return; 456 return;
453 } 457 }
454 458
455 // Switch to the message_loop() if necessary so we can access |watches_|. 459 // Switch to the task_runner() if necessary so we can access |watches_|.
456 if (!message_loop()->BelongsToCurrentThread()) { 460 if (!task_runner()->RunsTasksOnCurrentThread()) {
457 message_loop()->PostTask(FROM_HERE, 461 task_runner()->PostTask(
458 Bind(&FilePathWatcher::CancelWatch, 462 FROM_HERE,
459 make_scoped_refptr(this))); 463 Bind(&FilePathWatcher::CancelWatch, make_scoped_refptr(this)));
460 } else { 464 } else {
461 CancelOnMessageLoopThread(); 465 CancelOnMessageLoopThread();
462 } 466 }
463 } 467 }
464 468
465 void FilePathWatcherImpl::CancelOnMessageLoopThread() { 469 void FilePathWatcherImpl::CancelOnMessageLoopThread() {
466 DCHECK(message_loop()->BelongsToCurrentThread()); 470 DCHECK(task_runner()->RunsTasksOnCurrentThread());
467 set_cancelled(); 471 set_cancelled();
468 472
469 if (!callback_.is_null()) { 473 if (!callback_.is_null()) {
470 MessageLoop::current()->RemoveDestructionObserver(this); 474 MessageLoop::current()->RemoveDestructionObserver(this);
471 callback_.Reset(); 475 callback_.Reset();
472 } 476 }
473 477
474 for (size_t i = 0; i < watches_.size(); ++i) 478 for (size_t i = 0; i < watches_.size(); ++i)
475 g_inotify_reader.Get().RemoveWatch(watches_[i].watch, this); 479 g_inotify_reader.Get().RemoveWatch(watches_[i].watch, this);
476 watches_.clear(); 480 watches_.clear();
477 target_.clear(); 481 target_.clear();
478 482
479 if (recursive_) 483 if (recursive_)
480 RemoveRecursiveWatches(); 484 RemoveRecursiveWatches();
481 } 485 }
482 486
483 void FilePathWatcherImpl::WillDestroyCurrentMessageLoop() { 487 void FilePathWatcherImpl::WillDestroyCurrentMessageLoop() {
484 CancelOnMessageLoopThread(); 488 CancelOnMessageLoopThread();
485 } 489 }
486 490
487 void FilePathWatcherImpl::UpdateWatches() { 491 void FilePathWatcherImpl::UpdateWatches() {
488 // Ensure this runs on the message_loop() exclusively in order to avoid 492 // Ensure this runs on the task_runner() exclusively in order to avoid
489 // concurrency issues. 493 // concurrency issues.
490 DCHECK(message_loop()->BelongsToCurrentThread()); 494 DCHECK(task_runner()->RunsTasksOnCurrentThread());
491 DCHECK(HasValidWatchVector()); 495 DCHECK(HasValidWatchVector());
492 496
493 // Walk the list of watches and update them as we go. 497 // Walk the list of watches and update them as we go.
494 FilePath path(FILE_PATH_LITERAL("/")); 498 FilePath path(FILE_PATH_LITERAL("/"));
495 bool path_valid = true; 499 bool path_valid = true;
496 for (size_t i = 0; i < watches_.size(); ++i) { 500 for (size_t i = 0; i < watches_.size(); ++i) {
497 WatchEntry& watch_entry = watches_[i]; 501 WatchEntry& watch_entry = watches_[i];
498 InotifyReader::Watch old_watch = watch_entry.watch; 502 InotifyReader::Watch old_watch = watch_entry.watch;
499 watch_entry.watch = InotifyReader::kInvalidWatch; 503 watch_entry.watch = InotifyReader::kInvalidWatch;
500 watch_entry.linkname.clear(); 504 watch_entry.linkname.clear();
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 return watches_[watches_.size() - 1].subdir.empty(); 664 return watches_[watches_.size() - 1].subdir.empty();
661 } 665 }
662 666
663 } // namespace 667 } // namespace
664 668
665 FilePathWatcher::FilePathWatcher() { 669 FilePathWatcher::FilePathWatcher() {
666 impl_ = new FilePathWatcherImpl(); 670 impl_ = new FilePathWatcherImpl();
667 } 671 }
668 672
669 } // namespace base 673 } // namespace base
OLDNEW
« no previous file with comments | « base/files/file_path_watcher_kqueue.cc ('k') | base/files/file_path_watcher_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698