1
2 /*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10 #include "SkEventSink.h"
11 #include "SkTagList.h"
12 #include "SkThread.h"
13
14 #include "SkThread.h"
15 #include "SkTime.h"
16
17 SK_DEFINE_INST_COUNT(SkEventSink)
18
19 class SkEventSink_Globals {
20 public:
SkEventSink_Globals()21 SkEventSink_Globals() {
22 fNextSinkID = 0;
23 fSinkHead = NULL;
24 }
25
26 SkMutex fSinkMutex;
27 SkEventSinkID fNextSinkID;
28 SkEventSink* fSinkHead;
29 };
30
getGlobals()31 static SkEventSink_Globals& getGlobals() {
32 // leak this, so we don't incur any shutdown perf hit
33 static SkEventSink_Globals* gGlobals = new SkEventSink_Globals;
34 return *gGlobals;
35 }
36
SkEventSink()37 SkEventSink::SkEventSink() : fTagHead(NULL) {
38 SkEventSink_Globals& globals = getGlobals();
39
40 globals.fSinkMutex.acquire();
41
42 fID = ++globals.fNextSinkID;
43 fNextSink = globals.fSinkHead;
44 globals.fSinkHead = this;
45
46 globals.fSinkMutex.release();
47 }
48
~SkEventSink()49 SkEventSink::~SkEventSink() {
50 SkEventSink_Globals& globals = getGlobals();
51
52 if (fTagHead)
53 SkTagList::DeleteAll(fTagHead);
54
55 globals.fSinkMutex.acquire();
56
57 SkEventSink* sink = globals.fSinkHead;
58 SkEventSink* prev = NULL;
59
60 for (;;) {
61 SkEventSink* next = sink->fNextSink;
62 if (sink == this) {
63 if (prev) {
64 prev->fNextSink = next;
65 } else {
66 globals.fSinkHead = next;
67 }
68 break;
69 }
70 prev = sink;
71 sink = next;
72 }
73 globals.fSinkMutex.release();
74 }
75
doEvent(const SkEvent & evt)76 bool SkEventSink::doEvent(const SkEvent& evt) {
77 return this->onEvent(evt);
78 }
79
doQuery(SkEvent * evt)80 bool SkEventSink::doQuery(SkEvent* evt) {
81 SkASSERT(evt);
82 return this->onQuery(evt);
83 }
84
onEvent(const SkEvent &)85 bool SkEventSink::onEvent(const SkEvent&) {
86 return false;
87 }
88
onQuery(SkEvent *)89 bool SkEventSink::onQuery(SkEvent*) {
90 return false;
91 }
92
93 ///////////////////////////////////////////////////////////////////////////////
94
findTagList(U8CPU tag) const95 SkTagList* SkEventSink::findTagList(U8CPU tag) const {
96 return fTagHead ? SkTagList::Find(fTagHead, tag) : NULL;
97 }
98
addTagList(SkTagList * rec)99 void SkEventSink::addTagList(SkTagList* rec) {
100 SkASSERT(rec);
101 SkASSERT(fTagHead == NULL || SkTagList::Find(fTagHead, rec->fTag) == NULL);
102
103 rec->fNext = fTagHead;
104 fTagHead = rec;
105 }
106
removeTagList(U8CPU tag)107 void SkEventSink::removeTagList(U8CPU tag) {
108 if (fTagHead) {
109 SkTagList::DeleteTag(&fTagHead, tag);
110 }
111 }
112
113 ///////////////////////////////////////////////////////////////////////////////
114
115 struct SkListenersTagList : SkTagList {
SkListenersTagListSkListenersTagList116 SkListenersTagList(U16CPU count) : SkTagList(kListeners_SkTagList)
117 {
118 fExtra16 = SkToU16(count);
119 fIDs = (SkEventSinkID*)sk_malloc_throw(count * sizeof(SkEventSinkID));
120 }
~SkListenersTagListSkListenersTagList121 virtual ~SkListenersTagList()
122 {
123 sk_free(fIDs);
124 }
125
countListnersSkListenersTagList126 int countListners() const { return fExtra16; }
127
findSkListenersTagList128 int find(SkEventSinkID id) const
129 {
130 const SkEventSinkID* idptr = fIDs;
131 for (int i = fExtra16 - 1; i >= 0; --i)
132 if (idptr[i] == id)
133 return i;
134 return -1;
135 }
136
137 SkEventSinkID* fIDs;
138 };
139
addListenerID(SkEventSinkID id)140 void SkEventSink::addListenerID(SkEventSinkID id)
141 {
142 if (id == 0)
143 return;
144
145 SkListenersTagList* prev = (SkListenersTagList*)this->findTagList(kListeners_SkTagList);
146 int count = 0;
147
148 if (prev)
149 {
150 if (prev->find(id) >= 0)
151 return;
152 count = prev->countListners();
153 }
154
155 SkListenersTagList* next = SkNEW_ARGS(SkListenersTagList, (count + 1));
156
157 if (prev)
158 {
159 memcpy(next->fIDs, prev->fIDs, count * sizeof(SkEventSinkID));
160 this->removeTagList(kListeners_SkTagList);
161 }
162 next->fIDs[count] = id;
163 this->addTagList(next);
164 }
165
copyListeners(const SkEventSink & sink)166 void SkEventSink::copyListeners(const SkEventSink& sink)
167 {
168 SkListenersTagList* sinkList = (SkListenersTagList*)sink.findTagList(kListeners_SkTagList);
169 if (sinkList == NULL)
170 return;
171 SkASSERT(sinkList->countListners() > 0);
172 const SkEventSinkID* iter = sinkList->fIDs;
173 const SkEventSinkID* stop = iter + sinkList->countListners();
174 while (iter < stop)
175 addListenerID(*iter++);
176 }
177
removeListenerID(SkEventSinkID id)178 void SkEventSink::removeListenerID(SkEventSinkID id)
179 {
180 if (id == 0)
181 return;
182
183 SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList);
184
185 if (list == NULL)
186 return;
187
188 int index = list->find(id);
189 if (index >= 0)
190 {
191 int count = list->countListners();
192 SkASSERT(count > 0);
193 if (count == 1)
194 this->removeTagList(kListeners_SkTagList);
195 else
196 {
197 // overwrite without resize/reallocating our struct (for speed)
198 list->fIDs[index] = list->fIDs[count - 1];
199 list->fExtra16 = SkToU16(count - 1);
200 }
201 }
202 }
203
hasListeners() const204 bool SkEventSink::hasListeners() const
205 {
206 return this->findTagList(kListeners_SkTagList) != NULL;
207 }
208
postToListeners(const SkEvent & evt,SkMSec delay)209 void SkEventSink::postToListeners(const SkEvent& evt, SkMSec delay) {
210 SkListenersTagList* list = (SkListenersTagList*)this->findTagList(kListeners_SkTagList);
211 if (list) {
212 SkASSERT(list->countListners() > 0);
213 const SkEventSinkID* iter = list->fIDs;
214 const SkEventSinkID* stop = iter + list->countListners();
215 while (iter < stop) {
216 SkEvent* copy = SkNEW_ARGS(SkEvent, (evt));
217 copy->setTargetID(*iter++)->postDelay(delay);
218 }
219 }
220 }
221
222 ///////////////////////////////////////////////////////////////////////////////
223
DoEvent(const SkEvent & evt)224 SkEventSink::EventResult SkEventSink::DoEvent(const SkEvent& evt) {
225 SkEvent::Proc proc = evt.getTargetProc();
226 if (proc) {
227 return proc(evt) ? kHandled_EventResult : kNotHandled_EventResult;
228 }
229
230 SkEventSink* sink = SkEventSink::FindSink(evt.getTargetID());
231 if (sink) {
232 return sink->doEvent(evt) ? kHandled_EventResult : kNotHandled_EventResult;
233 }
234
235 return kSinkNotFound_EventResult;
236 }
237
FindSink(SkEventSinkID sinkID)238 SkEventSink* SkEventSink::FindSink(SkEventSinkID sinkID)
239 {
240 if (sinkID == 0)
241 return 0;
242
243 SkEventSink_Globals& globals = getGlobals();
244 SkAutoMutexAcquire ac(globals.fSinkMutex);
245 SkEventSink* sink = globals.fSinkHead;
246
247 while (sink)
248 {
249 if (sink->getSinkID() == sinkID)
250 return sink;
251 sink = sink->fNextSink;
252 }
253 return NULL;
254 }
255
256 ////////////////////////////////////////////////////////////////////////////////////////
257 ////////////////////////////////////////////////////////////////////////////////////////
258
259 #if 0 // experimental, not tested
260
261 #include "SkThread.h"
262 #include "SkTDict.h"
263
264 #define kMinStringBufferSize 128
265 SK_DECLARE_STATIC_MUTEX(gNamedSinkMutex);
266 static SkTDict<SkEventSinkID> gNamedSinkIDs(kMinStringBufferSize);
267
268 /** Register a name/id pair with the system. If the name already exists,
269 replace its ID with the new id. This pair will persist until UnregisterNamedSink()
270 is called.
271 */
272 void SkEventSink::RegisterNamedSinkID(const char name[], SkEventSinkID id)
273 {
274 if (id && name && *name)
275 {
276 SkAutoMutexAcquire ac(gNamedSinkMutex);
277 gNamedSinkIDs.set(name, id);
278 }
279 }
280
281 /** Return the id that matches the specified name (from a previous call to
282 RegisterNamedSinkID(). If no match is found, return 0
283 */
284 SkEventSinkID SkEventSink::FindNamedSinkID(const char name[])
285 {
286 SkEventSinkID id = 0;
287
288 if (name && *name)
289 {
290 SkAutoMutexAcquire ac(gNamedSinkMutex);
291 (void)gNamedSinkIDs.find(name, &id);
292 }
293 return id;
294 }
295
296 /** Remove all name/id pairs from the system. This is call internally
297 on shutdown, to ensure no memory leaks. It should not be called
298 before shutdown.
299 */
300 void SkEventSink::RemoveAllNamedSinkIDs()
301 {
302 SkAutoMutexAcquire ac(gNamedSinkMutex);
303 (void)gNamedSinkIDs.reset();
304 }
305 #endif
306