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

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: Introduced CancelTask to simplify cleanup. 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 {
Mattias Nissler (ping if slow) 2011/03/22 17:23:44 missing space before :
Joao da Silva 2011/03/22 17:42:33 Done.
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_;
Mattias Nissler (ping if slow) 2011/03/22 17:23:44 DISALLOW_COPY_AND_ASSIGN
Joao da Silva 2011/03/22 17:42:33 Done.
53 }; 66 };
54 67
55 // Used internally to encapsulate different members on different platforms. 68 // Used internally to encapsulate different members on different platforms.
56 class PlatformDelegate 69 class PlatformDelegate: public base::RefCountedThreadSafe<PlatformDelegate> {
57 : public base::RefCountedThreadSafe<PlatformDelegate,
58 DeletePlatformDelegate> {
59 public: 70 public:
60 PlatformDelegate(); 71 PlatformDelegate();
61 72
62 // Start watching for the given |path| and notify |delegate| about changes. 73 // 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 74 // |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 75 // backed by a CFRunLoop based MessagePump. This is usually going to be a
65 // MessageLoop of type TYPE_UI. 76 // MessageLoop of type TYPE_UI.
66 virtual bool Watch( 77 virtual bool Watch(
67 const FilePath& path, 78 const FilePath& path,
68 Delegate* delegate, 79 Delegate* delegate,
69 base::MessageLoopProxy* loop) WARN_UNUSED_RESULT = 0; 80 base::MessageLoopProxy* loop) WARN_UNUSED_RESULT = 0;
70 81
71 // Stop watching. This is called from FilePathWatcher's dtor in order to 82 // Stop watching. This is called from FilePathWatcher's dtor in order to
72 // allow to shut down properly while the object is still alive. 83 // allow to shut down properly while the object is still alive.
84 // It can be called from any thread.
73 virtual void Cancel() = 0; 85 virtual void Cancel() = 0;
74 86
75 protected: 87 protected:
76 friend class DeleteTask<PlatformDelegate>; 88 virtual ~PlatformDelegate();
77 friend struct DeletePlatformDelegate;
78 89
79 virtual ~PlatformDelegate(); 90 // Stop watching. This is only called on the thread of the appropriate
91 // message loop. Since it can also be called more than once, it should
92 // check |is_cancelled()| to avoid duplicate work.
93 virtual void CancelOnMessageLoopThread() = 0;
80 94
81 scoped_refptr<base::MessageLoopProxy> message_loop() const { 95 scoped_refptr<base::MessageLoopProxy> message_loop() const {
82 return message_loop_; 96 return message_loop_;
83 } 97 }
84 98
85 void set_message_loop(base::MessageLoopProxy* loop) { 99 void set_message_loop(base::MessageLoopProxy* loop) {
86 message_loop_ = loop; 100 message_loop_ = loop;
87 } 101 }
88 102
103 // Must be called before the PlatformDelegate is deleted.
104 void set_cancelled() {
105 cancelled_ = true;
106 }
107
108 bool is_cancelled() const {
109 return cancelled_;
110 }
111
89 private: 112 private:
113 friend class base::RefCountedThreadSafe<PlatformDelegate>;
114 friend class CancelTask;
115
90 scoped_refptr<base::MessageLoopProxy> message_loop_; 116 scoped_refptr<base::MessageLoopProxy> message_loop_;
117 bool cancelled_;
91 }; 118 };
92 119
93 private: 120 private:
94 scoped_refptr<PlatformDelegate> impl_; 121 scoped_refptr<PlatformDelegate> impl_;
95 122
96 DISALLOW_COPY_AND_ASSIGN(FilePathWatcher); 123 DISALLOW_COPY_AND_ASSIGN(FilePathWatcher);
97 }; 124 };
98 125
99 #endif // CONTENT_COMMON_FILE_PATH_WATCHER_FILE_PATH_WATCHER_H_ 126 #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