root/src/kits/debugger/model/Thread.cpp
/*
 * Copyright 2013-2016, Rene Gollent, rene@gollent.com.
 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Distributed under the terms of the MIT License.
 */

#include "model/Thread.h"

#include <stdio.h>

#include "CpuState.h"
#include "StackTrace.h"
#include "Team.h"


Thread::Thread(Team* team, thread_id threadID)
        :
        fTeam(team),
        fID(threadID),
        fState(THREAD_STATE_UNKNOWN),
        fReturnValueInfos(NULL),
        fStopRequestPending(false),
        fStoppedReason(THREAD_STOPPED_UNKNOWN),
        fCpuState(NULL),
        fStackTrace(NULL)
{
}


Thread::~Thread()
{
        if (fCpuState != NULL)
                fCpuState->ReleaseReference();
        if (fStackTrace != NULL)
                fStackTrace->ReleaseReference();

        ClearReturnValueInfos();
        delete fReturnValueInfos;
}


status_t
Thread::Init()
{
        fReturnValueInfos = new(std::nothrow) ReturnValueInfoList;
        if (fReturnValueInfos == NULL)
                return B_NO_MEMORY;

        return B_OK;
}


bool
Thread::IsMainThread() const
{
        return fID == fTeam->ID();
}


void
Thread::SetName(const BString& name)
{
        fName = name;
}


void
Thread::SetState(uint32 state, uint32 reason, const BString& info)
{
        if (state == fState && reason == fStoppedReason)
                return;

        fState = state;
        fStoppedReason = reason;
        fStoppedReasonInfo = info;

        // unset CPU state and stack trace, if the thread isn't stopped
        if (fState != THREAD_STATE_STOPPED) {
                SetCpuState(NULL);
                SetStackTrace(NULL);
                ClearReturnValueInfos();
                fStopRequestPending = false;
        }

        fTeam->NotifyThreadStateChanged(this);
}


void
Thread::SetCpuState(CpuState* state)
{
        if (state == fCpuState)
                return;

        if (fCpuState != NULL)
                fCpuState->ReleaseReference();

        fCpuState = state;

        if (fCpuState != NULL)
                fCpuState->AcquireReference();

        fTeam->NotifyThreadCpuStateChanged(this);
}


void
Thread::SetStackTrace(StackTrace* trace)
{
        if (trace == fStackTrace)
                return;

        if (fStackTrace != NULL)
                fStackTrace->ReleaseReference();

        fStackTrace = trace;

        if (fStackTrace != NULL)
                fStackTrace->AcquireReference();

        fTeam->NotifyThreadStackTraceChanged(this);
}

void
Thread::SetStopRequestPending()
{
        fStopRequestPending = true;
}


status_t
Thread::AddReturnValueInfo(ReturnValueInfo* info)
{
        if (!fReturnValueInfos->AddItem(info))
                return B_NO_MEMORY;

        info->AcquireReference();
        return B_OK;
}


void
Thread::ClearReturnValueInfos()
{
        for (int32 i = 0; i < fReturnValueInfos->CountItems(); i++)
                fReturnValueInfos->ItemAt(i)->ReleaseReference();

        fReturnValueInfos->MakeEmpty();
}