Panda3D
nodePathComponent.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file nodePathComponent.cxx
10  * @author drose
11  * @date 2002-02-25
12  */
13 
14 #include "nodePathComponent.h"
15 #include "lightMutexHolder.h"
16 
17 // We start the key counters off at 1, since 0 is reserved for an empty
18 // NodePath (and also for an unassigned key).
19 int NodePathComponent::_next_key = 1;
20 LightMutex NodePathComponent::_key_lock("NodePathComponent::_key_lock");
21 TypeHandle NodePathComponent::_type_handle;
22 TypeHandle NodePathComponent::CData::_type_handle;
23 
24 
25 /**
26  *
27  */
28 CycleData *NodePathComponent::CData::
29 make_copy() const {
30  return new CData(*this);
31 }
32 
33 /**
34  * Constructs a new NodePathComponent from the indicated node. Don't try to
35  * call this directly; ask the PandaNode to do it for you.
36  */
37 NodePathComponent::
38 NodePathComponent(PandaNode *node, NodePathComponent *next,
39  int pipeline_stage, Thread *current_thread) :
40  _node(node),
41  _key(0)
42 {
43 #ifdef DO_MEMORY_USAGE
44  MemoryUsage::update_type(this, get_class_type());
45 #endif
46 
47  for (int pipeline_stage_i = pipeline_stage;
48  pipeline_stage_i >= 0;
49  --pipeline_stage_i) {
50  CDStageWriter cdata(_cycler, pipeline_stage_i, current_thread);
51  cdata->_next = next;
52 
53  if (next != nullptr) {
54  cdata->_length = next->get_length(pipeline_stage_i, current_thread) + 1;
55  }
56  }
57 }
58 
59 /**
60  * Returns an index number that is guaranteed to be unique for this particular
61  * NodePathComponent, and not to be reused for the lifetime of the application
62  * (barring integer overflow).
63  */
65 get_key() const {
66  LightMutexHolder holder(_key_lock);
67  if (_key == 0) {
68  // The first time someone asks for a particular component's key, we make
69  // it up on the spot. This helps keep us from wasting index numbers
70  // generating a unique number for *every* component in the world (we only
71  // have 4.2 billion 32-bit integers, after all)
72  ((NodePathComponent *)this)->_key = _next_key++;
73  }
74  return _key;
75 }
76 
77 /**
78  * Returns true if this component represents the top node in the path.
79  */
81 is_top_node(int pipeline_stage, Thread *current_thread) const {
82  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
83  return (cdata->_next == nullptr);
84 }
85 
86 /**
87  * Returns the length of the path to this node.
88  */
90 get_length(int pipeline_stage, Thread *current_thread) const {
91  CDStageReader cdata(_cycler, pipeline_stage, current_thread);
92  return cdata->_length;
93 }
94 
95 /**
96  * Checks that the length indicated by the component is one more than the
97  * length of its predecessor. If this is broken, fixes it and returns true
98  * indicating the component has been changed; otherwise, returns false.
99  */
101 fix_length(int pipeline_stage, Thread *current_thread) {
102  CDLockedStageReader cdata(_cycler, pipeline_stage, current_thread);
103 
104  int length_should_be = 1;
105  if (cdata->_next != nullptr) {
106  length_should_be = cdata->_next->get_length(pipeline_stage, current_thread) + 1;
107  }
108 
109  if (cdata->_length == length_should_be) {
110  return false;
111  }
112 
113  CDStageWriter cdataw(_cycler, pipeline_stage, cdata);
114  cdataw->_length = length_should_be;
115  return true;
116 }
117 
118 /**
119  * The recursive implementation of NodePath::output(), this writes the names
120  * of each node component in order from beginning to end, by first walking to
121  * the end of the linked list and then outputting from there.
122  */
124 output(std::ostream &out) const {
125  Thread *current_thread = Thread::get_current_thread();
126  int pipeline_stage = current_thread->get_pipeline_stage();
127 
128  PandaNode *node = get_node();
129  NodePathComponent *next = get_next(pipeline_stage, current_thread);
130  if (next != nullptr) {
131  // This is not the head of the list; keep going up.
132  next->output(out);
133  out << "/";
134 
135  PandaNode *parent_node = next->get_node();
136  if (parent_node->find_stashed(node) >= 0) {
137  // The node is stashed.
138  out << "@@";
139 
140  } else if (node->find_parent(parent_node) < 0) {
141  // Oops, there's an error. This shouldn't happen.
142  out << ".../";
143  }
144  }
145 
146  // Now output this component.
147  if (node->has_name()) {
148  out << node->get_name();
149  } else {
150  out << "-" << node->get_type();
151  }
152  // out << "[" << this->get_length() << "]";
153 }
154 
155 /**
156  * Sets the next pointer in the path.
157  */
158 void NodePathComponent::
159 set_next(NodePathComponent *next, int pipeline_stage, Thread *current_thread) {
160  nassertv(next != nullptr);
161  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
162  cdata->_next = next;
163 }
164 
165 /**
166  * Severs any connection to the next pointer in the path and makes this
167  * component a top node.
168  */
169 void NodePathComponent::
170 set_top_node(int pipeline_stage, Thread *current_thread) {
171  CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
172  cdata->_next = nullptr;
173 }
bool fix_length(int pipeline_stage, Thread *current_thread)
Checks that the length indicated by the component is one more than the length of its predecessor.
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
int get_key() const
Returns an index number that is guaranteed to be unique for this particular NodePathComponent,...
This class is similar to CycleDataWriter, except it allows writing to a particular stage of the pipel...
A single page of data maintained by a PipelineCycler.
Definition: cycleData.h:47
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaNode * get_node() const
Returns the node referenced by this component.
get_pipeline_stage
Returns the Pipeline stage number associated with this thread.
Definition: thread.h:105
bool is_top_node(int pipeline_stage, Thread *current_thread) const
Returns true if this component represents the top node in the path.
Similar to MutexHolder, but for a light mutex.
void output(std::ostream &out) const
The recursive implementation of NodePath::output(), this writes the names of each node component in o...
NodePathComponent * get_next(int pipeline_stage, Thread *current_thread) const
Returns the next component in the path.
int find_parent(PandaNode *node, Thread *current_thread=Thread::get_current_thread()) const
Returns the index of the indicated parent node, if it is a parent, or -1 if it is not.
Definition: pandaNode.I:44
This class is similar to CycleDataLockedReader, except it allows reading from a particular stage of t...
static void update_type(ReferenceCount *ptr, TypeHandle type)
Associates the indicated type with the given pointer.
Definition: memoryUsage.I:55
This class is similar to CycleDataReader, except it allows reading from a particular stage of the pip...
A thread; that is, a lightweight process.
Definition: thread.h:46
int get_length(int pipeline_stage, Thread *current_thread) const
Returns the length of the path to this node.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
Definition: namable.I:44
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
int find_stashed(PandaNode *node, Thread *current_thread=Thread::get_current_thread()) const
Returns the index of the indicated stashed node, if it is a stashed child, or -1 if it is not.
Definition: pandaNode.I:178
This is a standard, non-reentrant mutex, similar to the Mutex class.
Definition: lightMutex.h:39
This is one component of a NodePath.