Pull a ValueNodeManager class out of VariableTableModel.

- The intention is to have a class which handles the actual management
  of the variable node graph, creating child nodes and such. This way
  the GUI, CLI and report generator don't have to each reimplement
  these low-level parts and can instead concentrate on their relevant
  representations thereof.
This commit is contained in:
Rene Gollent 2012-12-07 21:15:38 -05:00
parent adf4c44437
commit c1034c63fb
3 changed files with 289 additions and 0 deletions

View File

@ -263,6 +263,7 @@ Application Debugger :
ValueLoader.cpp
ValueNode.cpp
ValueNodeContainer.cpp
ValueNodeManager.cpp
# value/type_handlers
BListTypeHandler.cpp

View File

@ -0,0 +1,234 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "ValueNodeManager.h"
#include "AutoLocker.h"
#include "StackFrame.h"
#include "Thread.h"
#include "TypeHandlerRoster.h"
#include "ValueNode.h"
#include "Variable.h"
#include "VariableValueNodeChild.h"
ValueNodeManager::ValueNodeManager()
:
fContainer(NULL),
fStackFrame(NULL),
fThread(NULL)
{
}
ValueNodeManager::~ValueNodeManager()
{
SetStackFrame(NULL, NULL);
}
status_t
ValueNodeManager::SetStackFrame(Thread* thread,
StackFrame* stackFrame)
{
if (fContainer != NULL) {
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
fContainer->RemoveListener(this);
fContainer->RemoveAllChildren();
containerLocker.Unlock();
fContainer->ReleaseReference();
fContainer = NULL;
}
fStackFrame = stackFrame;
fThread = thread;
if (fStackFrame != NULL) {
fContainer = new(std::nothrow) ValueNodeContainer;
if (fContainer == NULL)
return B_NO_MEMORY;
status_t error = fContainer->Init();
if (error != B_OK) {
delete fContainer;
fContainer = NULL;
return error;
}
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
fContainer->AddListener(this);
for (int32 i = 0; Variable* variable = fStackFrame->ParameterAt(i);
i++) {
_AddNode(variable);
}
for (int32 i = 0; Variable* variable
= fStackFrame->LocalVariableAt(i); i++) {
_AddNode(variable);
}
}
return B_OK;
}
bool
ValueNodeManager::AddListener(ValueNodeContainer::Listener* listener)
{
return fListeners.AddItem(listener);
}
void
ValueNodeManager::RemoveListener(ValueNodeContainer::Listener* listener)
{
fListeners.RemoveItem(listener);
}
void
ValueNodeManager::ValueNodeChanged(ValueNodeChild* nodeChild,
ValueNode* oldNode, ValueNode* newNode)
{
if (fContainer == NULL)
return;
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
if (oldNode != NULL)
newNode->CreateChildren();
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
fListeners.ItemAt(i)->ValueNodeChanged(nodeChild, oldNode, newNode);
}
void
ValueNodeManager::ValueNodeChildrenCreated(ValueNode* node)
{
if (fContainer == NULL)
return;
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
fListeners.ItemAt(i)->ValueNodeChildrenCreated(node);
}
void
ValueNodeManager::ValueNodeChildrenDeleted(ValueNode* node)
{
if (fContainer == NULL)
return;
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
fListeners.ItemAt(i)->ValueNodeChildrenDeleted(node);
}
void
ValueNodeManager::ValueNodeValueChanged(ValueNode* valueNode)
{
if (fContainer == NULL)
return;
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
// check whether we know the node
ValueNodeChild* nodeChild = valueNode->NodeChild();
if (nodeChild == NULL)
return;
if (valueNode->ChildCreationNeedsValue()
&& !valueNode->ChildrenCreated()) {
status_t error = valueNode->CreateChildren();
if (error != B_OK)
return;
for (int32 i = 0; i < valueNode->CountChildren(); i++) {
ValueNodeChild* child = valueNode->ChildAt(i);
_CreateValueNode(child);
AddChildNodes(child);
}
}
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
fListeners.ItemAt(i)->ValueNodeValueChanged(valueNode);
}
void
ValueNodeManager::_AddNode(Variable* variable)
{
// create the node child for the variable
ValueNodeChild* nodeChild = new (std::nothrow) VariableValueNodeChild(
variable);
BReference<ValueNodeChild> nodeChildReference(nodeChild, true);
if (nodeChild == NULL || !fContainer->AddChild(nodeChild)) {
delete nodeChild;
return;
}
// automatically add child nodes for the top level nodes
AddChildNodes(nodeChild);
}
status_t
ValueNodeManager::_CreateValueNode(ValueNodeChild* nodeChild)
{
if (nodeChild->Node() != NULL)
return B_OK;
// create the node
ValueNode* valueNode;
status_t error;
if (nodeChild->IsInternal()) {
error = nodeChild->CreateInternalNode(valueNode);
} else {
error = TypeHandlerRoster::Default()->CreateValueNode(nodeChild,
nodeChild->GetType(), valueNode);
}
if (error != B_OK)
return error;
nodeChild->SetNode(valueNode);
valueNode->ReleaseReference();
return B_OK;
}
status_t
ValueNodeManager::AddChildNodes(ValueNodeChild* nodeChild)
{
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
// create a value node for the value node child, if doesn't have one yet
ValueNode* valueNode = nodeChild->Node();
if (valueNode == NULL) {
status_t error = _CreateValueNode(nodeChild);
if (error != B_OK)
return error;
valueNode = nodeChild->Node();
}
// check if this node requires child creation
// to be deferred until after its location/value have been resolved
if (valueNode->ChildCreationNeedsValue())
return B_OK;
// create the children, if not done yet
if (valueNode->ChildrenCreated())
return B_OK;
return valueNode->CreateChildren();
}

View File

@ -0,0 +1,54 @@
/*
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
#ifndef VALUE_NODE_MANAGER_H
#define VALUE_NODE_MANAGER_H
#include <Referenceable.h>
#include "ValueNodeContainer.h"
class StackFrame;
class Thread;
class Variable;
class ValueNodeManager : public BReferenceable,
private ValueNodeContainer::Listener {
public:
ValueNodeManager();
virtual ~ValueNodeManager();
status_t SetStackFrame(Thread* thread,
StackFrame* frame);
bool AddListener(
ValueNodeContainer::Listener* listener);
void RemoveListener(
ValueNodeContainer::Listener* listener);
virtual void ValueNodeChanged(ValueNodeChild* nodeChild,
ValueNode* oldNode, ValueNode* newNode);
virtual void ValueNodeChildrenCreated(ValueNode* node);
virtual void ValueNodeChildrenDeleted(ValueNode* node);
virtual void ValueNodeValueChanged(ValueNode* node);
ValueNodeContainer* GetContainer() const { return fContainer; };
status_t AddChildNodes(ValueNodeChild* nodeChild);
private:
typedef BObjectList<ValueNodeContainer::Listener> ListenerList;
void _AddNode(Variable* variable);
status_t _CreateValueNode(ValueNodeChild* nodeChild);
private:
ValueNodeContainer* fContainer;
StackFrame* fStackFrame;
Thread* fThread;
ListenerList fListeners;
};
#endif // VALUE_NODE_MANAGER_H