1 /* 2 * Copyright 2009 The Android Open Source Project 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 sk_tools_Registry_DEFINED 9 #define sk_tools_Registry_DEFINED 10 11 #include "SkNoncopyable.h" 12 #include "SkTypes.h" 13 14 namespace sk_tools { 15 16 /** Template class that registers itself (in the constructor) into a linked-list 17 and provides a function-pointer. This can be used to auto-register a set of 18 services, e.g. a set of image codecs. 19 */ 20 template <typename T> class Registry : SkNoncopyable { 21 public: Registry(T value)22 explicit Registry(T value) : fValue(value) { 23 #ifdef SK_BUILD_FOR_ANDROID 24 // work-around for double-initialization bug 25 { 26 Registry* reg = gHead; 27 while (reg) { 28 if (reg == this) { 29 return; 30 } 31 reg = reg->fChain; 32 } 33 } 34 #endif 35 fChain = gHead; 36 gHead = this; 37 } 38 Head()39 static const Registry* Head() { return gHead; } 40 next()41 const Registry* next() const { return fChain; } get()42 const T& get() const { return fValue; } 43 44 // for (const T& t : sk_tools::Registry<T>::Range()) { process(t); } 45 struct Range { 46 struct Iterator { 47 const Registry* fPtr; 48 const T& operator*() { return SkASSERT(fPtr), fPtr->get(); } 49 void operator++() { if (fPtr) { fPtr = fPtr->next(); } } 50 bool operator!=(const Iterator& other) const { return fPtr != other.fPtr; } 51 }; beginRange52 Iterator begin() const { return Iterator{Registry::Head()}; } endRange53 Iterator end() const { return Iterator{nullptr}; } 54 }; 55 56 private: 57 T fValue; 58 Registry* fChain; 59 60 static Registry* gHead; 61 }; 62 63 // The caller still needs to declare an instance of this somewhere 64 template <typename T> Registry<T>* Registry<T>::gHead; 65 66 } // namespace sk_tools 67 68 #endif 69