1 #ifndef HALIDE_OBJECT_INSTANCE_REGISTRY_H
2 #define HALIDE_OBJECT_INSTANCE_REGISTRY_H
3 
4 /** \file
5  *
6  * Provides a single global registry of Generators, GeneratorParams,
7  * and Params indexed by this pointer. This is used for finding the
8  * parameters inside of a Generator. NOTE: this is threadsafe only
9  * if you are compiling with C++11 enabled.
10  */
11 
12 #include <stddef.h>
13 #include <stdint.h>
14 
15 #include <map>
16 #include <mutex>
17 #include <vector>
18 
19 namespace Halide {
20 namespace Internal {
21 
22 class ObjectInstanceRegistry {
23 public:
24     enum Kind {
25         Invalid,
26         Generator,
27         GeneratorParam,
28         GeneratorInput,
29         GeneratorOutput,
30         FilterParam
31     };
32 
33     /** Add an instance to the registry. The size may be 0 for Param Kinds,
34      * but not for Generator. subject_ptr is the value actually associated
35      * with this instance; it is usually (but not necessarily) the same
36      * as this_ptr. Assert if this_ptr is already registered.
37      *
38      * If 'this' is directly heap allocated (not a member of a
39      * heap-allocated object) and you want the introspection subsystem
40      * to know about it and its members, set the introspection_helper
41      * argument to a pointer to a global variable with the same true
42      * type as 'this'. For example:
43      *
44      * MyObject *obj = new MyObject;
45      * static MyObject *introspection_helper = nullptr;
46      * register_instance(obj, sizeof(MyObject), kind, obj, &introspection_helper);
47      *
48      * I.e. introspection_helper should be a pointer to a pointer to
49      * an object instance. The inner pointer can be null. The
50      * introspection subsystem will then assume this new object is of
51      * the matching type, which will help its members deduce their
52      * names on construction.
53      */
54     static void register_instance(void *this_ptr, size_t size, Kind kind, void *subject_ptr,
55                                   const void *introspection_helper);
56 
57     /** Remove an instance from the registry. Assert if not found.
58      */
59     static void unregister_instance(void *this_ptr);
60 
61     /** Returns the list of subject pointers for objects that have
62      *   been directly registered within the given range. If there is
63      *   another containing object inside the range, instances within
64      *   that object are skipped.
65      */
66     static std::vector<void *> instances_in_range(void *start, size_t size, Kind kind);
67 
68 private:
69     static ObjectInstanceRegistry &get_registry();
70 
71     struct InstanceInfo {
72         void *subject_ptr;  // May be different from the this_ptr in the key
73         size_t size;        // May be 0 for params
74         Kind kind;
75         bool registered_for_introspection;
76 
InstanceInfoInstanceInfo77         InstanceInfo()
78             : subject_ptr(nullptr), size(0), kind(Invalid), registered_for_introspection(false) {
79         }
InstanceInfoInstanceInfo80         InstanceInfo(size_t size, Kind kind, void *subject_ptr, bool registered_for_introspection)
81             : subject_ptr(subject_ptr), size(size), kind(kind), registered_for_introspection(registered_for_introspection) {
82         }
83     };
84 
85     std::mutex mutex;
86     std::map<uintptr_t, InstanceInfo> instances;
87 
88     ObjectInstanceRegistry() = default;
89     ObjectInstanceRegistry(ObjectInstanceRegistry &rhs) = delete;
90 };
91 
92 }  // namespace Internal
93 }  // namespace Halide
94 
95 #endif  // HALIDE_OBJECT_INSTANCE_REGISTRY_H
96