| /* |
| * Copyright 2009 The Android Open Source Project |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef sk_tools_Registry_DEFINED |
| #define sk_tools_Registry_DEFINED |
| |
| #include "SkNoncopyable.h" |
| #include "SkTypes.h" |
| |
| namespace sk_tools { |
| |
| /** Template class that registers itself (in the constructor) into a linked-list |
| and provides a function-pointer. This can be used to auto-register a set of |
| services, e.g. a set of image codecs. |
| */ |
| template <typename T> class Registry : SkNoncopyable { |
| public: |
| explicit Registry(T value) : fValue(value) { |
| #ifdef SK_BUILD_FOR_ANDROID |
| // work-around for double-initialization bug |
| { |
| Registry* reg = gHead; |
| while (reg) { |
| if (reg == this) { |
| return; |
| } |
| reg = reg->fChain; |
| } |
| } |
| #endif |
| fChain = gHead; |
| gHead = this; |
| } |
| |
| static const Registry* Head() { return gHead; } |
| |
| const Registry* next() const { return fChain; } |
| const T& get() const { return fValue; } |
| |
| // for (const T& t : sk_tools::Registry<T>::Range()) { process(t); } |
| struct Range { |
| struct Iterator { |
| const Registry* fPtr; |
| const T& operator*() { return SkASSERT(fPtr), fPtr->get(); } |
| void operator++() { if (fPtr) { fPtr = fPtr->next(); } } |
| bool operator!=(const Iterator& other) const { return fPtr != other.fPtr; } |
| }; |
| Iterator begin() const { return Iterator{Registry::Head()}; } |
| Iterator end() const { return Iterator{nullptr}; } |
| }; |
| |
| private: |
| T fValue; |
| Registry* fChain; |
| |
| static Registry* gHead; |
| }; |
| |
| // The caller still needs to declare an instance of this somewhere |
| template <typename T> Registry<T>* Registry<T>::gHead; |
| |
| } // namespace sk_tools |
| |
| #endif |