1 /* 2 * Copyright 2012-2016, Rene Gollent, rene@gollent.com. 3 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 #include "ValueNodeManager.h" 8 9 #include "AutoLocker.h" 10 11 #include "model/Thread.h" 12 #include "StackFrame.h" 13 #include "Team.h" 14 #include "TypeHandlerRoster.h" 15 #include "ValueNode.h" 16 #include "Variable.h" 17 #include "VariableValueNodeChild.h" 18 19 20 ValueNodeManager::ValueNodeManager(bool addFrameNodes) 21 : 22 fAddFrameNodes(addFrameNodes), 23 fContainer(NULL), 24 fStackFrame(NULL), 25 fThread(NULL) 26 { 27 SetStackFrame(NULL, NULL); 28 } 29 30 31 ValueNodeManager::~ValueNodeManager() 32 { 33 SetStackFrame(NULL, NULL); 34 } 35 36 37 status_t 38 ValueNodeManager::SetStackFrame(Thread* thread, 39 StackFrame* stackFrame) 40 { 41 if (fContainer != NULL) { 42 AutoLocker<ValueNodeContainer> containerLocker(fContainer); 43 44 fContainer->RemoveListener(this); 45 46 fContainer->RemoveAllChildren(); 47 containerLocker.Unlock(); 48 fContainer->ReleaseReference(); 49 fContainer = NULL; 50 } 51 52 fStackFrame = stackFrame; 53 fThread = thread; 54 55 if (fStackFrame == NULL) 56 return B_OK; 57 58 fContainer = new(std::nothrow) ValueNodeContainer; 59 if (fContainer == NULL) 60 return B_NO_MEMORY; 61 62 status_t error = fContainer->Init(); 63 if (error != B_OK) { 64 delete fContainer; 65 fContainer = NULL; 66 return error; 67 } 68 69 AutoLocker<ValueNodeContainer> containerLocker(fContainer); 70 71 fContainer->AddListener(this); 72 73 if (fStackFrame != NULL && fAddFrameNodes) { 74 for (int32 i = 0; Variable* variable = fStackFrame->ParameterAt(i); 75 i++) { 76 _AddNode(variable); 77 } 78 79 for (int32 i = 0; Variable* variable 80 = fStackFrame->LocalVariableAt(i); i++) { 81 _AddNode(variable); 82 } 83 } 84 85 return B_OK; 86 } 87 88 89 bool 90 ValueNodeManager::AddListener(ValueNodeContainer::Listener* listener) 91 { 92 return fListeners.AddItem(listener); 93 } 94 95 96 void 97 ValueNodeManager::RemoveListener(ValueNodeContainer::Listener* listener) 98 { 99 fListeners.RemoveItem(listener); 100 } 101 102 103 void 104 ValueNodeManager::ValueNodeChanged(ValueNodeChild* nodeChild, 105 ValueNode* oldNode, ValueNode* newNode) 106 { 107 if (fContainer == NULL) 108 return; 109 110 AutoLocker<ValueNodeContainer> containerLocker(fContainer); 111 112 for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) 113 fListeners.ItemAt(i)->ValueNodeChanged(nodeChild, oldNode, newNode); 114 115 if (oldNode != NULL && !newNode->ChildCreationNeedsValue()) 116 newNode->CreateChildren(fThread->GetTeam()->GetTeamTypeInformation()); 117 } 118 119 120 void 121 ValueNodeManager::ValueNodeChildrenCreated(ValueNode* node) 122 { 123 if (fContainer == NULL) 124 return; 125 126 for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) 127 fListeners.ItemAt(i)->ValueNodeChildrenCreated(node); 128 } 129 130 131 void 132 ValueNodeManager::ValueNodeChildrenDeleted(ValueNode* node) 133 { 134 if (fContainer == NULL) 135 return; 136 137 for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) 138 fListeners.ItemAt(i)->ValueNodeChildrenDeleted(node); 139 } 140 141 142 void 143 ValueNodeManager::ValueNodeValueChanged(ValueNode* valueNode) 144 { 145 if (fContainer == NULL) 146 return; 147 148 AutoLocker<ValueNodeContainer> containerLocker(fContainer); 149 150 // check whether we know the node 151 ValueNodeChild* nodeChild = valueNode->NodeChild(); 152 if (nodeChild == NULL) 153 return; 154 155 if (valueNode->ChildCreationNeedsValue() 156 && !valueNode->ChildrenCreated()) { 157 status_t error = valueNode->CreateChildren( 158 fThread->GetTeam()->GetTeamTypeInformation()); 159 if (error == B_OK) { 160 for (int32 i = 0; i < valueNode->CountChildren(); i++) { 161 ValueNodeChild* child = valueNode->ChildAt(i); 162 _CreateValueNode(child); 163 AddChildNodes(child); 164 } 165 } 166 } 167 168 for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) 169 fListeners.ItemAt(i)->ValueNodeValueChanged(valueNode); 170 } 171 172 173 void 174 ValueNodeManager::_AddNode(Variable* variable) 175 { 176 // create the node child for the variable 177 ValueNodeChild* nodeChild = new (std::nothrow) VariableValueNodeChild( 178 variable); 179 BReference<ValueNodeChild> nodeChildReference(nodeChild, true); 180 if (nodeChild == NULL || !fContainer->AddChild(nodeChild)) { 181 delete nodeChild; 182 return; 183 } 184 185 // automatically add child nodes for the top level nodes 186 AddChildNodes(nodeChild); 187 } 188 189 190 status_t 191 ValueNodeManager::_CreateValueNode(ValueNodeChild* nodeChild) 192 { 193 if (nodeChild->Node() != NULL) 194 return B_OK; 195 196 // create the node 197 ValueNode* valueNode; 198 status_t error; 199 if (nodeChild->IsInternal()) { 200 error = nodeChild->CreateInternalNode(valueNode); 201 } else { 202 error = TypeHandlerRoster::Default()->CreateValueNode(nodeChild, 203 nodeChild->GetType(), NULL, valueNode); 204 } 205 206 if (error != B_OK) 207 return error; 208 209 nodeChild->SetNode(valueNode); 210 valueNode->ReleaseReference(); 211 212 return B_OK; 213 } 214 215 216 status_t 217 ValueNodeManager::AddChildNodes(ValueNodeChild* nodeChild) 218 { 219 AutoLocker<ValueNodeContainer> containerLocker(fContainer); 220 221 // create a value node for the value node child, if doesn't have one yet 222 ValueNode* valueNode = nodeChild->Node(); 223 if (valueNode == NULL) { 224 status_t error = _CreateValueNode(nodeChild); 225 if (error != B_OK) 226 return error; 227 valueNode = nodeChild->Node(); 228 } 229 230 // check if this node requires child creation 231 // to be deferred until after its location/value have been resolved 232 if (valueNode->ChildCreationNeedsValue()) 233 return B_OK; 234 235 // create the children, if not done yet 236 if (valueNode->ChildrenCreated()) 237 return B_OK; 238 239 return valueNode->CreateChildren( 240 fThread->GetTeam()->GetTeamTypeInformation()); 241 } 242