| /* | 
 |  * 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 "include/core/SkTypes.h" | 
 | #include "include/private/SkNoncopyable.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 |