More adjustments to CliContext.

- CliContext now listens for value node container events so that
  commands can request such a wait as well
- Implement an event wait mechanism for commands to make use of.
  Adjust CliStackTrace and CliPrintVariable accordingly.
This commit is contained in:
Rene Gollent
2012-12-18 18:11:55 -05:00
parent 486c4d38b2
commit 03289a339c
4 changed files with 73 additions and 15 deletions
@@ -118,6 +118,7 @@ CliContext::Init(Team* team, UserInterfaceListener* listener)
fNodeManager = new(std::nothrow) ValueNodeManager();
if (fNodeManager == NULL)
return B_NO_MEMORY;
fNodeManager->AddListener(this);
return B_OK;
}
@@ -316,6 +317,25 @@ CliContext::WaitForThreadOrUser()
}
void
CliContext::WaitForEvents(int32 eventMask)
{
for (;;) {
_PrepareToWaitForEvents(eventMask | EVENT_USER_INTERRUPT);
uint32 events = fEventsOccurred;
if ((events & eventMask) == 0) {
events = _WaitForEvents();
}
if ((events & EVENT_QUIT) != 0 || (events & eventMask) != 0) {
_SignalInputLoop(eventMask);
ProcessPendingEvents();
return;
}
}
}
void
CliContext::ProcessPendingEvents()
{
@@ -404,6 +424,35 @@ CliContext::ThreadStackTraceChanged(const Team::ThreadEvent& threadEvent)
}
void
CliContext::ValueNodeChanged(ValueNodeChild* nodeChild, ValueNode* oldNode,
ValueNode* newNode)
{
_SignalInputLoop(EVENT_VALUE_NODE_CHANGED);
}
void
CliContext::ValueNodeChildrenCreated(ValueNode* node)
{
_SignalInputLoop(EVENT_VALUE_NODE_CHANGED);
}
void
CliContext::ValueNodeChildrenDeleted(ValueNode* node)
{
_SignalInputLoop(EVENT_VALUE_NODE_CHANGED);
}
void
CliContext::ValueNodeValueChanged(ValueNode* oldNode)
{
_SignalInputLoop(EVENT_VALUE_NODE_CHANGED);
}
void
CliContext::_QueueEvent(Event* event)
{
@@ -13,6 +13,7 @@
#include <Locker.h>
#include "Team.h"
#include "ValueNodeContainer.h"
class StackFrame;
@@ -22,7 +23,8 @@ class UserInterfaceListener;
class ValueNodeManager;
class CliContext : private Team::Listener {
class CliContext : private Team::Listener,
private ValueNodeContainer::Listener {
public:
enum {
EVENT_QUIT = 0x01,
@@ -30,7 +32,8 @@ public:
EVENT_THREAD_ADDED = 0x04,
EVENT_THREAD_REMOVED = 0x08,
EVENT_THREAD_STOPPED = 0x10,
EVENT_THREAD_STACK_TRACE_CHANGED = 0x20
EVENT_THREAD_STACK_TRACE_CHANGED = 0x20,
EVENT_VALUE_NODE_CHANGED = 0x40
};
public:
@@ -70,6 +73,7 @@ public:
void QuitSession(bool killTeam);
void WaitForThreadOrUser();
void WaitForEvents(int32 eventMask);
void ProcessPendingEvents();
private:
@@ -87,6 +91,13 @@ private:
virtual void ThreadStackTraceChanged(
const Team::ThreadEvent& event);
// ValueNodeContainer::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);
private:
void _QueueEvent(Event* event);
@@ -116,16 +116,14 @@ CliPrintVariableCommand::_ResolveValueIfNeeded(ValueNode* node,
context.GetUserInterfaceListener()->ValueNodeValueRequested(
context.CurrentThread()->GetCpuState(), container, node);
// TODO: implement proper waiting
while (!context.IsTerminating()) {
context.ProcessPendingEvents();
if (node->LocationAndValueResolutionState()
!= VALUE_NODE_UNRESOLVED) {
break;
}
while (node->LocationAndValueResolutionState()
== VALUE_NODE_UNRESOLVED) {
containerLocker.Unlock();
snooze(20000);
context.WaitForEvents(CliContext::EVENT_VALUE_NODE_CHANGED);
containerLocker.Lock();
if (context.IsTerminating())
return B_ERROR;
}
}
@@ -45,11 +45,11 @@ CliStackTraceCommand::Execute(int argc, const char* const* argv,
// get its stack trace
StackTrace* stackTrace = thread->GetStackTrace();
if (stackTrace == NULL) {
// TODO: Wait for stack trace!
printf("Current thread doesn't have a stack trace. Waiting not "
"implemented yet\n");
return;
while (stackTrace == NULL) {
context.WaitForEvents(CliContext::EVENT_THREAD_STACK_TRACE_CHANGED);
if (context.IsTerminating())
return;
stackTrace = thread->GetStackTrace();
}
BReference<StackTrace> stackTraceReference(stackTrace);
// hold a reference until we're done