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

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

Issue 2523573002: Remove destruction observer from file_path_watcher_win.cc (Closed)
Patch Set: self-review Created 4 years, 1 month 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 | « no previous file | no next file » | 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/files/file.h" 8 #include "base/files/file.h"
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/memory/ref_counted.h" 13 #include "base/memory/ref_counted.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/threading/thread_task_runner_handle.h" 14 #include "base/threading/thread_task_runner_handle.h"
16 #include "base/time/time.h" 15 #include "base/time/time.h"
17 #include "base/win/object_watcher.h" 16 #include "base/win/object_watcher.h"
18 17
19 namespace base { 18 namespace base {
20 19
21 namespace { 20 namespace {
22 21
23 class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate, 22 class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate,
24 public base::win::ObjectWatcher::Delegate, 23 public base::win::ObjectWatcher::Delegate {
25 public MessageLoop::DestructionObserver {
26 public: 24 public:
27 FilePathWatcherImpl() 25 FilePathWatcherImpl()
28 : handle_(INVALID_HANDLE_VALUE), 26 : handle_(INVALID_HANDLE_VALUE),
29 recursive_watch_(false) {} 27 recursive_watch_(false) {}
30 28
31 // FilePathWatcher::PlatformDelegate overrides. 29 // FilePathWatcher::PlatformDelegate:
32 bool Watch(const FilePath& path, 30 bool Watch(const FilePath& path,
33 bool recursive, 31 bool recursive,
34 const FilePathWatcher::Callback& callback) override; 32 const FilePathWatcher::Callback& callback) override;
35 void Cancel() override; 33 void Cancel() override;
36 34
37 // Deletion of the FilePathWatcher will call Cancel() to dispose of this 35 // base::win::ObjectWatcher::Delegate:
38 // object in the right thread. This also observes destruction of the required
39 // cleanup thread, in case it quits before Cancel() is called.
40 void WillDestroyCurrentMessageLoop() override;
41
42 // Callback from MessageLoopForIO.
43 void OnObjectSignaled(HANDLE object) override; 36 void OnObjectSignaled(HANDLE object) override;
44 37
45 private: 38 private:
46 ~FilePathWatcherImpl() override {} 39 ~FilePathWatcherImpl() override {}
47 40
48 // Setup a watch handle for directory |dir|. Set |recursive| to true to watch 41 // Setup a watch handle for directory |dir|. Set |recursive| to true to watch
49 // the directory sub trees. Returns true if no fatal error occurs. |handle| 42 // the directory sub trees. Returns true if no fatal error occurs. |handle|
50 // will receive the handle value if |dir| is watchable, otherwise 43 // will receive the handle value if |dir| is watchable, otherwise
51 // INVALID_HANDLE_VALUE. 44 // INVALID_HANDLE_VALUE.
52 static bool SetupWatchHandle(const FilePath& dir, 45 static bool SetupWatchHandle(const FilePath& dir,
53 bool recursive, 46 bool recursive,
54 HANDLE* handle) WARN_UNUSED_RESULT; 47 HANDLE* handle) WARN_UNUSED_RESULT;
55 48
56 // (Re-)Initialize the watch handle. 49 // (Re-)Initialize the watch handle.
57 bool UpdateWatch() WARN_UNUSED_RESULT; 50 bool UpdateWatch() WARN_UNUSED_RESULT;
58 51
59 // Destroy the watch handle. 52 // Destroy the watch handle.
60 void DestroyWatch(); 53 void DestroyWatch();
61 54
62 // Cleans up and stops observing the |task_runner_| thread.
63 void CancelOnMessageLoopThread();
64
65 // Callback to notify upon changes. 55 // Callback to notify upon changes.
66 FilePathWatcher::Callback callback_; 56 FilePathWatcher::Callback callback_;
67 57
68 // Path we're supposed to watch (passed to callback). 58 // Path we're supposed to watch (passed to callback).
69 FilePath target_; 59 FilePath target_;
70 60
71 // Handle for FindFirstChangeNotification. 61 // Handle for FindFirstChangeNotification.
72 HANDLE handle_; 62 HANDLE handle_;
73 63
74 // ObjectWatcher to watch handle_ for events. 64 // ObjectWatcher to watch handle_ for events.
(...skipping 15 matching lines...) Expand all
90 80
91 bool FilePathWatcherImpl::Watch(const FilePath& path, 81 bool FilePathWatcherImpl::Watch(const FilePath& path,
92 bool recursive, 82 bool recursive,
93 const FilePathWatcher::Callback& callback) { 83 const FilePathWatcher::Callback& callback) {
94 DCHECK(target_.value().empty()); // Can only watch one path. 84 DCHECK(target_.value().empty()); // Can only watch one path.
95 85
96 set_task_runner(ThreadTaskRunnerHandle::Get()); 86 set_task_runner(ThreadTaskRunnerHandle::Get());
97 callback_ = callback; 87 callback_ = callback;
98 target_ = path; 88 target_ = path;
99 recursive_watch_ = recursive; 89 recursive_watch_ = recursive;
100 MessageLoop::current()->AddDestructionObserver(this);
101 90
102 File::Info file_info; 91 File::Info file_info;
103 if (GetFileInfo(target_, &file_info)) { 92 if (GetFileInfo(target_, &file_info)) {
104 last_modified_ = file_info.last_modified; 93 last_modified_ = file_info.last_modified;
105 first_notification_ = Time::Now(); 94 first_notification_ = Time::Now();
106 } 95 }
107 96
108 if (!UpdateWatch()) 97 if (!UpdateWatch())
109 return false; 98 return false;
110 99
111 watcher_.StartWatchingOnce(handle_, this); 100 watcher_.StartWatchingOnce(handle_, this);
112 101
113 return true; 102 return true;
114 } 103 }
115 104
116 void FilePathWatcherImpl::Cancel() { 105 void FilePathWatcherImpl::Cancel() {
117 if (callback_.is_null()) { 106 if (callback_.is_null()) {
118 // Watch was never called, or the |task_runner_| has already quit. 107 // Watch was never called, or the |task_runner_| has already quit.
119 set_cancelled(); 108 set_cancelled();
120 return; 109 return;
121 } 110 }
122 111
123 // Switch to the file thread if necessary so we can stop |watcher_|.
124 if (!task_runner()->BelongsToCurrentThread()) {
125 task_runner()->PostTask(
126 FROM_HERE, Bind(&FilePathWatcherImpl::CancelOnMessageLoopThread, this));
127 } else {
128 CancelOnMessageLoopThread();
129 }
130 }
131
132 void FilePathWatcherImpl::CancelOnMessageLoopThread() {
133 DCHECK(task_runner()->BelongsToCurrentThread()); 112 DCHECK(task_runner()->BelongsToCurrentThread());
134 set_cancelled(); 113 set_cancelled();
135 114
136 if (handle_ != INVALID_HANDLE_VALUE) 115 if (handle_ != INVALID_HANDLE_VALUE)
137 DestroyWatch(); 116 DestroyWatch();
138 117
139 if (!callback_.is_null()) { 118 callback_.Reset();
140 MessageLoop::current()->RemoveDestructionObserver(this);
141 callback_.Reset();
142 }
143 }
144
145 void FilePathWatcherImpl::WillDestroyCurrentMessageLoop() {
146 CancelOnMessageLoopThread();
147 } 119 }
148 120
149 void FilePathWatcherImpl::OnObjectSignaled(HANDLE object) { 121 void FilePathWatcherImpl::OnObjectSignaled(HANDLE object) {
150 DCHECK(object == handle_); 122 DCHECK(object == handle_);
151 // Make sure we stay alive through the body of this function. 123 // Make sure we stay alive through the body of this function.
152 scoped_refptr<FilePathWatcherImpl> keep_alive(this); 124 scoped_refptr<FilePathWatcherImpl> keep_alive(this);
153 125
154 if (!UpdateWatch()) { 126 if (!UpdateWatch()) {
155 callback_.Run(target_, true /* error */); 127 callback_.Run(target_, true /* error */);
156 return; 128 return;
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 } 266 }
295 267
296 } // namespace 268 } // namespace
297 269
298 FilePathWatcher::FilePathWatcher() { 270 FilePathWatcher::FilePathWatcher() {
299 sequence_checker_.DetachFromSequence(); 271 sequence_checker_.DetachFromSequence();
300 impl_ = new FilePathWatcherImpl(); 272 impl_ = new FilePathWatcherImpl();
301 } 273 }
302 274
303 } // namespace base 275 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698