Panda3D
threadSafePointerToBase.I
1 // Filename: threadSafePointerToBase.I
2 // Created by: drose (28Apr06)
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 
16 ////////////////////////////////////////////////////////////////////
17 // Function: ThreadSafePointerToBase::Constructor
18 // Access: Protected
19 // Description:
20 ////////////////////////////////////////////////////////////////////
21 template<class T>
23 ThreadSafePointerToBase(To *ptr) {
24  reassign(ptr);
25 }
26 
27 ////////////////////////////////////////////////////////////////////
28 // Function: ThreadSafePointerToBase::Copy Constructor
29 // Access: Protected
30 // Description:
31 ////////////////////////////////////////////////////////////////////
32 template<class T>
35  reassign(copy);
36 }
37 
38 ////////////////////////////////////////////////////////////////////
39 // Function: ThreadSafePointerToBase::Destructor
40 // Access: Protected
41 // Description:
42 ////////////////////////////////////////////////////////////////////
43 template<class T>
46  reassign((To *)NULL);
47 }
48 
49 ////////////////////////////////////////////////////////////////////
50 // Function: ThreadSafePointerToBase::reassign
51 // Access: Protected
52 // Description: This is the main work of the ThreadSafePointerTo family. When
53 // the pointer is reassigned, decrement the old
54 // reference count and increment the new one.
55 ////////////////////////////////////////////////////////////////////
56 template<class T>
58 reassign(To *ptr) {
59  To *old_ptr = (To *)AtomicAdjust::get_ptr(_void_ptr);
60  if (ptr == old_ptr) {
61  return;
62  }
63 
64 #ifdef HAVE_THREADS
65  void *orig_ptr = AtomicAdjust::compare_and_exchange_ptr(_void_ptr, old_ptr, ptr);
66  while (orig_ptr != old_ptr) {
67  // Some other thread assigned it first. Try again.
68  old_ptr = (To *)AtomicAdjust::get_ptr(_void_ptr);
69  if (ptr == old_ptr) {
70  return;
71  }
72 
73  orig_ptr = AtomicAdjust::compare_and_exchange_ptr(_void_ptr, old_ptr, ptr);
74  }
75 #else // HAVE_THREADS
76  _void_ptr = ptr;
77 #endif // HAVE_THREADS
78 
79  if (ptr != (To *)NULL) {
80  ptr->ref();
81 #ifdef DO_MEMORY_USAGE
82  if (MemoryUsage::get_track_memory_usage()) {
83  update_type(ptr);
84  }
85 #endif
86  }
87 
88  // Now delete the old pointer.
89  if (old_ptr != (To *)NULL) {
90  unref_delete(old_ptr);
91  }
92 }
93 
94 ////////////////////////////////////////////////////////////////////
95 // Function: ThreadSafePointerToBase::reassign
96 // Access: Protected
97 // Description:
98 ////////////////////////////////////////////////////////////////////
99 template<class T>
102  reassign((To *)copy._void_ptr);
103 }
104 
105 #ifdef DO_MEMORY_USAGE
106 ////////////////////////////////////////////////////////////////////
107 // Function: ThreadSafePointerToBase::update_type
108 // Access: Protected
109 // Description: Ensures that the MemoryUsage record for the pointer
110 // has the right type of object, if we know the type
111 // ourselves.
112 ////////////////////////////////////////////////////////////////////
113 template<class T>
115 update_type(To *ptr) {
116  TypeHandle type = get_type_handle(To);
117  if (type == TypeHandle::none()) {
118  do_init_type(To);
119  type = get_type_handle(To);
120  }
121  if (type != TypeHandle::none()) {
122  MemoryUsage::update_type(ptr, type);
123  }
124 }
125 #endif // DO_MEMORY_USAGE
126 
127 
128 ////////////////////////////////////////////////////////////////////
129 // Function: ThreadSafePointerToBase::clear
130 // Access: Published
131 // Description: A convenient way to set the ThreadSafePointerTo object to NULL.
132 // (Assignment to a NULL pointer also works, of course.)
133 ////////////////////////////////////////////////////////////////////
134 template<class T>
136 clear() {
137  reassign((To *)NULL);
138 }
139 
140 ////////////////////////////////////////////////////////////////////
141 // Function: ThreadSafePointerToBase::output
142 // Access: Published
143 // Description: A handy function to output ThreadSafePointerTo's as a hex
144 // pointer followed by a reference count.
145 ////////////////////////////////////////////////////////////////////
146 template<class T>
148 output(ostream &out) const {
149  out << _void_ptr;
150  if (_void_ptr != (void *)NULL) {
151  out << ":" << ((To *)_void_ptr)->get_ref_count();
152  }
153 }
static Pointer get_ptr(const Pointer &var)
Atomically retrieves the snapshot value of the indicated variable.
static TypeHandle none()
Returns a special zero-valued TypeHandle that is used to indicate no type.
Definition: typeHandle.I:274
void clear()
A convenient way to set the ThreadSafePointerTo object to NULL.
This is the base class for ThreadSafePointerTo and ThreadSafeConstPointerTo.
void output(ostream &out) const
A handy function to output ThreadSafePointerTo&#39;s as a hex pointer followed by a reference count...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
static Pointer compare_and_exchange_ptr(Pointer &mem, Pointer old_value, Pointer new_value)
Atomic compare and exchange.