xref: /haiku/src/apps/processcontroller/ThreadBarMenu.cpp (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
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 
18 ThreadBarMenu::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 
31 ThreadBarMenu::~ThreadBarMenu()
32 {
33 	free(fThreadsRec);
34 	if (gCurrentThreadBarMenu == this)
35 		gCurrentThreadBarMenu = NULL;
36 }
37 
38 
39 void
40 ThreadBarMenu::Init()
41 {
42 	int k = 0;
43 	while (k < fThreadsRecCount)
44 		fThreadsRec[k++].thread = -1;
45 	fRound = 1;
46 }
47 
48 
49 void
50 ThreadBarMenu::Reset(team_id team)
51 {
52 	fTeam = team;
53 	RemoveItems(0, CountItems(), true);
54 	Init();
55 }
56 
57 
58 void
59 ThreadBarMenu::AttachedToWindow()
60 {
61 	BMenu::AttachedToWindow();
62 }
63 
64 
65 void
66 ThreadBarMenu::Draw(BRect r)
67 {
68 	gCurrentThreadBarMenu = this;
69 	BMenu::Draw(r);
70 }
71 
72 
73 void
74 ThreadBarMenu::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 
119 void
120 ThreadBarMenu::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