152906712SIngo Weinhold/*
252906712SIngo Weinhold * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
352906712SIngo Weinhold * Distributed under the terms of the MIT License.
452906712SIngo Weinhold */
552906712SIngo Weinhold
6d8d4b902SIngo Weinhold
752906712SIngo Weinhold#include "thread_window/ActivityPage.h"
852906712SIngo Weinhold
952906712SIngo Weinhold#include <new>
1052906712SIngo Weinhold
11639e61adSIngo Weinhold#include <GridLayoutBuilder.h>
1252906712SIngo Weinhold#include <GroupLayoutBuilder.h>
13639e61adSIngo Weinhold#include <Message.h>
14972c78f8SIngo Weinhold#include <ScrollView.h>
1552906712SIngo Weinhold
1652906712SIngo Weinhold#include <AutoDeleter.h>
1752906712SIngo Weinhold
18639e61adSIngo Weinhold#include "ColorCheckBox.h"
19639e61adSIngo Weinhold#include "MessageCodes.h"
2052906712SIngo Weinhold#include "ThreadModel.h"
2152906712SIngo Weinhold
22d8d4b902SIngo Weinhold#include "chart/NanotimeChartAxisLegendSource.h"
2352906712SIngo Weinhold#include "chart/Chart.h"
2452906712SIngo Weinhold#include "chart/ChartDataSource.h"
2545febed6SIngo Weinhold#include "chart/DefaultChartAxisLegendSource.h"
2652906712SIngo Weinhold#include "chart/LegendChartAxis.h"
2752906712SIngo Weinhold#include "chart/LineChartRenderer.h"
2852906712SIngo Weinhold#include "chart/StringChartLegend.h"
2952906712SIngo Weinhold
3052906712SIngo Weinhold
3152906712SIngo Weinholdenum {
3252906712SIngo Weinhold	RUN_TIME			= 0,
3352906712SIngo Weinhold	WAIT_TIME			= 1,
3452906712SIngo Weinhold	PREEMPTION_TIME		= 2,
3552906712SIngo Weinhold	LATENCY_TIME		= 3,
3652906712SIngo Weinhold	UNSPECIFIED_TIME	= 4,
3752906712SIngo Weinhold	TIME_TYPE_COUNT		= 5
3852906712SIngo Weinhold};
3952906712SIngo Weinhold
40639e61adSIngo Weinholdstatic const rgb_color kRunTimeColor		= {0, 0, 0, 255};
41639e61adSIngo Weinholdstatic const rgb_color kWaitTimeColor		= {0, 255, 0, 255};
42639e61adSIngo Weinholdstatic const rgb_color kPreemptionTimeColor	= {0, 0, 255, 255};
43639e61adSIngo Weinholdstatic const rgb_color kLatencyTimeColor	= {255, 0, 0, 255};
44639e61adSIngo Weinhold
4552906712SIngo Weinhold
4652906712SIngo Weinholdclass ThreadWindow::ActivityPage::ThreadActivityData
4752906712SIngo Weinhold	: public ChartDataSource {
4852906712SIngo Weinholdpublic:
4952906712SIngo Weinhold	ThreadActivityData(ThreadModel* model, int32 timeType)
5052906712SIngo Weinhold		:
5152906712SIngo Weinhold		fModel(model),
5252906712SIngo Weinhold		fTimeType(timeType)
5352906712SIngo Weinhold	{
5452906712SIngo Weinhold	}
5552906712SIngo Weinhold
5652906712SIngo Weinhold	virtual ChartDataRange Domain() const
5752906712SIngo Weinhold	{
5852906712SIngo Weinhold		return ChartDataRange(0.0, (double)fModel->GetModel()->LastEventTime());
5952906712SIngo Weinhold	}
6052906712SIngo Weinhold
6152906712SIngo Weinhold	virtual ChartDataRange Range() const
6252906712SIngo Weinhold	{
6352906712SIngo Weinhold		return ChartDataRange(0.0, 1.0);
6452906712SIngo Weinhold	}
6552906712SIngo Weinhold
6652906712SIngo Weinhold	virtual void GetSamples(double start, double end, double* samples,
6752906712SIngo Weinhold		int32 sampleCount)
6852906712SIngo Weinhold	{
6952906712SIngo Weinhold		thread_id threadID = fModel->GetThread()->ID();
7052906712SIngo Weinhold
7152906712SIngo Weinhold		double sampleLength = (end - start) / (double)sampleCount;
7252906712SIngo Weinhold
73d8d4b902SIngo Weinhold		int32 startIndex = fModel->FindSchedulingEvent((nanotime_t)start);
74d8d4b902SIngo Weinhold		nanotime_t baseTime = fModel->GetModel()->BaseTime();
7552906712SIngo Weinhold
7652906712SIngo Weinhold		enum ScheduleState {
7752906712SIngo Weinhold			RUNNING,
7852906712SIngo Weinhold			STILL_RUNNING,
7952906712SIngo Weinhold			PREEMPTED,
8052906712SIngo Weinhold			READY,
8152906712SIngo Weinhold			WAITING,
8252906712SIngo Weinhold			UNKNOWN
8352906712SIngo Weinhold		};
8452906712SIngo Weinhold
8552906712SIngo Weinhold		ScheduleState state = UNKNOWN;
8652906712SIngo Weinhold
8752906712SIngo Weinhold		// get the first event and guess the initial state
8852906712SIngo Weinhold		const system_profiler_event_header* header
8952906712SIngo Weinhold			= fModel->SchedulingEventAt(startIndex);
9052906712SIngo Weinhold		if (header == NULL) {
9152906712SIngo Weinhold			for (int32 i = 0; i < sampleCount; i++)
9252906712SIngo Weinhold				samples[i] = 0;
9352906712SIngo Weinhold			return;
9452906712SIngo Weinhold		}
9552906712SIngo Weinhold
9652906712SIngo Weinhold		double previousEventTime = start;
9752906712SIngo Weinhold
9852906712SIngo Weinhold		switch (header->event) {
9952906712SIngo Weinhold			case B_SYSTEM_PROFILER_THREAD_SCHEDULED:
10052906712SIngo Weinhold			{
10152906712SIngo Weinhold				system_profiler_thread_scheduled* event
10252906712SIngo Weinhold					= (system_profiler_thread_scheduled*)(header + 1);
1039f463a19SIngo Weinhold				if (event->thread == threadID) {
1049f463a19SIngo Weinhold					// thread scheduled -- it must have been ready before
10552906712SIngo Weinhold					state = READY;
1069f463a19SIngo Weinhold				} else {
1079f463a19SIngo Weinhold					// thread unscheduled -- it was running earlier, but should
1089f463a19SIngo Weinhold					// now be "still running" or "running", depending on whether
1099f463a19SIngo Weinhold					// it had been added to the run queue before
1109f463a19SIngo Weinhold					const system_profiler_event_header* previousHeader
1119f463a19SIngo Weinhold						= fModel->SchedulingEventAt(startIndex - 1);
1129f463a19SIngo Weinhold					if (previousHeader != NULL
1139f463a19SIngo Weinhold						&& previousHeader->event
1149f463a19SIngo Weinhold							== B_SYSTEM_PROFILER_THREAD_ENQUEUED_IN_RUN_QUEUE) {
1159f463a19SIngo Weinhold						state = STILL_RUNNING;
1169f463a19SIngo Weinhold					} else
1179f463a19SIngo Weinhold						state = RUNNING;
1189f463a19SIngo Weinhold				}
1199f463a19SIngo Weinhold
12052906712SIngo Weinhold				previousEventTime = event->time;
12152906712SIngo Weinhold				break;
12252906712SIngo Weinhold			}
123972c78f8SIngo Weinhold
12552906712SIngo Weinhold			{
12652906712SIngo Weinhold				system_profiler_thread_enqueued_in_run_queue* event
12752906712SIngo Weinhold					= (system_profiler_thread_enqueued_in_run_queue*)
12852906712SIngo Weinhold						(header + 1);
12952906712SIngo Weinhold				state = WAITING;
13052906712SIngo Weinhold				previousEventTime = event->time;
13152906712SIngo Weinhold				break;
13252906712SIngo Weinhold			}
133972c78f8SIngo Weinhold
13552906712SIngo Weinhold			{
13652906712SIngo Weinhold				system_profiler_thread_removed_from_run_queue* event
13752906712SIngo Weinhold					= (system_profiler_thread_removed_from_run_queue*)
13852906712SIngo Weinhold						(header + 1);
13952906712SIngo Weinhold				state = READY;
14052906712SIngo Weinhold				previousEventTime = event->time;
14152906712SIngo Weinhold				break;
14252906712SIngo Weinhold			}
14352906712SIngo Weinhold		}
14452906712SIngo Weinhold
14552906712SIngo Weinhold		double times[TIME_TYPE_COUNT] = { };
14652906712SIngo Weinhold		int32 sampleIndex = -1;
14752906712SIngo Weinhold		double nextSampleTime = start;
14852906712SIngo Weinhold
14952906712SIngo Weinhold		for (int32 i = startIndex; ; i++) {
15052906712SIngo Weinhold			header = fModel->SchedulingEventAt(i);
15152906712SIngo Weinhold			double eventTime = previousEventTime;
15252906712SIngo Weinhold			int32 timeType = -1;
15352906712SIngo Weinhold
15452906712SIngo Weinhold			if (header != NULL) {
15552906712SIngo Weinhold				switch (header->event) {
15652906712SIngo Weinhold					case B_SYSTEM_PROFILER_THREAD_SCHEDULED:
15752906712SIngo Weinhold					{
15852906712SIngo Weinhold						system_profiler_thread_scheduled* event
15952906712SIngo Weinhold							= (system_profiler_thread_scheduled*)(header + 1);
16052906712SIngo Weinhold						eventTime = double(event->time - baseTime);
161972c78f8SIngo Weinhold
16252906712SIngo Weinhold						if (event->thread == threadID) {
16352906712SIngo Weinhold							// thread scheduled
16452906712SIngo Weinhold							if (state == READY) {
16552906712SIngo Weinhold								// thread scheduled after having been woken up
16652906712SIngo Weinhold								timeType = LATENCY_TIME;
16752906712SIngo Weinhold							} else if (state == PREEMPTED) {
16852906712SIngo Weinhold								// thread scheduled after having been preempted
16952906712SIngo Weinhold								// before
17052906712SIngo Weinhold								timeType = PREEMPTION_TIME;
1719f463a19SIngo Weinhold							} else if (state == STILL_RUNNING) {
17252906712SIngo Weinhold								// Thread was running and continues to run.
17352906712SIngo Weinhold								timeType = RUN_TIME;
1749f463a19SIngo Weinhold							} else {
1759f463a19SIngo Weinhold								// Can only happen, if we're missing context.
1769f463a19SIngo Weinhold								// Impossible to guess what the thread was doing
1779f463a19SIngo Weinhold								// before.
1789f463a19SIngo Weinhold								timeType = UNSPECIFIED_TIME;
17952906712SIngo Weinhold							}
1809f463a19SIngo Weinhold
1819f463a19SIngo Weinhold							state = RUNNING;
18252906712SIngo Weinhold						} else {
18352906712SIngo Weinhold							// thread unscheduled
18452906712SIngo Weinhold							if (state == STILL_RUNNING) {
18552906712SIngo Weinhold								// thread preempted
18652906712SIngo Weinhold								state = PREEMPTED;
18752906712SIngo Weinhold							} else if (state == RUNNING) {
18852906712SIngo Weinhold								// thread starts waiting (it hadn't been added
18952906712SIngo Weinhold								// to the run queue before being unscheduled)
19052906712SIngo Weinhold								state = WAITING;
1919f463a19SIngo Weinhold							} else {
1929f463a19SIngo Weinhold								// Can only happen, if we're missing context.
1939f463a19SIngo Weinhold								// Obviously the thread was running, but we
1949f463a19SIngo Weinhold								// can't guess the new thread state.
19552906712SIngo Weinhold							}
1969f463a19SIngo Weinhold
1979f463a19SIngo Weinhold							timeType = RUN_TIME;
19852906712SIngo Weinhold						}
199972c78f8SIngo Weinhold
20052906712SIngo Weinhold						break;
20152906712SIngo Weinhold					}
202972c78f8SIngo Weinhold
20452906712SIngo Weinhold					{
20552906712SIngo Weinhold						system_profiler_thread_enqueued_in_run_queue* event
20652906712SIngo Weinhold							= (system_profiler_thread_enqueued_in_run_queue*)
20752906712SIngo Weinhold								(header + 1);
20852906712SIngo Weinhold						eventTime = double(event->time - baseTime);
209972c78f8SIngo Weinhold
21052906712SIngo Weinhold						if (state == RUNNING || state == STILL_RUNNING) {
21152906712SIngo Weinhold							// Thread was running and is reentered into the run
21252906712SIngo Weinhold							// queue. This is done by the scheduler, if the
21352906712SIngo Weinhold							// thread remains ready.
21452906712SIngo Weinhold							state = STILL_RUNNING;
21552906712SIngo Weinhold							timeType = RUN_TIME;
21652906712SIngo Weinhold						} else if (state == READY || state == PREEMPTED) {
21752906712SIngo Weinhold							// Happens only after having been removed from the
21852906712SIngo Weinhold							// run queue for altering the priority.
21952906712SIngo Weinhold							timeType = state == READY
22052906712SIngo Weinhold								? LATENCY_TIME : PREEMPTION_TIME;
22152906712SIngo Weinhold						} else {
22252906712SIngo Weinhold							// Thread was waiting and is ready now.
22352906712SIngo Weinhold							state = READY;
22452906712SIngo Weinhold							timeType = WAIT_TIME;
22552906712SIngo Weinhold						}
226972c78f8SIngo Weinhold
22752906712SIngo Weinhold						break;
22852906712SIngo Weinhold					}
229972c78f8SIngo Weinhold
23152906712SIngo Weinhold					{
23252906712SIngo Weinhold						system_profiler_thread_removed_from_run_queue* event
23352906712SIngo Weinhold							= (system_profiler_thread_removed_from_run_queue*)
23452906712SIngo Weinhold								(header + 1);
23552906712SIngo Weinhold						eventTime = double(event->time - baseTime);
236972c78f8SIngo Weinhold
23752906712SIngo Weinhold						// This really only happens when the thread priority is
23852906712SIngo Weinhold						// changed while the thread is ready.
239972c78f8SIngo Weinhold
24052906712SIngo Weinhold						if (state == RUNNING) {
24152906712SIngo Weinhold							// This should never happen.
24252906712SIngo Weinhold							state = READY;
24352906712SIngo Weinhold							timeType = RUN_TIME;
24452906712SIngo Weinhold						} else if (state == READY) {
24552906712SIngo Weinhold							// Thread was ready after having been woken up.
24652906712SIngo Weinhold							timeType = LATENCY_TIME;
24752906712SIngo Weinhold						} else if (state == PREEMPTED) {
24852906712SIngo Weinhold							// Thread was ready after having been preempted.
24952906712SIngo Weinhold							timeType = PREEMPTION_TIME;
25052906712SIngo Weinhold						} else
25152906712SIngo Weinhold							state = READY;
252972c78f8SIngo Weinhold
25352906712SIngo Weinhold						break;
25452906712SIngo Weinhold					}
25552906712SIngo Weinhold				}
25652906712SIngo Weinhold			} else {
25752906712SIngo Weinhold				// no more events for this thread -- assume things go on like
25852906712SIngo Weinhold				// this until the death of the thread
25952906712SIngo Weinhold				switch (state) {
26052906712SIngo Weinhold					case RUNNING:
26152906712SIngo Weinhold					case STILL_RUNNING:
26252906712SIngo Weinhold						timeType = RUN_TIME;
26352906712SIngo Weinhold						break;
26452906712SIngo Weinhold					case PREEMPTED:
26552906712SIngo Weinhold						timeType = PREEMPTION_TIME;
26652906712SIngo Weinhold						break;
26752906712SIngo Weinhold					case READY:
26852906712SIngo Weinhold						timeType = LATENCY_TIME;
26952906712SIngo Weinhold						break;
27052906712SIngo Weinhold					case WAITING:
27152906712SIngo Weinhold						timeType = WAIT_TIME;
27252906712SIngo Weinhold						break;
2739f463a19SIngo Weinhold					case UNKNOWN:
2749f463a19SIngo Weinhold						timeType = UNSPECIFIED_TIME;
2759f463a19SIngo Weinhold						break;
27652906712SIngo Weinhold				}
27752906712SIngo Weinhold
27852906712SIngo Weinhold				if (fModel->GetThread()->DeletionTime() >= 0) {
27952906712SIngo Weinhold					eventTime = double(fModel->GetThread()->DeletionTime()
28052906712SIngo Weinhold						- baseTime);
28152906712SIngo Weinhold					if (eventTime <= previousEventTime) {
28252906712SIngo Weinhold						// thread is dead
28352906712SIngo Weinhold						eventTime = end + 1;
28452906712SIngo Weinhold						timeType = UNSPECIFIED_TIME;
28552906712SIngo Weinhold					}
28652906712SIngo Weinhold				} else
28752906712SIngo Weinhold					eventTime = end + 1;
28852906712SIngo Weinhold			}
28952906712SIngo Weinhold
29052906712SIngo Weinhold			if (timeType < 0)
29152906712SIngo Weinhold				continue;
29252906712SIngo Weinhold
29352906712SIngo Weinhold			while (eventTime >= nextSampleTime) {
29452906712SIngo Weinhold				// We've reached the next sample. Partially add this time to the
29552906712SIngo Weinhold				// current sample.
29652906712SIngo Weinhold				times[timeType] += nextSampleTime - previousEventTime;
29752906712SIngo Weinhold				previousEventTime = nextSampleTime;
29852906712SIngo Weinhold
29952906712SIngo Weinhold				// write the sample value
30052906712SIngo Weinhold				if (sampleIndex >= 0) {
30152906712SIngo Weinhold					samples[sampleIndex] = times[fTimeType] / sampleLength;
30252906712SIngo Weinhold					if (samples[sampleIndex] > 1.0)
30352906712SIngo Weinhold						samples[sampleIndex] = 1.0;
30452906712SIngo Weinhold				}
30552906712SIngo Weinhold
30652906712SIngo Weinhold				for (int32 k = 0; k < TIME_TYPE_COUNT; k++)
30752906712SIngo Weinhold					times[k] = 0;
30852906712SIngo Weinhold
30952906712SIngo Weinhold				// compute the time of the next sample
31052906712SIngo Weinhold				if (++sampleIndex >= sampleCount)
31152906712SIngo Weinhold					return;
31252906712SIngo Weinhold				nextSampleTime = start
31352906712SIngo Weinhold					+ (end - start)
31452906712SIngo Weinhold						* (double)(sampleIndex + 1) / (double)sampleCount;
31552906712SIngo Weinhold			}
31652906712SIngo Weinhold
31752906712SIngo Weinhold			// next sample not yet reached -- just add the time
31852906712SIngo Weinhold			times[timeType] += double(eventTime - previousEventTime);
31952906712SIngo Weinhold			previousEventTime = eventTime;
32052906712SIngo Weinhold		}
32152906712SIngo Weinhold	}
32252906712SIngo Weinhold
32352906712SIngo Weinholdprivate:
32452906712SIngo Weinhold	ThreadModel*	fModel;
32552906712SIngo Weinhold	int32			fTimeType;
32652906712SIngo Weinhold};
32752906712SIngo Weinhold
32852906712SIngo Weinhold
32952906712SIngo WeinholdThreadWindow::ActivityPage::ActivityPage()
33052906712SIngo Weinhold	:
33152906712SIngo Weinhold	BGroupView(B_VERTICAL),
33252906712SIngo Weinhold	fThreadModel(NULL),
33352906712SIngo Weinhold	fActivityChart(NULL),
33452906712SIngo Weinhold	fActivityChartRenderer(NULL),
33552906712SIngo Weinhold	fRunTimeData(NULL),
33652906712SIngo Weinhold	fWaitTimeData(NULL),
337639e61adSIngo Weinhold	fPreemptionTimeData(NULL),
338639e61adSIngo Weinhold	fLatencyTimeData(NULL)
33952906712SIngo Weinhold{
34052906712SIngo Weinhold	SetName("Activity");
34152906712SIngo Weinhold
34252906712SIngo Weinhold	GroupLayout()->SetInsets(10, 10, 10, 10);
34352906712SIngo Weinhold
34452906712SIngo Weinhold	fActivityChartRenderer = new LineChartRenderer;
34552906712SIngo Weinhold	ObjectDeleter<ChartRenderer> rendererDeleter(fActivityChartRenderer);
34652906712SIngo Weinhold
34752906712SIngo Weinhold	fActivityChart = new Chart(fActivityChartRenderer);
348f2bc8d23SIngo Weinhold	fActivityChart->SetDomainZoomLimit(1000);
349f2bc8d23SIngo Weinhold		// maximal zoom: 1 ms for the whole displayed domain
35052906712SIngo Weinhold
35152906712SIngo Weinhold	BGroupLayoutBuilder(this)
352972c78f8SIngo Weinhold		.Add(new BScrollView("activity scroll", fActivityChart, 0, true, false))
35352906712SIngo Weinhold		.AddStrut(20)
354639e61adSIngo Weinhold		.Add(BGridLayoutBuilder()
355579be822SIngo Weinhold			.Add(fRunTimeCheckBox = new ColorCheckBox("Run time", kRunTimeColor,
356639e61adSIngo Weinhold					new BMessage(MSG_CHECK_BOX_RUN_TIME)),
357639e61adSIngo Weinhold				0, 0)
358579be822SIngo Weinhold			.Add(fWaitTimeCheckBox = new ColorCheckBox("Wait time",
359639e61adSIngo Weinhold					kWaitTimeColor, new BMessage(MSG_CHECK_BOX_WAIT_TIME)),
360639e61adSIngo Weinhold				1, 0)
361579be822SIngo Weinhold			.Add(fPreemptionTimeCheckBox = new ColorCheckBox("Preemption time",
362639e61adSIngo Weinhold					kPreemptionTimeColor,
363639e61adSIngo Weinhold					new BMessage(MSG_CHECK_BOX_PREEMPTION_TIME)),
364639e61adSIngo Weinhold				0, 1)
365579be822SIngo Weinhold			.Add(fLatencyTimeCheckBox = new ColorCheckBox("Latency time",
366639e61adSIngo Weinhold					kLatencyTimeColor,
367639e61adSIngo Weinhold					new BMessage(MSG_CHECK_BOX_LATENCY_TIME)),
368639e61adSIngo Weinhold				1, 1)
369639e61adSIngo Weinhold		)
37052906712SIngo Weinhold	;
37152906712SIngo Weinhold
37252906712SIngo Weinhold	rendererDeleter.Detach();
37352906712SIngo Weinhold
374639e61adSIngo Weinhold	// enable the run time chart data
375639e61adSIngo Weinhold	fRunTimeCheckBox->CheckBox()->SetValue(B_CONTROL_ON);
376639e61adSIngo Weinhold
37752906712SIngo Weinhold// TODO: Allocation management...
37852906712SIngo Weinhold	LegendChartAxis* axis = new LegendChartAxis(
379d8d4b902SIngo Weinhold		new NanotimeChartAxisLegendSource, new StringChartLegendRenderer);
38052906712SIngo Weinhold	fActivityChart->SetAxis(CHART_AXIS_BOTTOM, axis);
38145febed6SIngo Weinhold
38245febed6SIngo Weinhold	axis = new LegendChartAxis(
383d8d4b902SIngo Weinhold		new NanotimeChartAxisLegendSource, new StringChartLegendRenderer);
38445febed6SIngo Weinhold	fActivityChart->SetAxis(CHART_AXIS_TOP, axis);
38545febed6SIngo Weinhold
38645febed6SIngo Weinhold	axis = new LegendChartAxis(
387972c78f8SIngo Weinhold		new DefaultChartAxisLegendSource, new StringChartLegendRenderer);
38845febed6SIngo Weinhold	fActivityChart->SetAxis(CHART_AXIS_LEFT, axis);
38945febed6SIngo Weinhold
39045febed6SIngo Weinhold	axis = new LegendChartAxis(
391972c78f8SIngo Weinhold		new DefaultChartAxisLegendSource, new StringChartLegendRenderer);
39245febed6SIngo Weinhold	fActivityChart->SetAxis(CHART_AXIS_RIGHT, axis);
39352906712SIngo Weinhold}
39452906712SIngo Weinhold
39552906712SIngo Weinhold
39652906712SIngo WeinholdThreadWindow::ActivityPage::~ActivityPage()
39752906712SIngo Weinhold{
39852906712SIngo Weinhold	delete fRunTimeData;
39952906712SIngo Weinhold	delete fWaitTimeData;
40052906712SIngo Weinhold	delete fLatencyTimeData;
40152906712SIngo Weinhold	delete fPreemptionTimeData;
40252906712SIngo Weinhold	delete fActivityChartRenderer;
40352906712SIngo Weinhold}
40452906712SIngo Weinhold
40552906712SIngo Weinhold
40652906712SIngo Weinholdvoid
40752906712SIngo WeinholdThreadWindow::ActivityPage::SetModel(ThreadModel* model)
40852906712SIngo Weinhold{
40952906712SIngo Weinhold	if (model == fThreadModel)
41052906712SIngo Weinhold		return;
41152906712SIngo Weinhold
41252906712SIngo Weinhold	if (fThreadModel != NULL) {
41352906712SIngo Weinhold		fActivityChart->RemoveAllDataSources();
41452906712SIngo Weinhold		delete fRunTimeData;
41552906712SIngo Weinhold		delete fWaitTimeData;
41652906712SIngo Weinhold		delete fLatencyTimeData;
41752906712SIngo Weinhold		delete fPreemptionTimeData;
41852906712SIngo Weinhold		fRunTimeData = NULL;
41952906712SIngo Weinhold		fWaitTimeData = NULL;
42052906712SIngo Weinhold		fLatencyTimeData = NULL;
42152906712SIngo Weinhold		fPreemptionTimeData = NULL;
42252906712SIngo Weinhold	}
42352906712SIngo Weinhold
42452906712SIngo Weinhold	fThreadModel = model;
42552906712SIngo Weinhold
42652906712SIngo Weinhold	if (fThreadModel != NULL) {
427639e61adSIngo Weinhold		_UpdateChartDataEnabled(RUN_TIME);
428639e61adSIngo Weinhold		_UpdateChartDataEnabled(WAIT_TIME);
429639e61adSIngo Weinhold		_UpdateChartDataEnabled(PREEMPTION_TIME);
430639e61adSIngo Weinhold		_UpdateChartDataEnabled(LATENCY_TIME);
431639e61adSIngo Weinhold	}
432639e61adSIngo Weinhold}
43352906712SIngo Weinhold
43452906712SIngo Weinhold
435639e61adSIngo Weinholdvoid
436639e61adSIngo WeinholdThreadWindow::ActivityPage::MessageReceived(BMessage* message)
437639e61adSIngo Weinhold{
438639e61adSIngo Weinhold	switch (message->what) {
439639e61adSIngo Weinhold		case MSG_CHECK_BOX_RUN_TIME:
440639e61adSIngo Weinhold			_UpdateChartDataEnabled(RUN_TIME);
441639e61adSIngo Weinhold			break;
442639e61adSIngo Weinhold		case MSG_CHECK_BOX_WAIT_TIME:
443639e61adSIngo Weinhold			_UpdateChartDataEnabled(WAIT_TIME);
444639e61adSIngo Weinhold			break;
445639e61adSIngo Weinhold		case MSG_CHECK_BOX_PREEMPTION_TIME:
446639e61adSIngo Weinhold			_UpdateChartDataEnabled(PREEMPTION_TIME);
447639e61adSIngo Weinhold			break;
448639e61adSIngo Weinhold		case MSG_CHECK_BOX_LATENCY_TIME:
449639e61adSIngo Weinhold			_UpdateChartDataEnabled(LATENCY_TIME);
450639e61adSIngo Weinhold			break;
451639e61adSIngo Weinhold		default:
452639e61adSIngo Weinhold			BGroupView::MessageReceived(message);
453639e61adSIngo Weinhold			break;
454639e61adSIngo Weinhold	}
455639e61adSIngo Weinhold}
45652906712SIngo Weinhold
45752906712SIngo Weinhold
458639e61adSIngo Weinholdvoid
459639e61adSIngo WeinholdThreadWindow::ActivityPage::AttachedToWindow()
460639e61adSIngo Weinhold{
461639e61adSIngo Weinhold	fRunTimeCheckBox->SetTarget(this);
462639e61adSIngo Weinhold	fWaitTimeCheckBox->SetTarget(this);
463639e61adSIngo Weinhold	fPreemptionTimeCheckBox->SetTarget(this);
464639e61adSIngo Weinhold	fLatencyTimeCheckBox->SetTarget(this);
465639e61adSIngo Weinhold}
46652906712SIngo Weinhold
46752906712SIngo Weinhold
468639e61adSIngo Weinholdvoid
469639e61adSIngo WeinholdThreadWindow::ActivityPage::_UpdateChartDataEnabled(int timeType)
470639e61adSIngo Weinhold{
471639e61adSIngo Weinhold	ThreadActivityData** data;
472639e61adSIngo Weinhold	ColorCheckBox* checkBox;
473639e61adSIngo Weinhold	rgb_color color;
474639e61adSIngo Weinhold
475639e61adSIngo Weinhold	switch (timeType) {
476639e61adSIngo Weinhold		case RUN_TIME:
477639e61adSIngo Weinhold			data = &fRunTimeData;
478639e61adSIngo Weinhold			checkBox = fRunTimeCheckBox;
479639e61adSIngo Weinhold			color = kRunTimeColor;
480639e61adSIngo Weinhold			break;
481639e61adSIngo Weinhold		case WAIT_TIME:
482639e61adSIngo Weinhold			data = &fWaitTimeData;
483639e61adSIngo Weinhold			checkBox = fWaitTimeCheckBox;
484639e61adSIngo Weinhold			color = kWaitTimeColor;
485639e61adSIngo Weinhold			break;
486639e61adSIngo Weinhold		case PREEMPTION_TIME:
487639e61adSIngo Weinhold			data = &fPreemptionTimeData;
488639e61adSIngo Weinhold			checkBox = fPreemptionTimeCheckBox;
489639e61adSIngo Weinhold			color = kPreemptionTimeColor;
490639e61adSIngo Weinhold			break;
491639e61adSIngo Weinhold		case LATENCY_TIME:
492639e61adSIngo Weinhold			data = &fLatencyTimeData;
493639e61adSIngo Weinhold			checkBox = fLatencyTimeCheckBox;
494639e61adSIngo Weinhold			color = kLatencyTimeColor;
495639e61adSIngo Weinhold			break;
496639e61adSIngo Weinhold		default:
497639e61adSIngo Weinhold			return;
498639e61adSIngo Weinhold	}
499639e61adSIngo Weinhold
500639e61adSIngo Weinhold	bool enabled = checkBox->CheckBox()->Value() == B_CONTROL_ON;
501639e61adSIngo Weinhold
502639e61adSIngo Weinhold	if ((*data != NULL) == enabled)
503639e61adSIngo Weinhold		return;
504639e61adSIngo Weinhold
505639e61adSIngo Weinhold	if (enabled) {
506639e61adSIngo Weinhold		LineChartRendererDataSourceConfig config(color);
507639e61adSIngo Weinhold
508639e61adSIngo Weinhold		*data = new(std::nothrow) ThreadActivityData(fThreadModel, timeType);
509639e61adSIngo Weinhold		if (*data == NULL)
510639e61adSIngo Weinhold			return;
51152906712SIngo Weinhold
512639e61adSIngo Weinhold		fActivityChart->AddDataSource(*data, &config);
513639e61adSIngo Weinhold	} else {
514639e61adSIngo Weinhold		fActivityChart->RemoveDataSource(*data);
515639e61adSIngo Weinhold		delete *data;
516639e61adSIngo Weinhold		*data = NULL;
51752906712SIngo Weinhold	}
51852906712SIngo Weinhold}