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 */
24class SkIDChangeListener : public SkRefCnt {
25public:
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
71private:
72 std::atomic<bool> fShouldDeregister;
73};
74
75#endif
76