/* * Copyright 2020 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkIDChangeListener_DEFINED #define SkIDChangeListener_DEFINED #include "include/core/SkRefCnt.h" #include "include/private/SkMutex.h" #include "include/private/SkTDArray.h" #include /** * Used to be notified when a gen/unique ID is invalidated, typically to preemptively purge * associated items from a cache that are no longer reachable. The listener can * be marked for deregistration if the cached item is remove before the listener is * triggered. This prevents unbounded listener growth when cache items are routinely * removed before the gen ID/unique ID is invalidated. */ class SkIDChangeListener : public SkRefCnt { public: SkIDChangeListener(); ~SkIDChangeListener() override; virtual void changed() = 0; /** * Mark the listener is no longer needed. It should be removed and changed() should not be * called. */ void markShouldDeregister() { fShouldDeregister.store(true, std::memory_order_relaxed); } /** Indicates whether markShouldDeregister was called. */ bool shouldDeregister() { return fShouldDeregister.load(std::memory_order_acquire); } /** Manages a list of SkIDChangeListeners. */ class List { public: List(); ~List(); /** * Add a new listener to the list. It must not already be deregistered. Also clears out * previously deregistered listeners. */ void add(sk_sp listener) SK_EXCLUDES(fMutex); /** * The number of registered listeners (including deregisterd listeners that are yet-to-be * removed. */ int count() const SK_EXCLUDES(fMutex); /** Calls changed() on all listeners that haven't been deregistered and resets the list. */ void changed() SK_EXCLUDES(fMutex); /** Resets without calling changed() on the listeners. */ void reset() SK_EXCLUDES(fMutex); private: mutable SkMutex fMutex; SkTDArray fListeners SK_GUARDED_BY(fMutex); // pointers are reffed }; private: std::atomic fShouldDeregister; }; #endif