• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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