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

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

Issue 2598193002: Allow FilePathWatcher to be used from sequenced tasks. (Closed)
Patch Set: thread -> sequence in comment Created 3 years, 12 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
« 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 <stddef.h> 8 #include <stddef.h>
9 #include <string.h> 9 #include <string.h>
10 #include <sys/inotify.h> 10 #include <sys/inotify.h>
(...skipping 14 matching lines...) Expand all
25 #include "base/files/file_path.h" 25 #include "base/files/file_path.h"
26 #include "base/files/file_util.h" 26 #include "base/files/file_util.h"
27 #include "base/lazy_instance.h" 27 #include "base/lazy_instance.h"
28 #include "base/location.h" 28 #include "base/location.h"
29 #include "base/logging.h" 29 #include "base/logging.h"
30 #include "base/macros.h" 30 #include "base/macros.h"
31 #include "base/posix/eintr_wrapper.h" 31 #include "base/posix/eintr_wrapper.h"
32 #include "base/single_thread_task_runner.h" 32 #include "base/single_thread_task_runner.h"
33 #include "base/stl_util.h" 33 #include "base/stl_util.h"
34 #include "base/synchronization/lock.h" 34 #include "base/synchronization/lock.h"
35 #include "base/threading/sequenced_task_runner_handle.h"
35 #include "base/threading/thread.h" 36 #include "base/threading/thread.h"
36 #include "base/threading/thread_task_runner_handle.h"
37 #include "base/trace_event/trace_event.h" 37 #include "base/trace_event/trace_event.h"
38 38
39 namespace base { 39 namespace base {
40 40
41 namespace { 41 namespace {
42 42
43 class FilePathWatcherImpl; 43 class FilePathWatcherImpl;
44 44
45 // Singleton to manage all inotify watches. 45 // Singleton to manage all inotify watches.
46 // TODO(tony): It would be nice if this wasn't a singleton. 46 // TODO(tony): It would be nice if this wasn't a singleton.
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 313
314 FilePathWatcherImpl::FilePathWatcherImpl() 314 FilePathWatcherImpl::FilePathWatcherImpl()
315 : recursive_(false) { 315 : recursive_(false) {
316 } 316 }
317 317
318 void FilePathWatcherImpl::OnFilePathChanged(InotifyReader::Watch fired_watch, 318 void FilePathWatcherImpl::OnFilePathChanged(InotifyReader::Watch fired_watch,
319 const FilePath::StringType& child, 319 const FilePath::StringType& child,
320 bool created, 320 bool created,
321 bool deleted, 321 bool deleted,
322 bool is_dir) { 322 bool is_dir) {
323 if (!task_runner()->BelongsToCurrentThread()) { 323 if (!task_runner()->RunsTasksOnCurrentThread()) {
324 // Switch to task_runner() to access |watches_| safely. 324 // Switch to task_runner() to access |watches_| safely.
325 task_runner()->PostTask(FROM_HERE, 325 task_runner()->PostTask(FROM_HERE,
326 Bind(&FilePathWatcherImpl::OnFilePathChanged, this, 326 Bind(&FilePathWatcherImpl::OnFilePathChanged, this,
327 fired_watch, child, created, deleted, is_dir)); 327 fired_watch, child, created, deleted, is_dir));
328 return; 328 return;
329 } 329 }
330 330
331 // Check to see if CancelOnMessageLoopThreadOrInDestructor() has already been 331 // Check to see if CancelOnMessageLoopThreadOrInDestructor() has already been
332 // called. May happen when code flow reaches here from the PostTask() above. 332 // called. May happen when code flow reaches here from the PostTask() above.
333 if (watches_.empty()) { 333 if (watches_.empty()) {
334 DCHECK(target_.empty()); 334 DCHECK(target_.empty());
335 return; 335 return;
336 } 336 }
337 337
338 DCHECK(task_runner()->BelongsToCurrentThread()); 338 DCHECK(task_runner()->RunsTasksOnCurrentThread());
339 DCHECK(HasValidWatchVector()); 339 DCHECK(HasValidWatchVector());
340 340
341 // Used below to avoid multiple recursive updates. 341 // Used below to avoid multiple recursive updates.
342 bool did_update = false; 342 bool did_update = false;
343 343
344 // Find the entry in |watches_| that corresponds to |fired_watch|. 344 // Find the entry in |watches_| that corresponds to |fired_watch|.
345 for (size_t i = 0; i < watches_.size(); ++i) { 345 for (size_t i = 0; i < watches_.size(); ++i) {
346 const WatchEntry& watch_entry = watches_[i]; 346 const WatchEntry& watch_entry = watches_[i];
347 if (fired_watch != watch_entry.watch) 347 if (fired_watch != watch_entry.watch)
348 continue; 348 continue;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 UpdateRecursiveWatches(fired_watch, is_dir); 414 UpdateRecursiveWatches(fired_watch, is_dir);
415 callback_.Run(target_, false /* error */); 415 callback_.Run(target_, false /* error */);
416 } 416 }
417 } 417 }
418 418
419 bool FilePathWatcherImpl::Watch(const FilePath& path, 419 bool FilePathWatcherImpl::Watch(const FilePath& path,
420 bool recursive, 420 bool recursive,
421 const FilePathWatcher::Callback& callback) { 421 const FilePathWatcher::Callback& callback) {
422 DCHECK(target_.empty()); 422 DCHECK(target_.empty());
423 423
424 set_task_runner(ThreadTaskRunnerHandle::Get()); 424 set_task_runner(SequencedTaskRunnerHandle::Get());
425 callback_ = callback; 425 callback_ = callback;
426 target_ = path; 426 target_ = path;
427 recursive_ = recursive; 427 recursive_ = recursive;
428 428
429 std::vector<FilePath::StringType> comps; 429 std::vector<FilePath::StringType> comps;
430 target_.GetComponents(&comps); 430 target_.GetComponents(&comps);
431 DCHECK(!comps.empty()); 431 DCHECK(!comps.empty());
432 for (size_t i = 1; i < comps.size(); ++i) 432 for (size_t i = 1; i < comps.size(); ++i)
433 watches_.push_back(WatchEntry(comps[i])); 433 watches_.push_back(WatchEntry(comps[i]));
434 watches_.push_back(WatchEntry(FilePath::StringType())); 434 watches_.push_back(WatchEntry(FilePath::StringType()));
435 UpdateWatches(); 435 UpdateWatches();
436 return true; 436 return true;
437 } 437 }
438 438
439 void FilePathWatcherImpl::Cancel() { 439 void FilePathWatcherImpl::Cancel() {
440 if (callback_.is_null()) { 440 if (callback_.is_null()) {
441 // Watch was never called, or the message_loop() thread is already gone. 441 // Watch was never called, or the message_loop() thread is already gone.
442 set_cancelled(); 442 set_cancelled();
443 return; 443 return;
444 } 444 }
445 445
446 // Switch to the task_runner() if necessary so we can access |watches_|. 446 // Switch to the task_runner() if necessary so we can access |watches_|.
447 if (!task_runner()->BelongsToCurrentThread()) { 447 if (!task_runner()->RunsTasksOnCurrentThread()) {
448 task_runner()->PostTask( 448 task_runner()->PostTask(
449 FROM_HERE, 449 FROM_HERE,
450 Bind(&FilePathWatcherImpl::CancelOnMessageLoopThreadOrInDestructor, 450 Bind(&FilePathWatcherImpl::CancelOnMessageLoopThreadOrInDestructor,
451 this)); 451 this));
452 } else { 452 } else {
453 CancelOnMessageLoopThreadOrInDestructor(); 453 CancelOnMessageLoopThreadOrInDestructor();
454 } 454 }
455 } 455 }
456 456
457 void FilePathWatcherImpl::CancelOnMessageLoopThreadOrInDestructor() { 457 void FilePathWatcherImpl::CancelOnMessageLoopThreadOrInDestructor() {
458 DCHECK(in_destructor_ || task_runner()->BelongsToCurrentThread()); 458 DCHECK(in_destructor_ || task_runner()->RunsTasksOnCurrentThread());
459 459
460 if (is_cancelled()) 460 if (is_cancelled())
461 return; 461 return;
462 462
463 set_cancelled(); 463 set_cancelled();
464 464
465 if (!callback_.is_null()) 465 if (!callback_.is_null())
466 callback_.Reset(); 466 callback_.Reset();
467 467
468 for (size_t i = 0; i < watches_.size(); ++i) 468 for (size_t i = 0; i < watches_.size(); ++i)
469 g_inotify_reader.Get().RemoveWatch(watches_[i].watch, this); 469 g_inotify_reader.Get().RemoveWatch(watches_[i].watch, this);
470 watches_.clear(); 470 watches_.clear();
471 target_.clear(); 471 target_.clear();
472 472
473 if (recursive_) 473 if (recursive_)
474 RemoveRecursiveWatches(); 474 RemoveRecursiveWatches();
475 } 475 }
476 476
477 void FilePathWatcherImpl::UpdateWatches() { 477 void FilePathWatcherImpl::UpdateWatches() {
478 // Ensure this runs on the task_runner() exclusively in order to avoid 478 // Ensure this runs on the task_runner() exclusively in order to avoid
479 // concurrency issues. 479 // concurrency issues.
480 DCHECK(task_runner()->BelongsToCurrentThread()); 480 DCHECK(task_runner()->RunsTasksOnCurrentThread());
481 DCHECK(HasValidWatchVector()); 481 DCHECK(HasValidWatchVector());
482 482
483 // Walk the list of watches and update them as we go. 483 // Walk the list of watches and update them as we go.
484 FilePath path(FILE_PATH_LITERAL("/")); 484 FilePath path(FILE_PATH_LITERAL("/"));
485 for (size_t i = 0; i < watches_.size(); ++i) { 485 for (size_t i = 0; i < watches_.size(); ++i) {
486 WatchEntry& watch_entry = watches_[i]; 486 WatchEntry& watch_entry = watches_[i];
487 InotifyReader::Watch old_watch = watch_entry.watch; 487 InotifyReader::Watch old_watch = watch_entry.watch;
488 watch_entry.watch = InotifyReader::kInvalidWatch; 488 watch_entry.watch = InotifyReader::kInvalidWatch;
489 watch_entry.linkname.clear(); 489 watch_entry.linkname.clear();
490 watch_entry.watch = g_inotify_reader.Get().AddWatch(path, this); 490 watch_entry.watch = g_inotify_reader.Get().AddWatch(path, this);
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
654 } 654 }
655 655
656 } // namespace 656 } // namespace
657 657
658 FilePathWatcher::FilePathWatcher() { 658 FilePathWatcher::FilePathWatcher() {
659 sequence_checker_.DetachFromSequence(); 659 sequence_checker_.DetachFromSequence();
660 impl_ = new FilePathWatcherImpl(); 660 impl_ = new FilePathWatcherImpl();
661 } 661 }
662 662
663 } // namespace base 663 } // 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