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) 116 newNode->CreateChildren(fThread->GetTeam()->GetTeamTypeInformation()); 117 118 } 119 120 121 void 122 ValueNodeManager::ValueNodeChildrenCreated(ValueNode* node) 123 { 124 if (fContainer == NULL) 125 return; 126 127 for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) 128 fListeners.ItemAt(i)->ValueNodeChildrenCreated(node); 129 } 130 131 132 void 133 ValueNodeManager::ValueNodeChildrenDeleted(ValueNode* node) 134 { 135 if (fContainer == NULL) 136 return; 137 138 for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) 139 fListeners.ItemAt(i)->ValueNodeChildrenDeleted(node); 140 } 141 142 143 void 144 ValueNodeManager::ValueNodeValueChanged(ValueNode* valueNode) 145 { 146 if (fContainer == NULL) 147 return; 148 149 AutoLocker<ValueNodeContainer> containerLocker(fContainer); 150 151 // check whether we know the node 152 ValueNodeChild* nodeChild = valueNode->NodeChild(); 153 if (nodeChild == NULL) 154 return; 155 156 if (valueNode->ChildCreationNeedsValue() 157 && !valueNode->ChildrenCreated()) { 158 status_t error = valueNode->CreateChildren( 159 fThread->GetTeam()->GetTeamTypeInformation()); 160 if (error == B_OK) { 161 for (int32 i = 0; i < valueNode->CountChildren(); i++) { 162 ValueNodeChild* child = valueNode->ChildAt(i); 163 _CreateValueNode(child); 164 AddChildNodes(child); 165 } 166 } 167 } 168 169 for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) 170 fListeners.ItemAt(i)->ValueNodeValueChanged(valueNode); 171 } 172 173 174 void 175 ValueNodeManager::_AddNode(Variable* variable) 176 { 177 // create the node child for the variable 178 ValueNodeChild* nodeChild = new (std::nothrow) VariableValueNodeChild( 179 variable); 180 BReference<ValueNodeChild> nodeChildReference(nodeChild, true); 181 if (nodeChild == NULL || !fContainer->AddChild(nodeChild)) { 182 delete nodeChild; 183 return; 184 } 185 186 // automatically add child nodes for the top level nodes 187 AddChildNodes(nodeChild); 188 } 189 190 191 status_t 192 ValueNodeManager::_CreateValueNode(ValueNodeChild* nodeChild) 193 { 194 if (nodeChild->Node() != NULL) 195 return B_OK; 196 197 // create the node 198 ValueNode* valueNode; 199 status_t error; 200 if (nodeChild->IsInternal()) { 201 error = nodeChild->CreateInternalNode(valueNode); 202 } else { 203 error = TypeHandlerRoster::Default()->CreateValueNode(nodeChild, 204 nodeChild->GetType(), valueNode); 205 } 206 207 if (error != B_OK) 208 return error; 209 210 nodeChild->SetNode(valueNode); 211 valueNode->ReleaseReference(); 212 213 return B_OK; 214 } 215 216 217 status_t 218 ValueNodeManager::AddChildNodes(ValueNodeChild* nodeChild) 219 { 220 AutoLocker<ValueNodeContainer> containerLocker(fContainer); 221 222 // create a value node for the value node child, if doesn't have one yet 223 ValueNode* valueNode = nodeChild->Node(); 224 if (valueNode == NULL) { 225 status_t error = _CreateValueNode(nodeChild); 226 if (error != B_OK) 227 return error; 228 valueNode = nodeChild->Node(); 229 } 230 231 // check if this node requires child creation 232 // to be deferred until after its location/value have been resolved 233 if (valueNode->ChildCreationNeedsValue()) 234 return B_OK; 235 236 // create the children, if not done yet 237 if (valueNode->ChildrenCreated()) 238 return B_OK; 239 240 return valueNode->CreateChildren( 241 fThread->GetTeam()->GetTeamTypeInformation()); 242 } 243