xref: /aosp_15_r20/external/skia/src/core/SkIDChangeListener.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 #include "include/private/base/SkAssert.h"
11 
12 #include <utility>
13 /**
14  * Used to be notified when a gen/unique ID is invalidated, typically to preemptively purge
15  * associated items from a cache that are no longer reachable. The listener can
16  * be marked for deregistration if the cached item is remove before the listener is
17  * triggered. This prevents unbounded listener growth when cache items are routinely
18  * removed before the gen ID/unique ID is invalidated.
19  */
20 
SkIDChangeListener()21 SkIDChangeListener::SkIDChangeListener() : fShouldDeregister(false) {}
22 
23 SkIDChangeListener::~SkIDChangeListener() = default;
24 
25 using List = SkIDChangeListener::List;
26 
27 List::List() = default;
28 
~List()29 List::~List() {
30     // We don't need the mutex. No other thread should have this list while it's being
31     // destroyed.
32     for (auto& listener : fListeners) {
33         if (!listener->shouldDeregister()) {
34             listener->changed();
35         }
36     }
37 }
38 
add(sk_sp<SkIDChangeListener> listener)39 void List::add(sk_sp<SkIDChangeListener> listener) {
40     if (!listener) {
41         return;
42     }
43     SkASSERT(!listener->shouldDeregister());
44 
45     SkAutoMutexExclusive lock(fMutex);
46     // Clean out any stale listeners before we append the new one.
47     for (int i = 0; i < fListeners.size(); ++i) {
48         if (fListeners[i]->shouldDeregister()) {
49             fListeners.removeShuffle(i--);  // No need to preserve the order after i.
50         }
51     }
52     fListeners.push_back(std::move(listener));
53 }
54 
count() const55 int List::count() const {
56     SkAutoMutexExclusive lock(fMutex);
57     return fListeners.size();
58 }
59 
changed()60 void List::changed() {
61     SkAutoMutexExclusive lock(fMutex);
62     for (auto& listener : fListeners) {
63         if (!listener->shouldDeregister()) {
64             listener->changed();
65         }
66     }
67     fListeners.clear();
68 }
69 
reset()70 void List::reset() {
71     SkAutoMutexExclusive lock(fMutex);
72     fListeners.clear();
73 }
74