• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/private/SkIDChangeListener.h"
9 
10 /**
11  * Used to be notified when a gen/unique ID is invalidated, typically to preemptively purge
12  * associated items from a cache that are no longer reachable. The listener can
13  * be marked for deregistration if the cached item is remove before the listener is
14  * triggered. This prevents unbounded listener growth when cache items are routinely
15  * removed before the gen ID/unique ID is invalidated.
16  */
17 
SkIDChangeListener()18 SkIDChangeListener::SkIDChangeListener() : fShouldDeregister(false) {}
19 
20 SkIDChangeListener::~SkIDChangeListener() = default;
21 
22 using List = SkIDChangeListener::List;
23 
24 List::List() = default;
25 
~List()26 List::~List() {
27     // We don't need the mutex. No other thread should have this list while it's being
28     // destroyed.
29     for (int i = 0; i < fListeners.count(); ++i) {
30         if (!fListeners[i]->shouldDeregister()) {
31             fListeners[i]->changed();
32         }
33         fListeners[i]->unref();
34     }
35 }
36 
add(sk_sp<SkIDChangeListener> listener)37 void List::add(sk_sp<SkIDChangeListener> listener) {
38     if (!listener) {
39         return;
40     }
41     SkASSERT(!listener->shouldDeregister());
42 
43     SkAutoMutexExclusive lock(fMutex);
44     // Clean out any stale listeners before we append the new one.
45     for (int i = 0; i < fListeners.count(); ++i) {
46         if (fListeners[i]->shouldDeregister()) {
47             fListeners[i]->unref();
48             fListeners.removeShuffle(i--);  // No need to preserve the order after i.
49         }
50     }
51     *fListeners.append() = listener.release();
52 }
53 
count() const54 int List::count() const {
55     SkAutoMutexExclusive lock(fMutex);
56     return fListeners.count();
57 }
58 
changed()59 void List::changed() {
60     SkAutoMutexExclusive lock(fMutex);
61     for (SkIDChangeListener* listener : fListeners) {
62         if (!listener->shouldDeregister()) {
63             listener->changed();
64         }
65         // Listeners get at most one shot, so whether these triggered or not, blow them away.
66         listener->unref();
67     }
68     fListeners.reset();
69 }
70 
reset()71 void List::reset() {
72     SkAutoMutexExclusive lock(fMutex);
73     fListeners.unrefAll();
74 }
75