• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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