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

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

Issue 2596273003: Remove ref-counting from FilePathWatcher. (Closed)
Patch Set: fix mac build error Created 3 years, 11 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_stub.cc ('k') | 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/ptr_util.h"
14 #include "base/threading/sequenced_task_runner_handle.h" 14 #include "base/threading/sequenced_task_runner_handle.h"
15 #include "base/time/time.h" 15 #include "base/time/time.h"
16 #include "base/win/object_watcher.h" 16 #include "base/win/object_watcher.h"
17 17
18 namespace base { 18 namespace base {
19 19
20 namespace { 20 namespace {
21 21
22 class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate, 22 class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate,
23 public base::win::ObjectWatcher::Delegate { 23 public base::win::ObjectWatcher::Delegate {
24 public: 24 public:
25 FilePathWatcherImpl() 25 FilePathWatcherImpl()
26 : handle_(INVALID_HANDLE_VALUE), 26 : handle_(INVALID_HANDLE_VALUE),
27 recursive_watch_(false) {} 27 recursive_watch_(false) {}
28 ~FilePathWatcherImpl() override;
28 29
29 // FilePathWatcher::PlatformDelegate: 30 // FilePathWatcher::PlatformDelegate:
30 bool Watch(const FilePath& path, 31 bool Watch(const FilePath& path,
31 bool recursive, 32 bool recursive,
32 const FilePathWatcher::Callback& callback) override; 33 const FilePathWatcher::Callback& callback) override;
33 void Cancel() override; 34 void Cancel() override;
34 35
35 // base::win::ObjectWatcher::Delegate: 36 // base::win::ObjectWatcher::Delegate:
36 void OnObjectSignaled(HANDLE object) override; 37 void OnObjectSignaled(HANDLE object) override;
37 38
38 private: 39 private:
39 ~FilePathWatcherImpl() override {}
40
41 // Setup a watch handle for directory |dir|. Set |recursive| to true to watch 40 // Setup a watch handle for directory |dir|. Set |recursive| to true to watch
42 // the directory sub trees. Returns true if no fatal error occurs. |handle| 41 // the directory sub trees. Returns true if no fatal error occurs. |handle|
43 // will receive the handle value if |dir| is watchable, otherwise 42 // will receive the handle value if |dir| is watchable, otherwise
44 // INVALID_HANDLE_VALUE. 43 // INVALID_HANDLE_VALUE.
45 static bool SetupWatchHandle(const FilePath& dir, 44 static bool SetupWatchHandle(const FilePath& dir,
46 bool recursive, 45 bool recursive,
47 HANDLE* handle) WARN_UNUSED_RESULT; 46 HANDLE* handle) WARN_UNUSED_RESULT;
48 47
49 // (Re-)Initialize the watch handle. 48 // (Re-)Initialize the watch handle.
50 bool UpdateWatch() WARN_UNUSED_RESULT; 49 bool UpdateWatch() WARN_UNUSED_RESULT;
51 50
52 // Destroy the watch handle. 51 // Destroy the watch handle.
53 void DestroyWatch(); 52 void DestroyWatch();
54 53
55 // Callback to notify upon changes. 54 // Callback to notify upon changes.
56 FilePathWatcher::Callback callback_; 55 FilePathWatcher::Callback callback_;
57 56
58 // Path we're supposed to watch (passed to callback). 57 // Path we're supposed to watch (passed to callback).
59 FilePath target_; 58 FilePath target_;
60 59
60 // Set to true in the destructor.
61 bool* was_deleted_ptr_ = nullptr;
62
61 // Handle for FindFirstChangeNotification. 63 // Handle for FindFirstChangeNotification.
62 HANDLE handle_; 64 HANDLE handle_;
63 65
64 // ObjectWatcher to watch handle_ for events. 66 // ObjectWatcher to watch handle_ for events.
65 base::win::ObjectWatcher watcher_; 67 base::win::ObjectWatcher watcher_;
66 68
67 // Set to true to watch the sub trees of the specified directory file path. 69 // Set to true to watch the sub trees of the specified directory file path.
68 bool recursive_watch_; 70 bool recursive_watch_;
69 71
70 // Keep track of the last modified time of the file. We use nulltime 72 // Keep track of the last modified time of the file. We use nulltime
71 // to represent the file not existing. 73 // to represent the file not existing.
72 Time last_modified_; 74 Time last_modified_;
73 75
74 // The time at which we processed the first notification with the 76 // The time at which we processed the first notification with the
75 // |last_modified_| time stamp. 77 // |last_modified_| time stamp.
76 Time first_notification_; 78 Time first_notification_;
77 79
78 DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl); 80 DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl);
79 }; 81 };
80 82
83 FilePathWatcherImpl::~FilePathWatcherImpl() {
84 DCHECK(!task_runner() || task_runner()->RunsTasksOnCurrentThread());
85 if (was_deleted_ptr_)
86 *was_deleted_ptr_ = true;
87 }
88
81 bool FilePathWatcherImpl::Watch(const FilePath& path, 89 bool FilePathWatcherImpl::Watch(const FilePath& path,
82 bool recursive, 90 bool recursive,
83 const FilePathWatcher::Callback& callback) { 91 const FilePathWatcher::Callback& callback) {
84 DCHECK(target_.value().empty()); // Can only watch one path. 92 DCHECK(target_.value().empty()); // Can only watch one path.
85 93
86 set_task_runner(SequencedTaskRunnerHandle::Get()); 94 set_task_runner(SequencedTaskRunnerHandle::Get());
87 callback_ = callback; 95 callback_ = callback;
88 target_ = path; 96 target_ = path;
89 recursive_watch_ = recursive; 97 recursive_watch_ = recursive;
90 98
(...skipping 21 matching lines...) Expand all
112 DCHECK(task_runner()->RunsTasksOnCurrentThread()); 120 DCHECK(task_runner()->RunsTasksOnCurrentThread());
113 set_cancelled(); 121 set_cancelled();
114 122
115 if (handle_ != INVALID_HANDLE_VALUE) 123 if (handle_ != INVALID_HANDLE_VALUE)
116 DestroyWatch(); 124 DestroyWatch();
117 125
118 callback_.Reset(); 126 callback_.Reset();
119 } 127 }
120 128
121 void FilePathWatcherImpl::OnObjectSignaled(HANDLE object) { 129 void FilePathWatcherImpl::OnObjectSignaled(HANDLE object) {
122 DCHECK(object == handle_); 130 DCHECK(task_runner()->RunsTasksOnCurrentThread());
123 // Make sure we stay alive through the body of this function. 131 DCHECK_EQ(object, handle_);
124 scoped_refptr<FilePathWatcherImpl> keep_alive(this); 132 DCHECK(!was_deleted_ptr_);
133
134 bool was_deleted = false;
135 was_deleted_ptr_ = &was_deleted;
125 136
126 if (!UpdateWatch()) { 137 if (!UpdateWatch()) {
127 callback_.Run(target_, true /* error */); 138 callback_.Run(target_, true /* error */);
128 return; 139 return;
129 } 140 }
130 141
131 // Check whether the event applies to |target_| and notify the callback. 142 // Check whether the event applies to |target_| and notify the callback.
132 File::Info file_info; 143 File::Info file_info;
133 bool file_exists = GetFileInfo(target_, &file_info); 144 bool file_exists = GetFileInfo(target_, &file_info);
134 if (recursive_watch_) { 145 if (recursive_watch_) {
(...skipping 29 matching lines...) Expand all
164 // Stop further notifications for this |last_modification_| time stamp. 175 // Stop further notifications for this |last_modification_| time stamp.
165 first_notification_ = Time(); 176 first_notification_ = Time();
166 } 177 }
167 callback_.Run(target_, false); 178 callback_.Run(target_, false);
168 } else if (!file_exists && !last_modified_.is_null()) { 179 } else if (!file_exists && !last_modified_.is_null()) {
169 last_modified_ = Time(); 180 last_modified_ = Time();
170 callback_.Run(target_, false); 181 callback_.Run(target_, false);
171 } 182 }
172 183
173 // The watch may have been cancelled by the callback. 184 // The watch may have been cancelled by the callback.
174 if (handle_ != INVALID_HANDLE_VALUE) 185 if (!was_deleted) {
175 watcher_.StartWatchingOnce(handle_, this); 186 watcher_.StartWatchingOnce(handle_, this);
187 was_deleted_ptr_ = nullptr;
188 }
176 } 189 }
177 190
178 // static 191 // static
179 bool FilePathWatcherImpl::SetupWatchHandle(const FilePath& dir, 192 bool FilePathWatcherImpl::SetupWatchHandle(const FilePath& dir,
180 bool recursive, 193 bool recursive,
181 HANDLE* handle) { 194 HANDLE* handle) {
182 *handle = FindFirstChangeNotification( 195 *handle = FindFirstChangeNotification(
183 dir.value().c_str(), 196 dir.value().c_str(),
184 recursive, 197 recursive,
185 FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE | 198 FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 void FilePathWatcherImpl::DestroyWatch() { 275 void FilePathWatcherImpl::DestroyWatch() {
263 watcher_.StopWatching(); 276 watcher_.StopWatching();
264 FindCloseChangeNotification(handle_); 277 FindCloseChangeNotification(handle_);
265 handle_ = INVALID_HANDLE_VALUE; 278 handle_ = INVALID_HANDLE_VALUE;
266 } 279 }
267 280
268 } // namespace 281 } // namespace
269 282
270 FilePathWatcher::FilePathWatcher() { 283 FilePathWatcher::FilePathWatcher() {
271 sequence_checker_.DetachFromSequence(); 284 sequence_checker_.DetachFromSequence();
272 impl_ = new FilePathWatcherImpl(); 285 impl_ = MakeUnique<FilePathWatcherImpl>();
273 } 286 }
274 287
275 } // namespace base 288 } // namespace base
OLDNEW
« no previous file with comments | « base/files/file_path_watcher_stub.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698