diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index f33bf5b343..a2d390b60a 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -25,6 +25,7 @@ Application Debugger : # ElfFile.cpp Jobs.cpp TeamDebugger.cpp + ThreadHandler.cpp Worker.cpp # arch diff --git a/src/apps/debugger/Jobs.cpp b/src/apps/debugger/Jobs.cpp index 0c857e856f..2ec6554525 100644 --- a/src/apps/debugger/Jobs.cpp +++ b/src/apps/debugger/Jobs.cpp @@ -22,6 +22,56 @@ #include "Thread.h" +// #pragma mark - GetThreadStateJob + + +GetThreadStateJob::GetThreadStateJob(DebuggerInterface* debuggerInterface, + Thread* thread) + : + fDebuggerInterface(debuggerInterface), + fThread(thread) +{ + fThread->AddReference(); +} + + +GetThreadStateJob::~GetThreadStateJob() +{ + fThread->RemoveReference(); +} + + +JobKey +GetThreadStateJob::Key() const +{ + return JobKey(fThread, JOB_TYPE_GET_THREAD_STATE); +} + + +status_t +GetThreadStateJob::Do() +{ + CpuState* state = NULL; + status_t error = fDebuggerInterface->GetCpuState(fThread->ID(), state); + Reference reference(state, true); + + AutoLocker locker(fThread->GetTeam()); + + if (fThread->State() != THREAD_STATE_UNKNOWN) + return B_OK; + + if (error == B_OK) { + fThread->SetState(THREAD_STATE_STOPPED); + fThread->SetCpuState(state); + } else if (error == B_BAD_THREAD_STATE) { + fThread->SetState(THREAD_STATE_RUNNING); + } else + return error; + + return B_OK; +} + + // #pragma mark - GetCpuStateJob diff --git a/src/apps/debugger/Jobs.h b/src/apps/debugger/Jobs.h index 1c70faf56d..05a2af58b7 100644 --- a/src/apps/debugger/Jobs.h +++ b/src/apps/debugger/Jobs.h @@ -20,6 +20,7 @@ class Thread; // job types enum { + JOB_TYPE_GET_THREAD_STATE, JOB_TYPE_GET_CPU_STATE, JOB_TYPE_GET_STACK_TRACE, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO, @@ -27,6 +28,22 @@ enum { }; +class GetThreadStateJob : public Job { +public: + GetThreadStateJob( + DebuggerInterface* debuggerInterface, + Thread* thread); + virtual ~GetThreadStateJob(); + + virtual JobKey Key() const; + virtual status_t Do(); + +private: + DebuggerInterface* fDebuggerInterface; + Thread* fThread; +}; + + class GetCpuStateJob : public Job { public: GetCpuStateJob( diff --git a/src/apps/debugger/TeamDebugger.cpp b/src/apps/debugger/TeamDebugger.cpp index ef3ae426bd..31378f0c2e 100644 --- a/src/apps/debugger/TeamDebugger.cpp +++ b/src/apps/debugger/TeamDebugger.cpp @@ -59,6 +59,13 @@ TeamDebugger::~TeamDebugger() if (fDebugEventListener >= 0) wait_for_thread(fDebugEventListener, NULL); + ThreadHandler* threadHandler = fThreadHandlers.Clear(true); + while (threadHandler != NULL) { + ThreadHandler* next = threadHandler->fNext; + threadHandler->RemoveReference(); + threadHandler = next; + } + delete fDebuggerInterface; delete fWorker; delete fDebugModel; @@ -92,6 +99,11 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain) fTeam->AddListener(this); + // init thread handler table + error = fThreadHandlers.Init(); + if (error != B_OK) + return error; + // create our worker fWorker = new(std::nothrow) Worker; if (fWorker == NULL) @@ -136,7 +148,14 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain) if (error != B_OK) return error; - _UpdateThreadState(thread); + ThreadHandler* handler = new(std::nothrow) ThreadHandler( + fDebugModel, thread, fWorker, fDebuggerInterface); + if (handler == NULL) + return B_NO_MEMORY; + + fThreadHandlers.Insert(handler); + + handler->Init(); } } @@ -204,7 +223,10 @@ TeamDebugger::MessageReceived(BMessage* message) if (message->FindInt32("thread", &threadID) != B_OK) break; - _HandleThreadAction(threadID, message->what); + if (ThreadHandler* handler = _GetThreadHandler(threadID)) { + handler->HandleThreadAction(message->what); + handler->RemoveReference(); + } break; } @@ -232,7 +254,10 @@ TeamDebugger::MessageReceived(BMessage* message) if (message->FindInt32("thread", &threadID) != B_OK) break; - _HandleThreadStateChanged(threadID); + if (ThreadHandler* handler = _GetThreadHandler(threadID)) { + handler->HandleThreadStateChanged(); + handler->RemoveReference(); + } break; } case MSG_THREAD_CPU_STATE_CHANGED: @@ -241,7 +266,10 @@ TeamDebugger::MessageReceived(BMessage* message) if (message->FindInt32("thread", &threadID) != B_OK) break; - _HandleCpuStateChanged(threadID); + if (ThreadHandler* handler = _GetThreadHandler(threadID)) { + handler->HandleCpuStateChanged(); + handler->RemoveReference(); + } break; } case MSG_THREAD_STACK_TRACE_CHANGED: @@ -250,7 +278,10 @@ TeamDebugger::MessageReceived(BMessage* message) if (message->FindInt32("thread", &threadID) != B_OK) break; - _HandleStackTraceChanged(threadID); + if (ThreadHandler* handler = _GetThreadHandler(threadID)) { + handler->HandleStackTraceChanged(); + handler->RemoveReference(); + } break; } @@ -448,35 +479,51 @@ TeamDebugger::_HandleDebuggerMessage(DebugEvent* event) printf("TeamDebugger::_HandleDebuggerMessage(): %d\n", event->EventType()); bool handled = false; + ThreadHandler* handler = _GetThreadHandler(event->Thread()); + Reference handlerReference(handler); + switch (event->EventType()) { case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: printf("B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: thread: %ld\n", event->Thread()); - handled = _HandleThreadDebugged( - dynamic_cast(event)); + if (handler != NULL) { + handled = handler->HandleThreadDebugged( + dynamic_cast(event)); + } break; case B_DEBUGGER_MESSAGE_DEBUGGER_CALL: printf("B_DEBUGGER_MESSAGE_DEBUGGER_CALL: thread: %ld\n", event->Thread()); - handled = _HandleDebuggerCall( - dynamic_cast(event)); + if (handler != NULL) { + handled = handler->HandleDebuggerCall( + dynamic_cast(event)); + } break; case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: printf("B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: thread: %ld\n", event->Thread()); - handled = _HandleBreakpointHit( - dynamic_cast(event)); + if (handler != NULL) { + handled = handler->HandleBreakpointHit( + dynamic_cast(event)); + } break; case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: printf("B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: thread: %ld\n", event->Thread()); - handled = _HandleWatchpointHit( - dynamic_cast(event)); + if (handler != NULL) { + handled = handler->HandleWatchpointHit( + dynamic_cast(event)); + } break; case B_DEBUGGER_MESSAGE_SINGLE_STEP: printf("B_DEBUGGER_MESSAGE_SINGLE_STEP: thread: %ld\n", event->Thread()); - handled = _HandleSingleStep(dynamic_cast(event)); + if (handler != NULL) { + handled = handler->HandleSingleStep( + dynamic_cast(event)); + } break; case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: printf("B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: thread: %ld\n", event->Thread()); - handled = _HandleExceptionOccurred( - dynamic_cast(event)); + if (handler != NULL) { + handled = handler->HandleExceptionOccurred( + dynamic_cast(event)); + } break; // case B_DEBUGGER_MESSAGE_TEAM_CREATED: //printf("B_DEBUGGER_MESSAGE_TEAM_CREATED: team: %ld\n", message.team_created.new_team); @@ -523,63 +570,6 @@ printf("B_DEBUGGER_MESSAGE_TEAM_EXEC: team: %ld\n", event->Team()); } -bool -TeamDebugger::_HandleThreadStopped(thread_id threadID, CpuState* cpuState) -{ - // get the thread - AutoLocker< ::Team> locker(fTeam); - ::Thread* thread = fTeam->ThreadByID(threadID); - if (thread == NULL) - return false; - - _SetThreadState(thread, THREAD_STATE_STOPPED, cpuState); - - return true; -} - - -bool -TeamDebugger::_HandleThreadDebugged(ThreadDebuggedEvent* event) -{ - return _HandleThreadStopped(event->Thread(), NULL); -} - - -bool -TeamDebugger::_HandleDebuggerCall(DebuggerCallEvent* event) -{ - return _HandleThreadStopped(event->Thread(), NULL); -} - - -bool -TeamDebugger::_HandleBreakpointHit(BreakpointHitEvent* event) -{ - return _HandleThreadStopped(event->Thread(), event->GetCpuState()); -} - - -bool -TeamDebugger::_HandleWatchpointHit(WatchpointHitEvent* event) -{ - return _HandleThreadStopped(event->Thread(), event->GetCpuState()); -} - - -bool -TeamDebugger::_HandleSingleStep(SingleStepEvent* event) -{ - return _HandleThreadStopped(event->Thread(), event->GetCpuState()); -} - - -bool -TeamDebugger::_HandleExceptionOccurred(ExceptionOccurredEvent* event) -{ - return _HandleThreadStopped(event->Thread(), NULL); -} - - bool TeamDebugger::_HandleThreadCreated(ThreadCreatedEvent* event) { @@ -588,8 +578,17 @@ TeamDebugger::_HandleThreadCreated(ThreadCreatedEvent* event) ThreadInfo info; status_t error = fDebuggerInterface->GetThreadInfo(event->NewThread(), info); - if (error == B_OK) - fTeam->AddThread(info); + if (error == B_OK) { + ::Thread* thread; + fTeam->AddThread(info, &thread); + + ThreadHandler* handler = new(std::nothrow) ThreadHandler( + fDebugModel, thread, fWorker, fDebuggerInterface); + if (handler != NULL) { + fThreadHandlers.Insert(handler); + handler->Init(); + } + } return false; } @@ -599,6 +598,10 @@ bool TeamDebugger::_HandleThreadDeleted(ThreadDeletedEvent* event) { AutoLocker< ::Team> locker(fTeam); + if (ThreadHandler* handler = fThreadHandlers.Lookup(event->Thread())) { + fThreadHandlers.Remove(handler); + handler->RemoveReference(); + } fTeam->RemoveThread(event->Thread()); return false; } @@ -622,32 +625,6 @@ TeamDebugger::_HandleImageDeleted(ImageDeletedEvent* event) } -void -TeamDebugger::_UpdateThreadState(::Thread* thread) -{ - CpuState* cpuState = NULL; - status_t error = fDebuggerInterface->GetCpuState(thread->ID(), cpuState); - - uint32 newState = THREAD_STATE_UNKNOWN; - if (error == B_OK) { - newState = THREAD_STATE_STOPPED; - cpuState->RemoveReference(); - } else if (error == B_BAD_THREAD_STATE) - newState = THREAD_STATE_RUNNING; - - _SetThreadState(thread, newState, cpuState); -} - - -void -TeamDebugger::_SetThreadState(::Thread* thread, uint32 state, - CpuState* cpuState) -{ - thread->SetState(state); - thread->SetCpuState(cpuState); -} - - status_t TeamDebugger::_SetUserBreakpoint(target_addr_t address, bool enabled) { @@ -715,56 +692,6 @@ printf("-> breakpoint %sinstalled successfully!\n", install ? "" : "un"); } -void -TeamDebugger::_HandleThreadAction(thread_id threadID, uint32 action) -{ - AutoLocker< ::Team> locker(fTeam); - - ::Thread* thread = fTeam->ThreadByID(threadID); - if (thread == NULL || thread->State() == THREAD_STATE_UNKNOWN) - return; - - // When stop is requested, thread must be running, otherwise stopped. - if (action == MSG_THREAD_STOP - ? thread->State() != THREAD_STATE_RUNNING - : thread->State() != THREAD_STATE_STOPPED) { - return; - } - - // When continuing the thread update thread state before actually issuing - // the command, since we need to unlock. - if (action != MSG_THREAD_STOP) - _SetThreadState(thread, THREAD_STATE_RUNNING, NULL); - - locker.Unlock(); - - switch (action) { - case MSG_THREAD_RUN: -printf("MSG_THREAD_RUN\n"); - fDebuggerInterface->ContinueThread(threadID); - break; - case MSG_THREAD_STOP: -printf("MSG_THREAD_STOP\n"); - fDebuggerInterface->StopThread(threadID); - break; - case MSG_THREAD_STEP_OVER: -printf("MSG_THREAD_STEP_OVER\n"); - fDebuggerInterface->SingleStepThread(threadID); - break; - case MSG_THREAD_STEP_INTO: -printf("MSG_THREAD_STEP_INTO\n"); - fDebuggerInterface->SingleStepThread(threadID); - break; - case MSG_THREAD_STEP_OUT: -printf("MSG_THREAD_STEP_OUT\n"); - fDebuggerInterface->SingleStepThread(threadID); - break; - -// TODO: Handle stepping correctly! - } -} - - void TeamDebugger::_HandleSetUserBreakpoint(target_addr_t address, bool enabled) { @@ -806,55 +733,15 @@ printf("TeamDebugger::_HandleClearUserBreakpoint(%#llx)\n", address); } -void -TeamDebugger::_HandleThreadStateChanged(thread_id threadID) +ThreadHandler* +TeamDebugger::_GetThreadHandler(thread_id threadID) { - AutoLocker< ::Team> teamLocker(fTeam); + AutoLocker locker(fDebugModel); - ::Thread* thread = fTeam->ThreadByID(threadID); - if (thread == NULL) - return; - - // cancel jobs for this thread - fWorker->AbortJob(JobKey(thread, JOB_TYPE_GET_CPU_STATE)); - fWorker->AbortJob(JobKey(thread, JOB_TYPE_GET_STACK_TRACE)); - - // If the thread is stopped and has no CPU state yet, schedule a job. - if (thread->State() == THREAD_STATE_STOPPED - && thread->GetCpuState() == NULL) { - fWorker->ScheduleJob( - new(std::nothrow) GetCpuStateJob(fDebuggerInterface, thread), - this); - } -} - - -void -TeamDebugger::_HandleCpuStateChanged(thread_id threadID) -{ - AutoLocker< ::Team> teamLocker(fTeam); - - ::Thread* thread = fTeam->ThreadByID(threadID); - if (thread == NULL) - return; - - // cancel stack trace job for this thread - fWorker->AbortJob(JobKey(thread, JOB_TYPE_GET_STACK_TRACE)); - - // If the thread has a CPU state, but no stack trace yet, schedule a job. - if (thread->GetCpuState() != NULL && thread->GetStackTrace() == NULL) { - fWorker->ScheduleJob( - new(std::nothrow) GetStackTraceJob(fDebuggerInterface, - fDebuggerInterface->GetArchitecture(), thread), - this); - } -} - - -void -TeamDebugger::_HandleStackTraceChanged(thread_id threadID) -{ -printf("TeamDebugger::_HandleStackTraceChanged()\n"); + ThreadHandler* handler = fThreadHandlers.Lookup(threadID); + if (handler != NULL) + handler->AddReference(); + return handler; } diff --git a/src/apps/debugger/TeamDebugger.h b/src/apps/debugger/TeamDebugger.h index 97170472a5..f40fb70cc8 100644 --- a/src/apps/debugger/TeamDebugger.h +++ b/src/apps/debugger/TeamDebugger.h @@ -13,6 +13,7 @@ #include "DebugEvent.h" #include "Team.h" #include "TeamWindow.h" +#include "ThreadHandler.h" #include "Worker.h" @@ -66,21 +67,6 @@ private: void _HandleDebuggerMessage(DebugEvent* event); - bool _HandleThreadStopped(thread_id threadID, - CpuState* cpuState); - - bool _HandleThreadDebugged( - ThreadDebuggedEvent* event); - bool _HandleDebuggerCall( - DebuggerCallEvent* event); - bool _HandleBreakpointHit( - BreakpointHitEvent* event); - bool _HandleWatchpointHit( - WatchpointHitEvent* event); - bool _HandleSingleStep( - SingleStepEvent* event); - bool _HandleExceptionOccurred( - ExceptionOccurredEvent* event); bool _HandleThreadCreated( ThreadCreatedEvent* event); bool _HandleThreadDeleted( @@ -90,23 +76,17 @@ private: bool _HandleImageDeleted( ImageDeletedEvent* event); - void _UpdateThreadState(::Thread* thread); - void _SetThreadState(::Thread* thread, uint32 state, - CpuState* cpuState); status_t _SetUserBreakpoint(target_addr_t address, bool enabled); - void _HandleThreadAction(thread_id threadID, - uint32 action); void _HandleSetUserBreakpoint(target_addr_t address, bool enabled); void _HandleClearUserBreakpoint( target_addr_t address); - void _HandleThreadStateChanged(thread_id threadID); - void _HandleCpuStateChanged(thread_id threadID); - void _HandleStackTraceChanged(thread_id threadID); + + ThreadHandler* _GetThreadHandler(thread_id threadID); void _NotifyUser(const char* title, const char* text,...); @@ -116,7 +96,8 @@ private: ::Team* fTeam; TeamDebugModel* fDebugModel; team_id fTeamID; - port_id fNubPort; + ThreadHandlerTable fThreadHandlers; + // protected by the team lock DebuggerInterface* fDebuggerInterface; Worker* fWorker; thread_id fDebugEventListener; diff --git a/src/apps/debugger/ThreadHandler.cpp b/src/apps/debugger/ThreadHandler.cpp new file mode 100644 index 0000000000..1dd06472c0 --- /dev/null +++ b/src/apps/debugger/ThreadHandler.cpp @@ -0,0 +1,196 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "ThreadHandler.h" + +#include + +#include + +#include + +#include "CpuState.h" +#include "DebuggerInterface.h" +#include "Jobs.h" +#include "MessageCodes.h" +#include "Team.h" +#include "TeamDebugModel.h" +#include "Worker.h" + + +ThreadHandler::ThreadHandler(TeamDebugModel* debugModel, Thread* thread, + Worker* worker, DebuggerInterface* debuggerInterface) + : + fDebugModel(debugModel), + fThread(thread), + fWorker(worker), + fDebuggerInterface(debuggerInterface) +{ +} + + +ThreadHandler::~ThreadHandler() +{ +} + + +void +ThreadHandler::Init() +{ + fWorker->ScheduleJob(new(std::nothrow) GetThreadStateJob(fDebuggerInterface, + fThread)); +} + + +bool +ThreadHandler::HandleThreadDebugged(ThreadDebuggedEvent* event) +{ + return _HandleThreadStopped(NULL); +} + + +bool +ThreadHandler::HandleDebuggerCall(DebuggerCallEvent* event) +{ + return _HandleThreadStopped(NULL); +} + + +bool +ThreadHandler::HandleBreakpointHit(BreakpointHitEvent* event) +{ + return _HandleThreadStopped(event->GetCpuState()); +} + + +bool +ThreadHandler::HandleWatchpointHit(WatchpointHitEvent* event) +{ + return _HandleThreadStopped(event->GetCpuState()); +} + + +bool +ThreadHandler::HandleSingleStep(SingleStepEvent* event) +{ + return _HandleThreadStopped(event->GetCpuState()); +} + + +bool +ThreadHandler::HandleExceptionOccurred(ExceptionOccurredEvent* event) +{ + return _HandleThreadStopped(NULL); +} + + +void +ThreadHandler::HandleThreadAction(uint32 action) +{ + AutoLocker locker(fDebugModel); + + if (fThread->State() == THREAD_STATE_UNKNOWN) + return; + + // When stop is requested, thread must be running, otherwise stopped. + if (action == MSG_THREAD_STOP + ? fThread->State() != THREAD_STATE_RUNNING + : fThread->State() != THREAD_STATE_STOPPED) { + return; + } + + // When continuing the thread update thread state before actually issuing + // the command, since we need to unlock. + if (action != MSG_THREAD_STOP) + _SetThreadState(THREAD_STATE_RUNNING, NULL); + + locker.Unlock(); + + switch (action) { + case MSG_THREAD_RUN: +printf("MSG_THREAD_RUN\n"); + fDebuggerInterface->ContinueThread(ThreadID()); + break; + case MSG_THREAD_STOP: +printf("MSG_THREAD_STOP\n"); + fDebuggerInterface->StopThread(ThreadID()); + break; + case MSG_THREAD_STEP_OVER: +printf("MSG_THREAD_STEP_OVER\n"); + fDebuggerInterface->SingleStepThread(ThreadID()); + break; + case MSG_THREAD_STEP_INTO: +printf("MSG_THREAD_STEP_INTO\n"); + fDebuggerInterface->SingleStepThread(ThreadID()); + break; + case MSG_THREAD_STEP_OUT: +printf("MSG_THREAD_STEP_OUT\n"); + fDebuggerInterface->SingleStepThread(ThreadID()); + break; + +// TODO: Handle stepping correctly! + } +} + + +void +ThreadHandler::HandleThreadStateChanged() +{ + AutoLocker locker(fDebugModel); + + // cancel jobs for this thread + fWorker->AbortJob(JobKey(fThread, JOB_TYPE_GET_CPU_STATE)); + fWorker->AbortJob(JobKey(fThread, JOB_TYPE_GET_STACK_TRACE)); + + // If the thread is stopped and has no CPU state yet, schedule a job. + if (fThread->State() == THREAD_STATE_STOPPED + && fThread->GetCpuState() == NULL) { + fWorker->ScheduleJob( + new(std::nothrow) GetCpuStateJob(fDebuggerInterface, fThread)); + } +} + + +void +ThreadHandler::HandleCpuStateChanged() +{ + AutoLocker locker(fDebugModel); + + // cancel stack trace job for this thread + fWorker->AbortJob(JobKey(fThread, JOB_TYPE_GET_STACK_TRACE)); + + // If the thread has a CPU state, but no stack trace yet, schedule a job. + if (fThread->GetCpuState() != NULL && fThread->GetStackTrace() == NULL) { + fWorker->ScheduleJob( + new(std::nothrow) GetStackTraceJob(fDebuggerInterface, + fDebuggerInterface->GetArchitecture(), fThread)); + } +} + + +void +ThreadHandler::HandleStackTraceChanged() +{ +printf("ThreadHandler::_HandleStackTraceChanged()\n"); +} + + +bool +ThreadHandler::_HandleThreadStopped(CpuState* cpuState) +{ + AutoLocker locker(fDebugModel); + + _SetThreadState(THREAD_STATE_STOPPED, cpuState); + + return true; +} + + +void +ThreadHandler::_SetThreadState(uint32 state, CpuState* cpuState) +{ + fThread->SetState(state); + fThread->SetCpuState(cpuState); +} diff --git a/src/apps/debugger/ThreadHandler.h b/src/apps/debugger/ThreadHandler.h new file mode 100644 index 0000000000..d394186500 --- /dev/null +++ b/src/apps/debugger/ThreadHandler.h @@ -0,0 +1,94 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef THREAD_HANDLER_H +#define THREAD_HANDLER_H + +#include +#include + +#include "DebugEvent.h" +#include "Thread.h" + + +class DebuggerInterface; +class TeamDebugModel; +class Worker; + + +class ThreadHandler : public Referenceable, + public HashTableLink { +public: + ThreadHandler(TeamDebugModel* debugModel, + Thread* thread, Worker* worker, + DebuggerInterface* debuggerInterface); + ~ThreadHandler(); + + void Init(); + + thread_id ThreadID() const { return fThread->ID(); } + Thread* GetThread() const { return fThread; } + + bool HandleThreadDebugged( + ThreadDebuggedEvent* event); + bool HandleDebuggerCall( + DebuggerCallEvent* event); + bool HandleBreakpointHit( + BreakpointHitEvent* event); + bool HandleWatchpointHit( + WatchpointHitEvent* event); + bool HandleSingleStep( + SingleStepEvent* event); + bool HandleExceptionOccurred( + ExceptionOccurredEvent* event); + + void HandleThreadAction(uint32 action); + + void HandleThreadStateChanged(); + void HandleCpuStateChanged(); + void HandleStackTraceChanged(); + +private: + bool _HandleThreadStopped(CpuState* cpuState); + + void _SetThreadState(uint32 state, + CpuState* cpuState); + +private: + TeamDebugModel* fDebugModel; + Thread* fThread; + Worker* fWorker; + DebuggerInterface* fDebuggerInterface; +}; + + +struct ThreadHandlerHashDefinition { + typedef thread_id KeyType; + typedef ThreadHandler ValueType; + + size_t HashKey(thread_id key) const + { + return (size_t)key; + } + + size_t Hash(const ThreadHandler* value) const + { + return HashKey(value->ThreadID()); + } + + bool Compare(thread_id key, ThreadHandler* value) const + { + return value->ThreadID() == key; + } + + HashTableLink* GetLink(ThreadHandler* value) const + { + return value; + } +}; + +typedef OpenHashTable ThreadHandlerTable; + + +#endif // THREAD_HANDLER_H