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 20ValueNodeManager::ValueNodeManager(bool addFrameNodes) 21 : 22 fAddFrameNodes(addFrameNodes), 23 fContainer(NULL), 24 fStackFrame(NULL), 25 fThread(NULL) 26{ 27 SetStackFrame(NULL, NULL); 28} 29 30 31ValueNodeManager::~ValueNodeManager() 32{ 33 SetStackFrame(NULL, NULL); 34} 35 36 37status_t 38ValueNodeManager::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 89bool 90ValueNodeManager::AddListener(ValueNodeContainer::Listener* listener) 91{ 92 return fListeners.AddItem(listener); 93} 94 95 96void 97ValueNodeManager::RemoveListener(ValueNodeContainer::Listener* listener) 98{ 99 fListeners.RemoveItem(listener); 100} 101 102 103void 104ValueNodeManager::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 120void 121ValueNodeManager::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 131void 132ValueNodeManager::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 142void 143ValueNodeManager::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 173void 174ValueNodeManager::_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 190status_t 191ValueNodeManager::_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 216status_t 217ValueNodeManager::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