1/*
2 * Copyright 2000, Georges-Edouard Berenger. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include "ThreadBarMenu.h"
7
8#include "PriorityMenu.h"
9#include "ProcessController.h"
10#include "ThreadBarMenuItem.h"
11
12#include <stdlib.h>
13#include <stdio.h>
14
15#define EXTRA 20
16
17
18ThreadBarMenu::ThreadBarMenu(const char *title, team_id team, int32 threadCount)
19	: BMenu(title),
20	fThreadsRecCount(threadCount + EXTRA),
21	fTeam(team)
22{
23	SetFont(be_plain_font);
24	fThreadsRec = (ThreadRec*) malloc(sizeof(ThreadRec) * fThreadsRecCount);
25	Init();
26	fRound = 0;	// for syslog
27	AddNew();
28}
29
30
31ThreadBarMenu::~ThreadBarMenu()
32{
33	free(fThreadsRec);
34	if (gCurrentThreadBarMenu == this)
35		gCurrentThreadBarMenu = NULL;
36}
37
38
39void
40ThreadBarMenu::Init()
41{
42	int k = 0;
43	while (k < fThreadsRecCount)
44		fThreadsRec[k++].thread = -1;
45	fRound = 1;
46}
47
48
49void
50ThreadBarMenu::Reset(team_id team)
51{
52	fTeam = team;
53	RemoveItems(0, CountItems(), true);
54	Init();
55}
56
57
58void
59ThreadBarMenu::AttachedToWindow()
60{
61	BMenu::AttachedToWindow();
62}
63
64
65void
66ThreadBarMenu::Draw(BRect r)
67{
68	gCurrentThreadBarMenu = this;
69	BMenu::Draw(r);
70}
71
72
73void
74ThreadBarMenu::AddNew()
75{
76	thread_info	info;
77	int32 cookie = 0;
78	int32 k = 0;
79	while (get_next_thread_info(fTeam, &cookie, &info) == B_OK) {
80		int	lastk = k;
81		while (k < fThreadsRecCount && fThreadsRec[k].thread != info.thread)
82			k++;
83		if (k == fThreadsRecCount) {
84			k = 0;
85			while (k < lastk && fThreadsRec[k].thread != info.thread)
86				k++;
87			if (k == lastk)
88				k = fThreadsRecCount; // flag that the search didn't work.
89		}
90		if (k == fThreadsRecCount) {
91//			printf("*** Thread %d %s/%s, user %lld, kernel %lld\n", info.thread, info.name, info.user_time, info.kernel_time);
92			// this is a new thread...
93			k = 0;
94			while (k < fThreadsRecCount && !(fThreadsRec[k].thread == -1 || fThreadsRec[k].last_round+1 < fRound))
95				k++;
96			if (k == fThreadsRecCount) {
97				fThreadsRecCount += EXTRA;
98				fThreadsRec = (ThreadRec*) realloc(fThreadsRec, sizeof(ThreadRec)*fThreadsRecCount);
99				lastk = k;
100				while (lastk < fThreadsRecCount)
101					fThreadsRec[lastk++].thread = -1;
102			}
103			fThreadsRec[k].thread = info.thread;
104			BMessage* kill_thread = new BMessage('KlTh');
105			kill_thread->AddInt32("thread", info.thread);
106
107			PriorityMenu* prio = new PriorityMenu(info.thread, info.priority);
108			prio->SetFont(be_plain_font);
109			ThreadBarMenuItem* threadbarmenuitem = new ThreadBarMenuItem(info.name, info.thread, prio, kill_thread);
110			threadbarmenuitem->SetTarget(gPCView);
111			AddItem(threadbarmenuitem);
112		}
113		fThreadsRec[k].last_round = fRound;
114	}
115	fRound++;
116}
117
118
119void
120ThreadBarMenu::Update()
121{
122	AddNew();
123	int32 k, del;
124	del = -1;
125	ThreadBarMenuItem *item;
126
127	for (k = 0; (item = (ThreadBarMenuItem*) ItemAt(k)) != NULL; k++) {
128		item->BarUpdate();
129		item->DrawBar(false);
130		if (item->fKernel < 0) {
131			if (del < 0)
132				del = k;
133		} else if (del >= 0) {
134			RemoveItems(del, k-del, true);
135			k = del;
136			del = -1;
137		}
138	}
139	if (del >= 0)
140		RemoveItems(del, k-del, true);
141}
142