root/src/apps/debuganalyzer/model/Model.h
/*
 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Distributed under the terms of the MIT License.
 */
#ifndef MODEL_H
#define MODEL_H


#include <stdlib.h>

#include <OS.h>
#include <String.h>

#include <ObjectList.h>
#include <Referenceable.h>
#include <util/OpenHashTable.h>

#include <system_profiler_defs.h>
#include <util/SinglyLinkedList.h>


enum ThreadState {
        RUNNING,
        STILL_RUNNING,
        PREEMPTED,
        READY,
        WAITING,
        UNKNOWN
};

const char* thread_state_name(ThreadState state);
const char* wait_object_type_name(uint32 type);


class Model : public BReferenceable {
public:
                        struct creation_time_id;
                        struct type_and_object;
                        class CPU;
                        struct IOOperation;
                        struct IORequest;
                        class IOScheduler;
                        class WaitObjectGroup;
                        class WaitObject;
                        class ThreadWaitObject;
                        class ThreadWaitObjectGroup;
                        class Team;
                        class Thread;
                        struct CompactThreadSchedulingState;
                        struct ThreadSchedulingState;
                        struct ThreadSchedulingStateDefinition;
                        typedef BOpenHashTable<ThreadSchedulingStateDefinition>
                                ThreadSchedulingStateTable;
                        class SchedulingState;
                        class CompactSchedulingState;

public:
                                                                Model(const char* dataSourceName,
                                                                        void* eventData, size_t eventDataSize,
                                                                        system_profiler_event_header** events,
                                                                        size_t eventCount);
                                                                ~Model();

        inline  const char*                     DataSourceName() const;
        inline  void*                           EventData() const;
        inline  size_t                          EventDataSize() const;
        inline  system_profiler_event_header** Events() const;
        inline  size_t                          CountEvents() const;
                        size_t                          ClosestEventIndex(nanotime_t eventTime) const;
                                                                        // finds the greatest event with event
                                                                        // time >= eventTime; may return
                                                                        // CountEvents()

                        bool                            AddAssociatedData(void* data);
                        void                            RemoveAssociatedData(void* data);

                        void                            LoadingFinished();

        inline  nanotime_t                      BaseTime() const;
                        void                            SetBaseTime(nanotime_t time);

        inline  nanotime_t                      LastEventTime() const;
                        void                            SetLastEventTime(nanotime_t time);

        inline  nanotime_t                      IdleTime() const;

        inline  int32                           CountCPUs() const;
                        bool                            SetCPUCount(int32 count);
        inline  CPU*                            CPUAt(int32 index) const;

                        int32                           CountTeams() const;
                        Team*                           TeamAt(int32 index) const;
                        Team*                           TeamByID(team_id id) const;
                        Team*                           AddTeam(
                                                                        const system_profiler_team_added* event,
                                                                        nanotime_t time);

                        int32                           CountThreads() const;
                        Thread*                         ThreadAt(int32 index) const;
                        Thread*                         ThreadByID(thread_id id) const;
                        Thread*                         AddThread(
                                                                        const system_profiler_thread_added* event,
                                                                        nanotime_t time);

                        WaitObject*                     AddWaitObject(
                                                                        const system_profiler_wait_object_info*
                                                                                event,
                                                                        WaitObjectGroup** _waitObjectGroup);

                        int32                           CountWaitObjectGroups() const;
                        WaitObjectGroup*        WaitObjectGroupAt(int32 index) const;
                        WaitObjectGroup*        WaitObjectGroupFor(uint32 type,
                                                                        addr_t object) const;

                        ThreadWaitObject*       AddThreadWaitObject(thread_id threadID,
                                                                        WaitObject* waitObject,
                                                                        ThreadWaitObjectGroup**
                                                                                _threadWaitObjectGroup);
                        ThreadWaitObjectGroup* ThreadWaitObjectGroupFor(
                                                                        thread_id threadID, uint32 type,
                                                                        addr_t object) const;

                        int32                           CountIOSchedulers() const;
                        IOScheduler*            IOSchedulerAt(int32 index) const;
                        IOScheduler*            IOSchedulerByID(int32 id) const;
                        IOScheduler*            AddIOScheduler(
                                                                        system_profiler_io_scheduler_added* event);

                        bool                            AddSchedulingStateSnapshot(
                                                                        const SchedulingState& state,
                                                                        off_t eventOffset);
                                                                        // must be added in order (of time)
                        const CompactSchedulingState* ClosestSchedulingState(
                                                                        nanotime_t eventTime) const;
                                                                        // returns the closest previous state

private:
                        typedef BObjectList<CPU, true> CPUList;
                        typedef BObjectList<Team, true> TeamList;
                        typedef BObjectList<Thread, true> ThreadList;
                        typedef BObjectList<WaitObjectGroup, true> WaitObjectGroupList;
                        typedef BObjectList<IOScheduler, true> IOSchedulerList;
                        typedef BObjectList<CompactSchedulingState> SchedulingStateList;

private:
        static  int                                     _CompareEventTimeSchedulingState(
                                                                        const nanotime_t* time,
                                                                        const CompactSchedulingState* state);

private:
                        BString                         fDataSourceName;
                        void*                           fEventData;
                        system_profiler_event_header** fEvents;
                        size_t                          fEventDataSize;
                        size_t                          fEventCount;
                        int32                           fCPUCount;
                        nanotime_t                      fBaseTime;
                        nanotime_t                      fLastEventTime;
                        nanotime_t                      fIdleTime;
                        CPUList                         fCPUs;
                        TeamList                        fTeams;         // sorted by ID
                        ThreadList                      fThreads;       // sorted by ID
                        WaitObjectGroupList     fWaitObjectGroups;
                        IOSchedulerList         fIOSchedulers;
                        SchedulingStateList     fSchedulingStates;
                        BList                           fAssociatedData;
};


struct Model::creation_time_id {
        nanotime_t      time;
        thread_id       id;
};


struct Model::type_and_object {
        uint32          type;
        addr_t          object;
};


class Model::CPU {
public:
                                                                CPU();

        inline  nanotime_t                      IdleTime() const;
                        void                            SetIdleTime(nanotime_t time);

private:
                        nanotime_t                      fIdleTime;
};


struct Model::IOOperation {
        system_profiler_io_operation_started*   startedEvent;
        system_profiler_io_operation_finished*  finishedEvent;

        static inline int                       CompareByTime(const IOOperation* a,
                                                                        const IOOperation* b);

        inline  nanotime_t                      StartedTime() const;
        inline  nanotime_t                      FinishedTime() const;
        inline  bool                            IsFinished() const;
        inline  off_t                           Offset() const;
        inline  size_t                          Length() const;
        inline  bool                            IsWrite() const;
        inline  status_t                        Status() const;
        inline  size_t                          BytesTransferred() const;
};


struct Model::IORequest {
        system_profiler_io_request_scheduled*   scheduledEvent;
        system_profiler_io_request_finished*    finishedEvent;
        size_t                                                                  operationCount;
        IOOperation                                                             operations[0];

                                                                IORequest(
                                                                        system_profiler_io_request_scheduled*
                                                                                scheduledEvent,
                                                                        system_profiler_io_request_finished*
                                                                                finishedEvent,
                                                                        size_t operationCount);
                                                                ~IORequest();

        static  IORequest*                      Create(
                                                                        system_profiler_io_request_scheduled*
                                                                                scheduledEvent,
                                                                        system_profiler_io_request_finished*
                                                                        finishedEvent,
                                                                        size_t operationCount);
                        void                            Delete();

        inline  nanotime_t                      ScheduledTime() const;
        inline  nanotime_t                      FinishedTime() const;
        inline  bool                            IsFinished() const;
        inline  int32                           Scheduler() const;
        inline  off_t                           Offset() const;
        inline  size_t                          Length() const;
        inline  bool                            IsWrite() const;
        inline  uint8                           Priority() const;
        inline  status_t                        Status() const;
        inline  size_t                          BytesTransferred() const;


        static inline bool                      TimeLess(const IORequest* a,
                                                                        const IORequest* b);
        static inline bool                      SchedulerTimeLess(const IORequest* a,
                                                                        const IORequest* b);
        static inline int                       CompareSchedulerTime(const IORequest* a,
                                                                        const IORequest* b);
};


class Model::IOScheduler {
public:
                                                                IOScheduler(
                                                                        system_profiler_io_scheduler_added* event,
                                                                        int32 index);

        inline  int32                           ID() const;
        inline  const char*                     Name() const;
        inline  int32                           Index() const;

private:
                        system_profiler_io_scheduler_added* fAddedEvent;
                        int32                           fIndex;
};


class Model::WaitObject {
public:
                                                                WaitObject(
                                                                        const system_profiler_wait_object_info*
                                                                                event);
                                                                ~WaitObject();

        inline  uint32                          Type() const;
        inline  addr_t                          Object() const;
        inline  const char*                     Name() const;
        inline  addr_t                          ReferencedObject();

        inline  int64                           Waits() const;
        inline  nanotime_t                      TotalWaitTime() const;

                        void                            AddWait(nanotime_t waitTime);

        static inline int                       CompareByTypeObject(const WaitObject* a,
                                                                        const WaitObject* b);
        static inline int                       CompareWithTypeObject(
                                                                        const type_and_object* key,
                                                                        const WaitObject* object);

private:
                        const system_profiler_wait_object_info* fEvent;

private:
                        int64                           fWaits;
                        nanotime_t                      fTotalWaitTime;
};


class Model::WaitObjectGroup {
public:
                                                                WaitObjectGroup(WaitObject* waitObject);
                                                                ~WaitObjectGroup();

        inline  uint32                          Type() const;
        inline  addr_t                          Object() const;
        inline  const char*                     Name() const;

                        int64                           Waits();
                        nanotime_t                      TotalWaitTime();

        inline  WaitObject*                     MostRecentWaitObject() const;

        inline  int32                           CountWaitObjects() const;
        inline  Model::WaitObject*      WaitObjectAt(int32 index) const;

        inline  void                            AddWaitObject(WaitObject* waitObject);

        static inline int                       CompareByTypeObject(const WaitObjectGroup* a,
                                                                        const WaitObjectGroup* b);
        static inline int                       CompareWithTypeObject(
                                                                        const type_and_object* key,
                                                                        const WaitObjectGroup* group);

private:
                        typedef BObjectList<WaitObject> WaitObjectList;

                        void                            _ComputeWaits();

private:
                        WaitObjectList          fWaitObjects;
                        int64                           fWaits;
                        nanotime_t                      fTotalWaitTime;
};


class Model::ThreadWaitObject
        : public SinglyLinkedListLinkImpl<ThreadWaitObject> {
public:
                                                                ThreadWaitObject(WaitObject* waitObject);
                                                                ~ThreadWaitObject();

        inline  WaitObject*                     GetWaitObject() const;

        inline  uint32                          Type() const;
        inline  addr_t                          Object() const;
        inline  const char*                     Name() const;
        inline  addr_t                          ReferencedObject();

        inline  int64                           Waits() const;
        inline  nanotime_t                      TotalWaitTime() const;

                        void                            AddWait(nanotime_t waitTime);

private:
                        WaitObject*                     fWaitObject;
                        int64                           fWaits;
                        nanotime_t                      fTotalWaitTime;
};


class Model::ThreadWaitObjectGroup {
public:
                                                                ThreadWaitObjectGroup(
                                                                        ThreadWaitObject* threadWaitObject);
                                                                ~ThreadWaitObjectGroup();

        inline  uint32                          Type() const;
        inline  addr_t                          Object() const;
        inline  const char*                     Name() const;

        inline  ThreadWaitObject*       MostRecentThreadWaitObject() const;
        inline  WaitObject*                     MostRecentWaitObject() const;

        inline  void                            AddWaitObject(
                                                                        ThreadWaitObject* threadWaitObject);

                        bool                            GetThreadWaitObjects(
                                                                        BObjectList<ThreadWaitObject>& objects);

        static inline int                       CompareByTypeObject(
                                                                        const ThreadWaitObjectGroup* a,
                                                                        const ThreadWaitObjectGroup* b);
        static inline int                       CompareWithTypeObject(
                                                                        const type_and_object* key,
                                                                        const ThreadWaitObjectGroup* group);

private:
                        typedef SinglyLinkedList<ThreadWaitObject> ThreadWaitObjectList;

private:
                        ThreadWaitObjectList fWaitObjects;
};


class Model::Team {
public:
                                                                Team(const system_profiler_team_added* event,
                                                                        nanotime_t time);
                                                                ~Team();

        inline  team_id                         ID() const;
        inline  const char*                     Name() const;

        inline  nanotime_t                      CreationTime() const;
        inline  nanotime_t                      DeletionTime() const;

                        bool                            AddThread(Thread* thread);

        inline  void                            SetDeletionTime(nanotime_t time);

        static inline int                       CompareByID(const Team* a, const Team* b);
        static inline int                       CompareWithID(const team_id* id,
                                                                        const Team* team);

private:
                        typedef BObjectList<Thread> ThreadList;

private:
                        const system_profiler_team_added* fCreationEvent;
                        nanotime_t                      fCreationTime;
                        nanotime_t                      fDeletionTime;
                        ThreadList                      fThreads;       // sorted by creation time, ID
};


class Model::Thread {
public:
                                                                Thread(Team* team,
                                                                        const system_profiler_thread_added* event,
                                                                        nanotime_t time);
                                                                ~Thread();

        inline  thread_id                       ID() const;
        inline  const char*                     Name() const;
        inline  Team*                           GetTeam() const;

        inline  int32                           Index() const;
        inline  void                            SetIndex(int32 index);

        inline  system_profiler_event_header** Events() const;
        inline  size_t                          CountEvents() const;
                        void                            SetEvents(system_profiler_event_header** events,
                                                                        size_t eventCount);

        inline  IORequest**                     IORequests() const;
        inline  size_t                          CountIORequests() const;
                        void                            SetIORequests(IORequest** requests,
                                                                        size_t requestCount);
                        size_t                          ClosestRequestStartIndex(
                                                                        nanotime_t minRequestStartTime) const;
                                                                        // Returns the index of the first request
                                                                        // with a start time >= minRequestStartTime.
                                                                        // minRequestStartTime is absolute, not
                                                                        // base time relative.

        inline  nanotime_t                      CreationTime() const;
        inline  nanotime_t                      DeletionTime() const;

        inline  int64                           Runs() const;
        inline  nanotime_t                      TotalRunTime() const;
        inline  int64                           Reruns() const;
        inline  nanotime_t                      TotalRerunTime() const;
        inline  int64                           Latencies() const;
        inline  nanotime_t                      TotalLatency() const;
        inline  int64                           Preemptions() const;
        inline  int64                           Waits() const;
        inline  nanotime_t                      TotalWaitTime() const;
        inline  nanotime_t                      UnspecifiedWaitTime() const;

        inline  int64                           IOCount() const;
        inline  nanotime_t                      IOTime() const;

                        ThreadWaitObjectGroup* ThreadWaitObjectGroupFor(uint32 type,
                                                                        addr_t object) const;
        inline  int32                           CountThreadWaitObjectGroups() const;
        inline  ThreadWaitObjectGroup* ThreadWaitObjectGroupAt(int32 index) const;

        inline  void                            SetDeletionTime(nanotime_t time);

                        void                            AddRun(nanotime_t runTime);
                        void                            AddRerun(nanotime_t runTime);
                        void                            AddLatency(nanotime_t latency);
                        void                            AddPreemption(nanotime_t runTime);
                        void                            AddWait(nanotime_t waitTime);
                        void                            AddUnspecifiedWait(nanotime_t waitTime);

                        ThreadWaitObject*       AddThreadWaitObject(WaitObject* waitObject,
                                                                        ThreadWaitObjectGroup**
                                                                                _threadWaitObjectGroup);

                        void                            SetIOs(int64 count, nanotime_t time);

        static inline int                       CompareByID(const Thread* a, const Thread* b);
        static inline int                       CompareWithID(const thread_id* id,
                                                                        const Thread* thread);

        static inline int                       CompareByCreationTimeID(const Thread* a,
                                                                        const Thread* b);
        static inline int                       CompareWithCreationTimeID(
                                                                        const creation_time_id* key,
                                                                        const Thread* thread);

private:
                        typedef BObjectList<ThreadWaitObjectGroup, true>
                                ThreadWaitObjectGroupList;

private:
                        system_profiler_event_header** fEvents;
                        size_t                          fEventCount;

                        IORequest**                     fIORequests;
                        size_t                          fIORequestCount;

                        Team*                           fTeam;
                        const system_profiler_thread_added* fCreationEvent;
                        nanotime_t                      fCreationTime;
                        nanotime_t                      fDeletionTime;

                        int64                           fRuns;
                        nanotime_t                      fTotalRunTime;
                        nanotime_t                      fMinRunTime;
                        nanotime_t                      fMaxRunTime;

                        int64                           fLatencies;
                        nanotime_t                      fTotalLatency;
                        nanotime_t                      fMinLatency;
                        nanotime_t                      fMaxLatency;

                        int64                           fReruns;
                        nanotime_t                      fTotalRerunTime;
                        nanotime_t                      fMinRerunTime;
                        nanotime_t                      fMaxRerunTime;

                        int64                           fWaits;
                        nanotime_t                      fTotalWaitTime;
                        nanotime_t                      fUnspecifiedWaitTime;

                        int64                           fIOCount;
                        nanotime_t                      fIOTime;

                        int64                           fPreemptions;

                        int32                           fIndex;

                        ThreadWaitObjectGroupList fWaitObjectGroups;
};


struct Model::CompactThreadSchedulingState {
                        nanotime_t                      lastTime;
                        Model::Thread*          thread;
                        ThreadWaitObject*       waitObject;
                        ThreadState                     state;
                        uint8                           priority;

public:
                        thread_id                       ID() const      { return thread->ID(); }

        inline  CompactThreadSchedulingState& operator=(
                                                                        const CompactThreadSchedulingState& other);
};


struct Model::ThreadSchedulingState : CompactThreadSchedulingState {
                        ThreadSchedulingState* next;

public:
        inline                                          ThreadSchedulingState(
                                                                        const CompactThreadSchedulingState& other);
        inline                                          ThreadSchedulingState(Thread* thread);
};


struct Model::ThreadSchedulingStateDefinition {
        typedef thread_id                               KeyType;
        typedef ThreadSchedulingState   ValueType;

        size_t HashKey(thread_id key) const
                { return (size_t)key; }

        size_t Hash(const ThreadSchedulingState* value) const
                { return (size_t)value->ID(); }

        bool Compare(thread_id key, const ThreadSchedulingState* value) const
                { return key == value->ID(); }

        ThreadSchedulingState*& GetLink(ThreadSchedulingState* value) const
                { return value->next; }
};


class Model::SchedulingState {
public:
        inline                                          SchedulingState();
        virtual                                         ~SchedulingState();

                        status_t                        Init();
                        status_t                        Init(const CompactSchedulingState* state);
                        void                            Clear();

        inline  nanotime_t                      LastEventTime() const { return fLastEventTime; }
        inline  void                            SetLastEventTime(nanotime_t time);

        inline  ThreadSchedulingState* LookupThread(thread_id threadID) const;
        inline  void                            InsertThread(ThreadSchedulingState* thread);
        inline  void                            RemoveThread(ThreadSchedulingState* thread);
        inline  const ThreadSchedulingStateTable& ThreadStates() const;

protected:
        virtual void                            DeleteThread(ThreadSchedulingState* thread);

private:
                        nanotime_t                      fLastEventTime;
                        ThreadSchedulingStateTable fThreadStates;
};


class Model::CompactSchedulingState {
public:
        static  CompactSchedulingState* Create(const SchedulingState& state,
                                                                        off_t eventOffset);
                        void                            Delete();

        inline  off_t                           EventOffset() const;
        inline  nanotime_t                      LastEventTime() const;

        inline  int32                           CountThreadsStates() const;
        inline  const CompactThreadSchedulingState* ThreadStateAt(int32 index)
                                                                        const;

private:
        friend class BObjectList<CompactSchedulingState>;
                // work-around for our private destructor

private:
                                                                CompactSchedulingState();
        inline                                          ~CompactSchedulingState() {}

private:
                        nanotime_t                      fLastEventTime;
                        off_t                           fEventOffset;
                        int32                           fThreadCount;
                        CompactThreadSchedulingState fThreadStates[0];
};


// #pragma mark - Model


const char*
Model::DataSourceName() const
{
        return fDataSourceName.String();
}


void*
Model::EventData() const
{
        return fEventData;
}


size_t
Model::EventDataSize() const
{
        return fEventDataSize;
}


system_profiler_event_header**
Model::Events() const
{
        return fEvents;
}


size_t
Model::CountEvents() const
{
        return fEventCount;
}


nanotime_t
Model::BaseTime() const
{
        return fBaseTime;
}


nanotime_t
Model::LastEventTime() const
{
        return fLastEventTime;
}


nanotime_t
Model::IdleTime() const
{
        return fIdleTime;
}


int32
Model::CountCPUs() const
{
        return fCPUCount;
}


Model::CPU*
Model::CPUAt(int32 index) const
{
        return fCPUs.ItemAt(index);
}


// #pragma mark - CPU


nanotime_t
Model::CPU::IdleTime() const
{
        return fIdleTime;
}


// #pragma mark - IOOperation


nanotime_t
Model::IOOperation::StartedTime() const
{
        return startedEvent->time;
}


nanotime_t
Model::IOOperation::FinishedTime() const
{
        return finishedEvent != NULL ? finishedEvent->time : 0;
}


bool
Model::IOOperation::IsFinished() const
{
        return finishedEvent != NULL;
}


off_t
Model::IOOperation::Offset() const
{
        return startedEvent->offset;
}


size_t
Model::IOOperation::Length() const
{
        return startedEvent->length;
}


bool
Model::IOOperation::IsWrite() const
{
        return startedEvent->write;
}


status_t
Model::IOOperation::Status() const
{
        return finishedEvent != NULL ? finishedEvent->status : B_OK;
}


size_t
Model::IOOperation::BytesTransferred() const
{
        return finishedEvent != NULL ? finishedEvent->transferred : 0;
}


/*static*/ int
Model::IOOperation::CompareByTime(const IOOperation* a, const IOOperation* b)
{
        nanotime_t timeA = a->startedEvent->time;
        nanotime_t timeB = b->startedEvent->time;

        if (timeA < timeB)
                return -1;
        return timeA == timeB ? 0 : 1;
}


// #pragma mark - IORequest


nanotime_t
Model::IORequest::ScheduledTime() const
{
        return scheduledEvent->time;
}


nanotime_t
Model::IORequest::FinishedTime() const
{
        return finishedEvent != NULL ? finishedEvent->time : 0;
}


bool
Model::IORequest::IsFinished() const
{
        return finishedEvent != NULL;
}


int32
Model::IORequest::Scheduler() const
{
        return scheduledEvent->scheduler;
}


off_t
Model::IORequest::Offset() const
{
        return scheduledEvent->offset;
}


size_t
Model::IORequest::Length() const
{
        return scheduledEvent->length;
}


bool
Model::IORequest::IsWrite() const
{
        return scheduledEvent->write;
}


uint8
Model::IORequest::Priority() const
{
        return scheduledEvent->priority;
}


status_t
Model::IORequest::Status() const
{
        return finishedEvent != NULL ? finishedEvent->status : B_OK;
}


size_t
Model::IORequest::BytesTransferred() const
{
        return finishedEvent != NULL ? finishedEvent->transferred : 0;
}


/*static*/ bool
Model::IORequest::TimeLess(const IORequest* a, const IORequest* b)
{
        return a->scheduledEvent->time < b->scheduledEvent->time;
}


/*static*/ bool
Model::IORequest::SchedulerTimeLess(const IORequest* a, const IORequest* b)
{
        int32 cmp = a->scheduledEvent->scheduler - b->scheduledEvent->scheduler;
        if (cmp != 0)
                return cmp < 0;

        return a->scheduledEvent->time < b->scheduledEvent->time;
}


/*static*/ int
Model::IORequest::CompareSchedulerTime(const IORequest* a, const IORequest* b)
{
        int32 cmp = a->scheduledEvent->scheduler - b->scheduledEvent->scheduler;
        if (cmp != 0)
                return cmp < 0;

        nanotime_t timeCmp = a->scheduledEvent->time - b->scheduledEvent->time;
        if (timeCmp == 0)
                return 0;
        return timeCmp < 0 ? -1 : 1;
}


// #pragma mark - IOScheduler


int32
Model::IOScheduler::ID() const
{
        return fAddedEvent->scheduler;
}


const char*
Model::IOScheduler::Name() const
{
        return fAddedEvent->name;
}


int32
Model::IOScheduler::Index() const
{
        return fIndex;
}


// #pragma mark - WaitObject


uint32
Model::WaitObject::Type() const
{
        return fEvent->type;
}


addr_t
Model::WaitObject::Object() const
{
        return fEvent->object;
}


const char*
Model::WaitObject::Name() const
{
        return fEvent->name;
}


addr_t
Model::WaitObject::ReferencedObject()
{
        return fEvent->referenced_object;
}


int64
Model::WaitObject::Waits() const
{
        return fWaits;
}


nanotime_t
Model::WaitObject::TotalWaitTime() const
{
        return fTotalWaitTime;
}


/*static*/ int
Model::WaitObject::CompareByTypeObject(const WaitObject* a, const WaitObject* b)
{
        type_and_object key;
        key.type = a->Type();
        key.object = a->Object();

        return CompareWithTypeObject(&key, b);
}


/*static*/ int
Model::WaitObject::CompareWithTypeObject(const type_and_object* key,
        const WaitObject* object)
{
        if (key->type == object->Type()) {
                if (key->object == object->Object())
                        return 0;
                return key->object < object->Object() ? -1 : 1;
        }

        return key->type < object->Type() ? -1 : 1;
}


// #pragma mark - WaitObjectGroup


uint32
Model::WaitObjectGroup::Type() const
{
        return MostRecentWaitObject()->Type();
}


addr_t
Model::WaitObjectGroup::Object() const
{
        return MostRecentWaitObject()->Object();
}


const char*
Model::WaitObjectGroup::Name() const
{
        return MostRecentWaitObject()->Name();
}


Model::WaitObject*
Model::WaitObjectGroup::MostRecentWaitObject() const
{
        return fWaitObjects.ItemAt(fWaitObjects.CountItems() - 1);
}


int32
Model::WaitObjectGroup::CountWaitObjects() const
{
        return fWaitObjects.CountItems();
}


Model::WaitObject*
Model::WaitObjectGroup::WaitObjectAt(int32 index) const
{
        return fWaitObjects.ItemAt(index);
}


void
Model::WaitObjectGroup::AddWaitObject(WaitObject* waitObject)
{
        fWaitObjects.AddItem(waitObject);
}


/*static*/ int
Model::WaitObjectGroup::CompareByTypeObject(
        const WaitObjectGroup* a, const WaitObjectGroup* b)
{
        return WaitObject::CompareByTypeObject(a->MostRecentWaitObject(),
                b->MostRecentWaitObject());
}


/*static*/ int
Model::WaitObjectGroup::CompareWithTypeObject(const type_and_object* key,
        const WaitObjectGroup* group)
{
        return WaitObject::CompareWithTypeObject(key,
                group->MostRecentWaitObject());
}


// #pragma mark - ThreadWaitObject


Model::WaitObject*
Model::ThreadWaitObject::GetWaitObject() const
{
        return fWaitObject;
}


uint32
Model::ThreadWaitObject::Type() const
{
        return fWaitObject->Type();
}


addr_t
Model::ThreadWaitObject::Object() const
{
        return fWaitObject->Object();
}


const char*
Model::ThreadWaitObject::Name() const
{
        return fWaitObject->Name();
}


addr_t
Model::ThreadWaitObject::ReferencedObject()
{
        return fWaitObject->ReferencedObject();
}


int64
Model::ThreadWaitObject::Waits() const
{
        return fWaits;
}


nanotime_t
Model::ThreadWaitObject::TotalWaitTime() const
{
        return fTotalWaitTime;
}


// #pragma mark - ThreadWaitObjectGroup


uint32
Model::ThreadWaitObjectGroup::Type() const
{
        return MostRecentThreadWaitObject()->Type();
}


addr_t
Model::ThreadWaitObjectGroup::Object() const
{
        return MostRecentThreadWaitObject()->Object();
}


const char*
Model::ThreadWaitObjectGroup::Name() const
{
        return MostRecentThreadWaitObject()->Name();
}


Model::ThreadWaitObject*
Model::ThreadWaitObjectGroup::MostRecentThreadWaitObject() const
{
        return fWaitObjects.Head();
}


Model::WaitObject*
Model::ThreadWaitObjectGroup::MostRecentWaitObject() const
{
        return MostRecentThreadWaitObject()->GetWaitObject();
}


void
Model::ThreadWaitObjectGroup::AddWaitObject(ThreadWaitObject* threadWaitObject)
{
        fWaitObjects.Add(threadWaitObject);
}


/*static*/ int
Model::ThreadWaitObjectGroup::CompareByTypeObject(
        const ThreadWaitObjectGroup* a, const ThreadWaitObjectGroup* b)
{
        return WaitObject::CompareByTypeObject(a->MostRecentWaitObject(),
                b->MostRecentWaitObject());
}


/*static*/ int
Model::ThreadWaitObjectGroup::CompareWithTypeObject(const type_and_object* key,
        const ThreadWaitObjectGroup* group)
{
        return WaitObject::CompareWithTypeObject(key,
                group->MostRecentWaitObject());
}


// #pragma mark - Team


team_id
Model::Team::ID() const
{
        return fCreationEvent->team;
}


const char*
Model::Team::Name() const
{
        return fCreationEvent->name;
                // TODO: We should probably return the last exec name!
}


nanotime_t
Model::Team::CreationTime() const
{
        return fCreationTime;
}


nanotime_t
Model::Team::DeletionTime() const
{
        return fDeletionTime;
}


void
Model::Team::SetDeletionTime(nanotime_t time)
{
        fDeletionTime = time;
}


/*static*/ int
Model::Team::CompareByID(const Team* a, const Team* b)
{
        return a->ID() - b->ID();
}


/*static*/ int
Model::Team::CompareWithID(const team_id* id, const Team* team)
{
        return *id - team->ID();
}


// #pragma mark - Thread


thread_id
Model::Thread::ID() const
{
        return fCreationEvent->thread;
}


const char*
Model::Thread::Name() const
{
        return fCreationEvent->name;
}


Model::Team*
Model::Thread::GetTeam() const
{
        return fTeam;
}


nanotime_t
Model::Thread::CreationTime() const
{
        return fCreationTime;
}


nanotime_t
Model::Thread::DeletionTime() const
{
        return fDeletionTime;
}


int32
Model::Thread::Index() const
{
        return fIndex;
}


void
Model::Thread::SetIndex(int32 index)
{
        fIndex = index;
}


system_profiler_event_header**
Model::Thread::Events() const
{
        return fEvents;
}


size_t
Model::Thread::CountEvents() const
{
        return fEventCount;
}


Model::IORequest**
Model::Thread::IORequests() const
{
        return fIORequests;
}


size_t
Model::Thread::CountIORequests() const
{
        return fIORequestCount;
}


int64
Model::Thread::Runs() const
{
        return fRuns;
}


nanotime_t
Model::Thread::TotalRunTime() const
{
        return fTotalRunTime;
}


int64
Model::Thread::Reruns() const
{
        return fReruns;
}


nanotime_t
Model::Thread::TotalRerunTime() const
{
        return fTotalRerunTime;
}


int64
Model::Thread::Latencies() const
{
        return fLatencies;
}


nanotime_t
Model::Thread::TotalLatency() const
{
        return fTotalLatency;
}


int64
Model::Thread::Preemptions() const
{
        return fPreemptions;
}


int64
Model::Thread::Waits() const
{
        return fWaits;
}


nanotime_t
Model::Thread::TotalWaitTime() const
{
        return fTotalWaitTime;
}


nanotime_t
Model::Thread::UnspecifiedWaitTime() const
{
        return fUnspecifiedWaitTime;
}


int64
Model::Thread::IOCount() const
{
        return fIOCount;
}


nanotime_t
Model::Thread::IOTime() const
{
        return fIOTime;
}


int32
Model::Thread::CountThreadWaitObjectGroups() const
{
        return fWaitObjectGroups.CountItems();
}


Model::ThreadWaitObjectGroup*
Model::Thread::ThreadWaitObjectGroupAt(int32 index) const
{
        return fWaitObjectGroups.ItemAt(index);
}


void
Model::Thread::SetDeletionTime(nanotime_t time)
{
        fDeletionTime = time;
}


/*static*/ int
Model::Thread::CompareByID(const Thread* a, const Thread* b)
{
        return a->ID() - b->ID();
}


/*static*/ int
Model::Thread::CompareWithID(const thread_id* id, const Thread* thread)
{
        return *id - thread->ID();
}


/*static*/ int
Model::Thread::CompareByCreationTimeID(const Thread* a, const Thread* b)
{
        creation_time_id key;
        key.time = a->fCreationTime;
        key.id = a->ID();
        return CompareWithCreationTimeID(&key, b);
}


/*static*/ int
Model::Thread::CompareWithCreationTimeID(const creation_time_id* key,
        const Thread* thread)
{
        nanotime_t cmp = key->time - thread->fCreationTime;
        if (cmp == 0)
                return key->id - thread->ID();
        return cmp < 0 ? -1 : 1;
}


// #pragma mark - CompactThreadSchedulingState


Model::CompactThreadSchedulingState&
Model::CompactThreadSchedulingState::operator=(
        const CompactThreadSchedulingState& other)
{
        lastTime = other.lastTime;
        thread = other.thread;
        waitObject = other.waitObject;
        state = other.state;
        priority = other.priority;
        return *this;
}


// #pragma mark - ThreadSchedulingState


Model::ThreadSchedulingState::ThreadSchedulingState(
        const CompactThreadSchedulingState& other)
{
        this->CompactThreadSchedulingState::operator=(other);
}


Model::ThreadSchedulingState::ThreadSchedulingState(Thread* thread)
{
        lastTime = 0;
        this->thread = thread;
        waitObject = NULL;
        state = UNKNOWN;
}


// #pragma mark - SchedulingState


Model::SchedulingState::SchedulingState()
        :
        fLastEventTime(-1)
{
}


void
Model::SchedulingState::SetLastEventTime(nanotime_t time)
{
        fLastEventTime = time;
}


Model::ThreadSchedulingState*
Model::SchedulingState::LookupThread(thread_id threadID) const
{
        return fThreadStates.Lookup(threadID);
}


void
Model::SchedulingState::InsertThread(ThreadSchedulingState* thread)
{
        fThreadStates.Insert(thread);
}


void
Model::SchedulingState::RemoveThread(ThreadSchedulingState* thread)
{
        fThreadStates.Remove(thread);
}


const Model::ThreadSchedulingStateTable&
Model::SchedulingState::ThreadStates() const
{
        return fThreadStates;
}


// #pragma mark - CompactSchedulingState


off_t
Model::CompactSchedulingState::EventOffset() const
{
        return fEventOffset;
}


nanotime_t
Model::CompactSchedulingState::LastEventTime() const
{
        return fLastEventTime;
}


int32
Model::CompactSchedulingState::CountThreadsStates() const
{
        return fThreadCount;
}


const Model::CompactThreadSchedulingState*
Model::CompactSchedulingState::ThreadStateAt(int32 index) const
{
        return index >= 0 && index < fThreadCount ? &fThreadStates[index] : NULL;
}


#endif  // MODEL_H