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 | #ifndef SkIDChangeListener_DEFINED |
9 | #define SkIDChangeListener_DEFINED |
10 | |
11 | #include "include/core/SkRefCnt.h" |
12 | #include "include/private/SkMutex.h" |
13 | #include "include/private/SkTDArray.h" |
14 | |
15 | #include <atomic> |
16 | |
17 | /** |
18 | * Used to be notified when a gen/unique ID is invalidated, typically to preemptively purge |
19 | * associated items from a cache that are no longer reachable. The listener can |
20 | * be marked for deregistration if the cached item is remove before the listener is |
21 | * triggered. This prevents unbounded listener growth when cache items are routinely |
22 | * removed before the gen ID/unique ID is invalidated. |
23 | */ |
24 | class SkIDChangeListener : public SkRefCnt { |
25 | public: |
26 | SkIDChangeListener(); |
27 | |
28 | ~SkIDChangeListener() override; |
29 | |
30 | virtual void changed() = 0; |
31 | |
32 | /** |
33 | * Mark the listener is no longer needed. It should be removed and changed() should not be |
34 | * called. |
35 | */ |
36 | void markShouldDeregister() { fShouldDeregister.store(true, std::memory_order_relaxed); } |
37 | |
38 | /** Indicates whether markShouldDeregister was called. */ |
39 | bool shouldDeregister() { return fShouldDeregister.load(std::memory_order_acquire); } |
40 | |
41 | /** Manages a list of SkIDChangeListeners. */ |
42 | class List { |
43 | public: |
44 | List(); |
45 | |
46 | ~List(); |
47 | |
48 | /** |
49 | * Add a new listener to the list. It must not already be deregistered. Also clears out |
50 | * previously deregistered listeners. |
51 | */ |
52 | void add(sk_sp<SkIDChangeListener> listener, bool singleThreaded = false); |
53 | |
54 | /** |
55 | * The number of registered listeners (including deregisterd listeners that are yet-to-be |
56 | * removed. |
57 | */ |
58 | int count(); |
59 | |
60 | /** Calls changed() on all listeners that haven't been deregistered and resets the list. */ |
61 | void changed(bool singleThreaded = false); |
62 | |
63 | /** Resets without calling changed() on the listeners. */ |
64 | void reset(bool singleThreaded = false); |
65 | |
66 | private: |
67 | SkMutex fMutex; |
68 | SkTDArray<SkIDChangeListener*> fListeners; // pointers are reffed |
69 | }; |
70 | |
71 | private: |
72 | std::atomic<bool> fShouldDeregister; |
73 | }; |
74 | |
75 | #endif |
76 | |