Panda3D
globalPointerRegistry.h
1 // Filename: globalPointerRegistry.h
2 // Created by: drose (03Feb00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #ifndef GLOBALPOINTERREGISTRY_H
16 #define GLOBALPOINTERREGISTRY_H
17 
18 #include "pandabase.h"
19 
20 #include "typedObject.h"
21 
22 #include "pmap.h"
23 
24 ////////////////////////////////////////////////////////////////////
25 // Class : GlobalPointerRegistry
26 // Description : This class maintains a one-to-one mapping from
27 // TypeHandle to a void * pointer. Its purpose is to
28 // store a pointer to some class data for a given class.
29 //
30 // Normally, one would simply use a static data member
31 // to store class data. However, when the static data
32 // is associated with a template class, the dynamic
33 // loader may have difficulty in properly resolving the
34 // statics.
35 //
36 // Consider: class foo<int> defines a static member, _a.
37 // There should be only one instance of _a shared
38 // between all instances of foo<int>, and there will be
39 // a different instance of _a shared between all
40 // instances of foo<float>.
41 //
42 // Now suppose that two different shared libraries
43 // instantiate foo<int>. In each .so, there exists a
44 // different foo<int>::_a. It is the loader's job to
45 // recognize this and collapse them together when both
46 // libraries are loaded. This usually works, but
47 // sometimes it doesn't, and you end up with two
48 // different instances of foo<int>::_a; some functions
49 // see one instance, while others see the other. We
50 // have particularly seen this problem occur under Linux
51 // with gcc.
52 //
53 // This class attempts to circumvent the problem by
54 // managing pointers to data based on TypeHandle. Since
55 // the TypeHandle will already be unique based on the
56 // string name supplied to the init_type() function, it
57 // can be used to differentiate foo<int> from
58 // foo<float>, while allowing different instances of
59 // foo<int> to guarantee that they share the same static
60 // data.
61 ////////////////////////////////////////////////////////////////////
62 class EXPCL_PANDA_PUTIL GlobalPointerRegistry {
63 public:
64  INLINE static void *get_pointer(TypeHandle type);
65  INLINE static void store_pointer(TypeHandle type, void *ptr);
66  INLINE static void clear_pointer(TypeHandle type);
67 
68 private:
69  // Nonstatic implementations of the above functions.
70  void *ns_get_pointer(TypeHandle type) const;
71  void ns_store_pointer(TypeHandle type, void *ptr);
72  void ns_clear_pointer(TypeHandle type);
73 
74  INLINE static GlobalPointerRegistry *get_global_ptr();
75  static GlobalPointerRegistry *_global_ptr;
76 
77 private:
78  typedef phash_map<TypeHandle, void *> Pointers;
79  Pointers _pointers;
80 };
81 
82 #include "globalPointerRegistry.I"
83 
84 #endif
85 
This class maintains a one-to-one mapping from TypeHandle to a void * pointer.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85