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

Side by Side Diff: content/common/file_path_watcher/file_path_watcher.h

Issue 6697020: Fixed shutdown concurrency issues in FilePathWatcher. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Small fixes. Created 9 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | content/common/file_path_watcher/file_path_watcher.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) 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 // This module provides a way to monitor a file or directory for changes. 5 // This module provides a way to monitor a file or directory for changes.
6 6
7 #ifndef CONTENT_COMMON_FILE_PATH_WATCHER_FILE_PATH_WATCHER_H_ 7 #ifndef CONTENT_COMMON_FILE_PATH_WATCHER_FILE_PATH_WATCHER_H_
8 #define CONTENT_COMMON_FILE_PATH_WATCHER_FILE_PATH_WATCHER_H_ 8 #define CONTENT_COMMON_FILE_PATH_WATCHER_FILE_PATH_WATCHER_H_
9 #pragma once 9 #pragma once
10 10
(...skipping 22 matching lines...) Expand all
33 }; 33 };
34 34
35 FilePathWatcher(); 35 FilePathWatcher();
36 ~FilePathWatcher(); 36 ~FilePathWatcher();
37 37
38 // Register interest in any changes on |path|. OnPathChanged will be called 38 // Register interest in any changes on |path|. OnPathChanged will be called
39 // back for each change. Returns true on success. |loop| is only used 39 // back for each change. Returns true on success. |loop| is only used
40 // by the Mac implementation right now, and must be backed by a CFRunLoop 40 // by the Mac implementation right now, and must be backed by a CFRunLoop
41 // based MessagePump. This is usually going to be a MessageLoop of type 41 // based MessagePump. This is usually going to be a MessageLoop of type
42 // TYPE_UI. 42 // TYPE_UI.
43 // OnFilePathChanged() will be called on the same thread as Watch() is called,
44 // which should have a MessageLoop of TYPE_IO.
43 bool Watch(const FilePath& path, 45 bool Watch(const FilePath& path,
44 Delegate* delegate, 46 Delegate* delegate,
45 base::MessageLoopProxy* loop) WARN_UNUSED_RESULT; 47 base::MessageLoopProxy* loop) WARN_UNUSED_RESULT;
46 48
47 class PlatformDelegate; 49 class PlatformDelegate;
48 50
49 // Traits for PlatformDelegate, which must delete itself on the IO message 51 // A custom Task that always cleans up the PlatformDelegate, either when
50 // loop that Watch was called from. 52 // executed or when deleted without having been executed at all, as can
51 struct DeletePlatformDelegate { 53 // happen during shutdown.
52 static void Destruct(const PlatformDelegate* delegate); 54 class CancelTask : public Task {
55 public:
56 CancelTask(PlatformDelegate* delegate): delegate_(delegate) {}
57 virtual ~CancelTask() {
58 delegate_->CancelOnMessageLoopThread();
59 }
60
61 virtual void Run() {
62 delegate_->CancelOnMessageLoopThread();
63 }
64 private:
65 scoped_refptr<PlatformDelegate> delegate_;
66
67 DISALLOW_COPY_AND_ASSIGN(CancelTask);
53 }; 68 };
54 69
55 // Used internally to encapsulate different members on different platforms. 70 // Used internally to encapsulate different members on different platforms.
56 class PlatformDelegate 71 class PlatformDelegate : public base::RefCountedThreadSafe<PlatformDelegate> {
57 : public base::RefCountedThreadSafe<PlatformDelegate,
58 DeletePlatformDelegate> {
59 public: 72 public:
60 PlatformDelegate(); 73 PlatformDelegate();
61 74
62 // Start watching for the given |path| and notify |delegate| about changes. 75 // Start watching for the given |path| and notify |delegate| about changes.
63 // |loop| is only used by the Mac implementation right now, and must be 76 // |loop| is only used by the Mac implementation right now, and must be
64 // backed by a CFRunLoop based MessagePump. This is usually going to be a 77 // backed by a CFRunLoop based MessagePump. This is usually going to be a
65 // MessageLoop of type TYPE_UI. 78 // MessageLoop of type TYPE_UI.
66 virtual bool Watch( 79 virtual bool Watch(
67 const FilePath& path, 80 const FilePath& path,
68 Delegate* delegate, 81 Delegate* delegate,
69 base::MessageLoopProxy* loop) WARN_UNUSED_RESULT = 0; 82 base::MessageLoopProxy* loop) WARN_UNUSED_RESULT = 0;
70 83
71 // Stop watching. This is called from FilePathWatcher's dtor in order to 84 // Stop watching. This is called from FilePathWatcher's dtor in order to
72 // allow to shut down properly while the object is still alive. 85 // allow to shut down properly while the object is still alive.
86 // It can be called from any thread.
73 virtual void Cancel() = 0; 87 virtual void Cancel() = 0;
74 88
75 protected: 89 protected:
76 friend class DeleteTask<PlatformDelegate>; 90 virtual ~PlatformDelegate();
77 friend struct DeletePlatformDelegate;
78 91
79 virtual ~PlatformDelegate(); 92 // Stop watching. This is only called on the thread of the appropriate
93 // message loop. Since it can also be called more than once, it should
94 // check |is_cancelled()| to avoid duplicate work.
95 virtual void CancelOnMessageLoopThread() = 0;
80 96
81 scoped_refptr<base::MessageLoopProxy> message_loop() const { 97 scoped_refptr<base::MessageLoopProxy> message_loop() const {
82 return message_loop_; 98 return message_loop_;
83 } 99 }
84 100
85 void set_message_loop(base::MessageLoopProxy* loop) { 101 void set_message_loop(base::MessageLoopProxy* loop) {
86 message_loop_ = loop; 102 message_loop_ = loop;
87 } 103 }
88 104
105 // Must be called before the PlatformDelegate is deleted.
106 void set_cancelled() {
107 cancelled_ = true;
108 }
109
110 bool is_cancelled() const {
111 return cancelled_;
112 }
113
89 private: 114 private:
115 friend class base::RefCountedThreadSafe<PlatformDelegate>;
116 friend class CancelTask;
117
90 scoped_refptr<base::MessageLoopProxy> message_loop_; 118 scoped_refptr<base::MessageLoopProxy> message_loop_;
119 bool cancelled_;
91 }; 120 };
92 121
93 private: 122 private:
94 scoped_refptr<PlatformDelegate> impl_; 123 scoped_refptr<PlatformDelegate> impl_;
95 124
96 DISALLOW_COPY_AND_ASSIGN(FilePathWatcher); 125 DISALLOW_COPY_AND_ASSIGN(FilePathWatcher);
97 }; 126 };
98 127
99 #endif // CONTENT_COMMON_FILE_PATH_WATCHER_FILE_PATH_WATCHER_H_ 128 #endif // CONTENT_COMMON_FILE_PATH_WATCHER_FILE_PATH_WATCHER_H_
OLDNEW
« no previous file with comments | « no previous file | content/common/file_path_watcher/file_path_watcher.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698