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

Side by Side Diff: chrome/browser/sync/util/channel.h

Issue 2075012: Replace changes_channel with an observer list. (Closed)
Patch Set: Ready for checkin Created 10 years, 6 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 | « chrome/browser/sync/syncable/syncable.cc ('k') | chrome/browser/sync/util/channel_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef CHROME_BROWSER_SYNC_UTIL_CHANNEL_H_
6 #define CHROME_BROWSER_SYNC_UTIL_CHANNEL_H_
7
8 ///////////////////////////////////////////////////////////////////////////////
9 //
10 // OVERVIEW:
11 //
12 // A threadsafe container for a list of observers. Observers are able to
13 // remove themselves during iteration, and can be added on any thread. This
14 // allows observers to safely remove themselves during notifications. It
15 // also provides a handler when an observer is added that will remove the
16 // observer on destruction.
17 //
18 // It is expected that all observers are removed before destruction.
19 // The channel owner should notify all observers to disconnect on shutdown if
20 // needed to ensure this.
21 //
22 // TYPICAL USAGE:
23 //
24 // class MyWidget {
25 // public:
26 // ...
27 //
28 // class Observer : public ChannelEventHandler<FooEvent> {
29 // public:
30 // virtual void HandleChannelEvent(const FooEvent& w) = 0;
31 // };
32 //
33 // ChannelHookup<MyEvent>* AddObserver(Observer* obs) {
34 // return channel_.AddObserver(obs);
35 // }
36 //
37 // void RemoveObserver(Observer* obs) {
38 // channel_.RemoveObserver(obs);
39 // }
40 //
41 // void NotifyFoo(FooEvent& event) {
42 // channel_.Notify(event);
43 // }
44 //
45 // private:
46 // Channel<FooEvent> channel_;
47 // };
48 //
49 //
50 ///////////////////////////////////////////////////////////////////////////////
51
52 #include "base/lock.h"
53 #include "base/observer_list.h"
54
55 namespace browser_sync {
56
57 template <typename EventType>
58 class Channel;
59
60 class EventHandler {
61 };
62
63 template <typename EventType>
64 class ChannelEventHandler : public EventHandler {
65 public:
66 virtual void HandleChannelEvent(const EventType& event) = 0;
67 };
68
69 // This class manages a connection to a channel. When it is destroyed, it
70 // will remove the listener from the channel observer list.
71 template <typename EventType>
72 class ChannelHookup {
73 public:
74 ChannelHookup(Channel<EventType>* channel,
75 browser_sync::ChannelEventHandler<EventType>* handler)
76 : channel_(channel),
77 handler_(handler) {}
78 ~ChannelHookup() {
79 channel_->RemoveObserver(handler_);
80 }
81
82 private:
83 Channel<EventType>* channel_;
84 browser_sync::ChannelEventHandler<EventType>* handler_;
85 };
86
87 template <typename EventType>
88 class Channel {
89 public:
90 typedef ObserverListBase<EventHandler> ChannelObserverList;
91
92 Channel() : locking_thread_(0) {}
93
94 ChannelHookup<EventType>* AddObserver(
95 ChannelEventHandler<EventType>* observer) {
96 AutoLock scoped_lock(event_handlers_mutex_);
97 event_handlers_.AddObserver(observer);
98 return new ChannelHookup<EventType>(this, observer);
99 }
100
101 void RemoveObserver(ChannelEventHandler<EventType>* observer) {
102 // This can be called in response to a notification, so we may already have
103 // locked this channel on this thread.
104 bool need_lock = (locking_thread_ != PlatformThread::CurrentId());
105 if (need_lock)
106 event_handlers_mutex_.Acquire();
107
108 event_handlers_mutex_.AssertAcquired();
109 event_handlers_.RemoveObserver(observer);
110 if (need_lock)
111 event_handlers_mutex_.Release();
112 }
113
114 void Notify(const EventType& event) {
115 AutoLock scoped_lock(event_handlers_mutex_);
116
117 // This may result in an observer trying to remove itself, so keep track
118 // of the thread we're locked on.
119 locking_thread_ = PlatformThread::CurrentId();
120
121 ChannelObserverList::Iterator it(event_handlers_);
122 EventHandler* obs;
123 while ((obs = it.GetNext()) != NULL) {
124 static_cast<ChannelEventHandler<EventType>* >(obs)->
125 HandleChannelEvent(event);
126 }
127
128 // Set back to an invalid thread id.
129 locking_thread_ = 0;
130 }
131
132 private:
133 Lock event_handlers_mutex_;
134 PlatformThreadId locking_thread_;
135 ObserverList<EventHandler> event_handlers_;
136 };
137
138 } // namespace browser_sync
139
140 #endif // CHROME_BROWSER_SYNC_UTIL_CHANNEL_H_
OLDNEW
« no previous file with comments | « chrome/browser/sync/syncable/syncable.cc ('k') | chrome/browser/sync/util/channel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698