* The beginnings of an activity monitor application. Very bare and feature-less

right now, but it's already working (and shows that we better compute our
  system_info::cached_pages field directly).
* I am not sure if we want to keep this app here, merge it with
  ProcessController, or have it as a separate (3rdparty) app. Opinions welcome.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24846 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-04-06 21:30:50 +00:00
parent 6a7b827501
commit 18d3e65ebd
14 changed files with 1658 additions and 0 deletions
+1
View File
@@ -2,6 +2,7 @@ SubDir HAIKU_TOP src apps ;
SubInclude HAIKU_TOP src apps 3dmov ;
SubInclude HAIKU_TOP src apps aboutsystem ;
SubInclude HAIKU_TOP src apps activitymonitor ;
SubInclude HAIKU_TOP src apps bsnow ;
SubInclude HAIKU_TOP src apps bootman ;
SubInclude HAIKU_TOP src apps cdplayer ;
@@ -0,0 +1,91 @@
/*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "ActivityMonitor.h"
#include <stdlib.h>
#include <Alert.h>
#include <Application.h>
#include <TextView.h>
#include "ActivityWindow.h"
const char* kSignature = "application/x-vnd.Haiku-ActivityMonitor";
ActivityMonitor::ActivityMonitor()
: BApplication(kSignature)
{
}
ActivityMonitor::~ActivityMonitor()
{
}
void
ActivityMonitor::ReadyToRun()
{
fWindow = new ActivityWindow();
fWindow->Show();
}
void
ActivityMonitor::RefsReceived(BMessage* message)
{
fWindow->PostMessage(message);
}
void
ActivityMonitor::MessageReceived(BMessage* message)
{
BApplication::MessageReceived(message);
}
void
ActivityMonitor::AboutRequested()
{
ShowAbout();
}
/*static*/ void
ActivityMonitor::ShowAbout()
{
BAlert *alert = new BAlert("about", "ActivityMonitor\n"
"\twritten by Axel Dörfler\n"
"\tCopyright 2008, Haiku Inc.\n", "Ok");
BTextView *view = alert->TextView();
BFont font;
view->SetStylable(true);
view->GetFont(&font);
font.SetSize(18);
font.SetFace(B_BOLD_FACE);
view->SetFontAndColor(0, 15, &font);
alert->Go();
}
// #pragma mark -
int
main(int /*argc*/, char** /*argv*/)
{
ActivityMonitor app;
app.Run();
return 0;
}
@@ -0,0 +1,35 @@
/*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef ACTIVITY_MONITOR_H
#define ACTIVITY_MONITOR_H
#include <Application.h>
class BMessage;
class ActivityWindow;
class ActivityMonitor : public BApplication {
public:
ActivityMonitor();
virtual ~ActivityMonitor();
virtual void ReadyToRun();
virtual void RefsReceived(BMessage* message);
virtual void MessageReceived(BMessage* message);
virtual void AboutRequested();
static void ShowAbout();
private:
ActivityWindow* fWindow;
};
extern const char* kSignature;
#endif // ACTIVITY_MONITOR_H
@@ -0,0 +1,46 @@
resource(1, "BEOS:APP_SIG") #'MIMS' "application/x-vnd.Haiku-ActivityMonitor";
resource app_version {
major = 1,
middle = 0,
minor = 0,
variety = B_APPV_BETA,
internal = 3,
short_info = "ActivityMonitor",
long_info = "ActivityMonitor ©2008 Haiku, Inc."
};
resource app_flags B_MULTIPLE_LAUNCH;
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
resource vector_icon {
$"6E6369660E03010000020002023980000000000000004000004BE00008908100"
$"010000FFFF01000000020016023CC7EE389BC0BA16573E39B04977C842ADC700"
$"FFFFD3020006023C529D3753A2B8966F3D9D084B6044496AAF00474747FFA5A0"
$"A002001602BC4E76BC411B3C90DABCA00D47587D4ABA850090FFD40200160238"
$"313C3B5CF0BFCD963C7AAC4C13943FCAF901ECFFC3054B04017E020006033E2F"
$"99387F17BA42DB3FF5B94A0E32482C90001D1E2C3D454658FF01010102000602"
$"3879063B8224BE2CC83B10DB4A1F6F49B894FF9A9A9A00242222020006033C69"
$"A60000000000003E186148800049800058F3F3F300D4CECEFFD9D9D902000603"
$"3C1F1A33E78CB7ACC03FFE4F48BB3EBD7B6C0078D905818CFF05FF7ADD050200"
$"1602349C2E37B5FABA1F6036FC624A3E004B320001D3FF910200160235777837"
$"0A67B7E8CE363A844A1D684B45D800F3FF2E0D0A04486050605C51544E04033E"
$"5349594856475C49604B5C4E604B0A06262A264C485E5252523030240A04262A"
$"4838523030240A044838485E525252300A04262A264C485E48380A04453A4553"
$"2844282E0A04B6F9C0F42845282EB701B8EC0A044550455328452AC0F30A0445"
$"3A45502A43B701B8EC0408AEBAB6BCBCC32FBD4F2E3930BDA8B9ACC0A5BA9EBC"
$"03BB1EBFD937BF0DBD4FC072BCC3C019BDDBC0CB46460204BF23C726BF91C70D"
$"BEB5C73FBE9FC87EBE7AC7D9BEC5C922BFAAC97BBF3CC994C018C962C02DC823"
$"C053C8C8C008C77F0204BFCEC6FBC042C6E0BF5BC715BF48C85ABF1FC7B3BF71"
$"C902C063C95ABFF0C974C0D7C93FC0EAC7FAC113C8A2C0C1C7530E0A07010000"
$"0A0101011001178300040A0001021001178400040A020103000A080109000A0B"
$"010A1001178120040A030104000A04020506000A090107000A0A0108000A0D01"
$"0C0815FF0A0C010B0815FF0A0D010C0A3FEAF70000000000003FEAF7C573B4C2"
$"770615FF0A0C010B0A3FEAF70000000000003FEAF7C573B4C2770615FF"
};
#endif // HAIKU_TARGET_PLATFORM_HAIKU
+500
View File
@@ -0,0 +1,500 @@
/*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "ActivityView.h"
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <Application.h>
#include <Bitmap.h>
#include <Dragger.h>
#include <MenuItem.h>
#include <MessageRunner.h>
#include <PopUpMenu.h>
#include <String.h>
#include "ActivityMonitor.h"
#include "DataSource.h"
#include "SystemInfo.h"
struct data_item {
bigtime_t time;
int64 value;
};
const bigtime_t kInitialRefreshInterval = 500000LL;
const uint32 kMsgRefresh = 'refr';
const uint32 kMsgToggleDataSource = 'tgds';
extern const char* kSignature;
DataHistory::DataHistory(bigtime_t memorize, bigtime_t interval)
:
fBuffer(10000),
fMinimumValue(0),
fMaximumValue(0),
fRefreshInterval(interval),
fLastIndex(-1)
{
}
DataHistory::~DataHistory()
{
}
void
DataHistory::AddValue(bigtime_t time, int64 value)
{
if (fBuffer.IsEmpty() || fMaximumValue < value)
fMaximumValue = value;
if (fBuffer.IsEmpty() || fMinimumValue > value)
fMinimumValue = value;
data_item item = {time, value};
fBuffer.AddItem(item);
}
int64
DataHistory::ValueAt(bigtime_t time)
{
// TODO: if the refresh rate changes, this computation won't work anymore!
int32 index = (time - Start()) / fRefreshInterval;
data_item* item = fBuffer.ItemAt(index);
if (item != NULL)
return item->value;
return 0;
}
int64
DataHistory::MaximumValue() const
{
return fMaximumValue;
}
int64
DataHistory::MinimumValue() const
{
return fMinimumValue;
}
bigtime_t
DataHistory::Start() const
{
if (fBuffer.CountItems() == 0)
return 0;
return fBuffer.ItemAt(0)->time;
}
bigtime_t
DataHistory::End() const
{
if (fBuffer.CountItems() == 0)
return 0;
return fBuffer.ItemAt(fBuffer.CountItems() - 1)->time;
}
void
DataHistory::SetRefreshInterval(bigtime_t interval)
{
// TODO: adjust buffer size
}
// #pragma mark -
ActivityView::ActivityView(BRect frame, const char* name,
const BMessage& settings, uint32 resizingMode)
: BView(frame, name, resizingMode,
B_WILL_DRAW | B_SUBPIXEL_PRECISE | B_FULL_UPDATE_ON_RESIZE
| B_FRAME_EVENTS)
{
_Init(&settings);
BRect rect(Bounds());
rect.top = rect.bottom - 7;
rect.left = rect.right - 7;
BDragger* dragger = new BDragger(rect, this,
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
AddChild(dragger);
}
ActivityView::ActivityView(BMessage* archive)
: BView(archive)
{
_Init(archive);
}
ActivityView::~ActivityView()
{
}
void
ActivityView::_Init(const BMessage* settings)
{
fBackgroundColor = (rgb_color){255, 255, 240};
SetLowColor(fBackgroundColor);
fRefreshInterval = kInitialRefreshInterval;
fDrawInterval = kInitialRefreshInterval * 2;
fLastRefresh = 0;
fDrawResolution = 1;
AddDataSource(new UsedMemoryDataSource());
AddDataSource(new CachedMemoryDataSource());
AddDataSource(new ThreadsDataSource());
AddDataSource(new CpuUsageDataSource());
}
status_t
ActivityView::Archive(BMessage* into, bool deep) const
{
status_t status;
status = BView::Archive(into, deep);
if (status < B_OK)
return status;
status = into->AddString("add_on", kSignature);
if (status < B_OK)
return status;
status = SaveState(*into);
if (status < B_OK)
return status;
return B_OK;
}
BArchivable*
ActivityView::Instantiate(BMessage* archive)
{
if (!validate_instantiation(archive, "ActivityView"))
return NULL;
return new ActivityView(archive);
}
status_t
ActivityView::SaveState(BMessage& state) const
{
return B_ERROR;
}
DataSource*
ActivityView::FindDataSource(const char* name)
{
for (int32 i = fSources.CountItems(); i-- > 0;) {
DataSource* source = fSources.ItemAt(i);
if (!strcmp(source->Label(), name))
return source;
}
return NULL;
}
status_t
ActivityView::AddDataSource(DataSource* source)
{
DataHistory* values = new(std::nothrow) DataHistory(10 * 60000000LL,
fRefreshInterval);
if (values == NULL)
return B_NO_MEMORY;
if (!fValues.AddItem(values)) {
delete values;
return B_NO_MEMORY;
}
if (!fSources.AddItem(source)) {
fValues.RemoveItem(values);
delete values;
return B_NO_MEMORY;
}
return B_OK;
}
status_t
ActivityView::RemoveDataSource(DataSource* source)
{
int32 index = fSources.IndexOf(source);
if (index < 0)
return B_ENTRY_NOT_FOUND;
fSources.RemoveItemAt(index);
delete source;
DataHistory* values = fValues.RemoveItemAt(index);
delete values;
return B_OK;
}
void
ActivityView::RemoveAllDataSources()
{
fSources.MakeEmpty();
fValues.MakeEmpty();
}
void
ActivityView::AttachedToWindow()
{
BMessage refresh(kMsgRefresh);
fRunner = new BMessageRunner(this, &refresh, fRefreshInterval);
}
void
ActivityView::DetachedFromWindow()
{
delete fRunner;
}
void
ActivityView::FrameResized(float /*width*/, float /*height*/)
{
}
void
ActivityView::MouseDown(BPoint where)
{
#if 0
int32 buttons = B_PRIMARY_MOUSE_BUTTON;
int32 clicks = 1;
if (Looper() != NULL && Looper()->CurrentMessage() != NULL) {
Looper()->CurrentMessage()->FindInt32("buttons", &buttons);
Looper()->CurrentMessage()->FindInt32("clicks", &clicks);
}
#endif
BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
menu->SetFont(be_plain_font);
BMenuItem* item;
for (int32 i = 0; i < DataSource::CountSources(); i++) {
const DataSource* source = DataSource::SourceAt(i);
BMessage* message = new BMessage(kMsgToggleDataSource);
message->AddInt32("index", i);
item = new BMenuItem(source->Label(), message);
if (FindDataSource(source->Label()))
item->SetMarked(true);
menu->AddItem(item);
}
menu->SetTargetForItems(this);
ConvertToScreen(&where);
menu->Go(where, true, false, true);
}
void
ActivityView::MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{
}
void
ActivityView::MessageReceived(BMessage* message)
{
switch (message->what) {
case B_ABOUT_REQUESTED:
ActivityMonitor::ShowAbout();
break;
case kMsgRefresh:
_Refresh();
break;
case kMsgToggleDataSource:
{
int32 index;
if (message->FindInt32("index", &index) != B_OK)
break;
const DataSource* baseSource = DataSource::SourceAt(index);
if (baseSource == NULL)
break;
DataSource* source = FindDataSource(baseSource->Label());
if (source == NULL)
AddDataSource(baseSource->Copy());
else
RemoveDataSource(source);
Invalidate();
break;
}
case B_MOUSE_WHEEL_CHANGED:
{
float deltaY = 0.0f;
if (message->FindFloat("be:wheel_delta_y", &deltaY) != B_OK
|| deltaY == 0.0f)
break;
if (deltaY > 0)
fDrawResolution *= 2;
else
fDrawResolution /= 2;
if (fDrawResolution < 1)
fDrawResolution = 1;
if (fDrawResolution > 128)
fDrawResolution = 128;
Invalidate();
break;
}
default:
BView::MessageReceived(message);
break;
}
}
float
ActivityView::_PositionForValue(DataSource* source, DataHistory* values,
int64 value)
{
int64 min = source->Minimum();
int64 max = source->Maximum();
if (source->AdaptiveScale()) {
int64 adaptiveMax = int64(values->MaximumValue() * 1.2);
if (adaptiveMax < max)
max = adaptiveMax;
}
if (value > max)
value = max;
if (value < min)
value = min;
float height = Bounds().Height();
return height - (value - min) * height / (max - min);
}
void
ActivityView::Draw(BRect /*updateRect*/)
{
uint32 step = 2;
uint32 resolution = fDrawResolution;
if (fDrawResolution > 1) {
step = 1;
resolution--;
}
uint32 width = Bounds().IntegerWidth() - 10;
uint32 steps = width / step;
bigtime_t timeStep = fRefreshInterval * resolution;
bigtime_t now = system_time();
SetPenSize(2);
for (uint32 i = fSources.CountItems(); i-- > 0;) {
DataSource* source = fSources.ItemAt(i);
DataHistory* values = fValues.ItemAt(i);
bigtime_t time = now - steps * timeStep;
// for now steps pixels per second
BeginLineArray(steps);
SetHighColor(source->Color());
float lastY = FLT_MIN;
uint32 lastX = 0;
for (uint32 x = 0; x < width; x += step, time += timeStep) {
// TODO: compute starting point instead!
if (values->Start() > time || values->End() < time)
continue;
int64 value = values->ValueAt(time);
if (timeStep > fRefreshInterval) {
// TODO: always start with the same index, so that it always
// uses the same values for computation (currently it jumps)
uint32 count = 1;
for (bigtime_t offset = fRefreshInterval; offset < timeStep;
offset += fRefreshInterval) {
// TODO: handle int64 overflow correctly!
value += values->ValueAt(time + offset);
count++;
}
value /= count;
}
float y = _PositionForValue(source, values, value);
if (lastY != FLT_MIN)
AddLine(BPoint(lastX, lastY), BPoint(x, y), source->Color());
lastX = x;
lastY = y;
}
EndLineArray();
}
// TODO: add marks when an app started or quit
}
void
ActivityView::_Refresh()
{
SystemInfo info;
// TODO: run refresh in another thread to decouple it from the UI!
for (uint32 i = fSources.CountItems(); i-- > 0;) {
DataSource* source = fSources.ItemAt(i);
DataHistory* values = fValues.ItemAt(i);
int64 value = source->NextValue(info);
values->AddValue(info.Time(), value);
}
bigtime_t now = info.Time();
if (fLastRefresh + fDrawInterval <= now) {
Invalidate();
fLastRefresh = now;
}
}
+89
View File
@@ -0,0 +1,89 @@
/*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef ACTIVITY_VIEW_H
#define ACTIVITY_VIEW_H
#include <View.h>
#include <ObjectList.h>
#include "CircularBuffer.h"
class BMessageRunner;
class DataSource;
struct data_item;
class DataHistory {
public:
DataHistory(bigtime_t memorize, bigtime_t interval);
~DataHistory();
void AddValue(bigtime_t time, int64 value);
int64 ValueAt(bigtime_t time);
int64 MaximumValue() const;
int64 MinimumValue() const;
bigtime_t Start() const;
bigtime_t End() const;
void SetRefreshInterval(bigtime_t interval);
private:
CircularBuffer<data_item> fBuffer;
int64 fMinimumValue;
int64 fMaximumValue;
bigtime_t fRefreshInterval;
int32 fLastIndex;
};
class ActivityView : public BView {
public:
ActivityView(BRect frame, const char* name,
const BMessage& settings, uint32 resizingMode);
ActivityView(BMessage* archive);
virtual ~ActivityView();
virtual status_t Archive(BMessage* into, bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive);
status_t SaveState(BMessage& state) const;
DataSource* FindDataSource(const char* name);
status_t AddDataSource(DataSource* source);
status_t RemoveDataSource(DataSource* source);
void RemoveAllDataSources();
protected:
virtual void AttachedToWindow();
virtual void DetachedFromWindow();
virtual void FrameResized(float width, float height);
virtual void MouseDown(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
virtual void MessageReceived(BMessage* message);
virtual void Draw(BRect updateRect);
private:
void _Init(const BMessage* settings);
void _Refresh();
float _PositionForValue(DataSource* source,
DataHistory* values, int64 value);
rgb_color fBackgroundColor;
BObjectList<DataSource> fSources;
BObjectList<DataHistory> fValues;
BMessageRunner* fRunner;
bigtime_t fRefreshInterval;
bigtime_t fLastRefresh;
bigtime_t fDrawInterval;
int32 fDrawResolution;
};
#endif // ACTIVITY_VIEW_H
+156
View File
@@ -0,0 +1,156 @@
/*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "ActivityWindow.h"
#include <stdio.h>
#include <Application.h>
#include <File.h>
#include <FindDirectory.h>
#include <Menu.h>
#include <MenuBar.h>
#include <MenuItem.h>
#include <Path.h>
#include <Roster.h>
#include "ActivityMonitor.h"
#include "ActivityView.h"
ActivityWindow::ActivityWindow()
: BWindow(BRect(100, 100, 500, 250), "ActivityMonitor", B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE)
{
BMessage settings;
_LoadSettings(settings);
BRect frame;
if (settings.FindRect("window frame", &frame) == B_OK) {
MoveTo(frame.LeftTop());
ResizeTo(frame.Width(), frame.Height());
frame.OffsetTo(B_ORIGIN);
} else
frame = Bounds();
// create GUI
BMenuBar* menuBar = new BMenuBar(Bounds(), "menu");
AddChild(menuBar);
frame.top = menuBar->Frame().bottom;
BView* top = new BView(frame, NULL, B_FOLLOW_ALL, B_WILL_DRAW);
top->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
AddChild(top);
fActivityView = new ActivityView(top->Bounds().InsetByCopy(10, 10),
"ActivityMonitor", settings, B_FOLLOW_ALL);
top->AddChild(fActivityView);
// add menu
// "File" menu
BMenu* menu = new BMenu("File");
BMenuItem* item;
menu->AddItem(item = new BMenuItem("About ActivityMonitor" B_UTF8_ELLIPSIS,
new BMessage(B_ABOUT_REQUESTED)));
menu->AddSeparatorItem();
menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'));
menu->SetTargetForItems(this);
item->SetTarget(be_app);
menuBar->AddItem(menu);
}
ActivityWindow::~ActivityWindow()
{
}
status_t
ActivityWindow::_OpenSettings(BFile& file, uint32 mode)
{
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return B_ERROR;
path.Append("ActivityMonitor settings");
return file.SetTo(path.Path(), mode);
}
status_t
ActivityWindow::_LoadSettings(BMessage& settings)
{
BFile file;
status_t status = _OpenSettings(file, B_READ_ONLY);
if (status < B_OK)
return status;
return settings.Unflatten(&file);
}
status_t
ActivityWindow::_SaveSettings()
{
BFile file;
status_t status = _OpenSettings(file, B_WRITE_ONLY | B_CREATE_FILE
| B_ERASE_FILE);
if (status < B_OK)
return status;
BMessage settings('actm');
status = settings.AddRect("window frame", Frame());
if (status == B_OK)
status = settings.Flatten(&file);
return status;
}
void
ActivityWindow::_MessageDropped(BMessage* message)
{
entry_ref ref;
if (message->FindRef("refs", &ref) != B_OK) {
// TODO: If app, then launch it, and add ActivityView for this one?
}
}
void
ActivityWindow::MessageReceived(BMessage* message)
{
if (message->WasDropped()) {
_MessageDropped(message);
return;
}
switch (message->what) {
case B_REFS_RECEIVED:
case B_SIMPLE_DATA:
_MessageDropped(message);
break;
default:
BWindow::MessageReceived(message);
break;
}
}
bool
ActivityWindow::QuitRequested()
{
_SaveSettings();
be_app->PostMessage(B_QUIT_REQUESTED);
return true;
}
+33
View File
@@ -0,0 +1,33 @@
/*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef ACTIVITY_WINDOW_H
#define ACTIVITY_WINDOW_H
#include <Window.h>
class BFile;
class ActivityView;
class ActivityWindow : public BWindow {
public:
ActivityWindow();
virtual ~ActivityWindow();
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
private:
status_t _OpenSettings(BFile& file, uint32 mode);
status_t _LoadSettings(BMessage& settings);
status_t _SaveSettings();
void _MessageDropped(BMessage *message);
ActivityView* fActivityView;
};
#endif // ACTIVITY_WINDOW_H
+77
View File
@@ -0,0 +1,77 @@
/*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef CIRCULAR_BUFFER_H
#define CIRCULAR_BUFFER_H
#include <stdlib.h>
#include <OS.h>
template<typename Type>
class CircularBuffer {
public:
CircularBuffer(size_t size)
:
fSize(size)
{
fBuffer = (Type *)malloc(fSize * sizeof(Type));
MakeEmpty();
}
~CircularBuffer()
{
free(fBuffer);
}
status_t InitCheck() const
{
return fBuffer != NULL ? B_OK : B_NO_MEMORY;
}
void MakeEmpty()
{
fIn = 0;
fFirst = 0;
}
bool IsEmpty() const
{
return fIn == 0;
}
int32 CountItems() const
{
return fIn;
}
Type* ItemAt(int32 index) const
{
if (index >= (int32)fIn || index < 0)
return NULL;
return &fBuffer[(fFirst + index) % fSize];
}
void AddItem(const Type& item)
{
uint32 index;
if (fIn < fSize)
index = fFirst + fIn++;
else
index = fFirst++;
fBuffer[index % fSize] = item;
}
private:
uint32 fFirst;
uint32 fIn;
uint32 fSize;
Type* fBuffer;
};
#endif // CIRCULAR_BUFFER_H
+395
View File
@@ -0,0 +1,395 @@
/*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "DataSource.h"
#include <stdio.h>
#include <OS.h>
#include <String.h>
#include "SystemInfo.h"
const DataSource* kSources[] = {
new UsedMemoryDataSource(),
new CachedMemoryDataSource(),
new ThreadsDataSource(),
new CpuUsageDataSource(),
};
const size_t kSourcesCount = sizeof(kSources) / sizeof(kSources[0]);
DataSource::DataSource(int64 initialMin, int64 initialMax)
:
fMinimum(initialMin),
fMaximum(initialMax),
fInterval(1000000LL),
fColor((rgb_color){200, 0, 0})
{
}
DataSource::DataSource()
:
fMinimum(0),
fMaximum(100),
fInterval(1000000LL),
fColor((rgb_color){200, 0, 0})
{
}
DataSource::DataSource(const DataSource& other)
{
fMinimum = other.fMinimum;
fMaximum = other.fMaximum;
fInterval = other.fInterval;
fColor = other.fColor;
}
DataSource::~DataSource()
{
}
DataSource*
DataSource::Copy() const
{
return NULL;
// this class cannot be copied
}
int64
DataSource::Minimum() const
{
return fMinimum;
}
int64
DataSource::Maximum() const
{
return fMaximum;
}
bigtime_t
DataSource::RefreshInterval() const
{
return fInterval;
}
void
DataSource::SetLimits(int64 min, int64 max)
{
fMinimum = min;
fMaximum = max;
}
void
DataSource::SetRefreshInterval(bigtime_t interval)
{
fInterval = interval;
}
void
DataSource::SetColor(rgb_color color)
{
fColor = color;
}
int64
DataSource::NextValue(SystemInfo& info)
{
return 0;
}
void
DataSource::Print(BString& text, int64 value) const
{
text = "";
text << value;
}
const char*
DataSource::Label() const
{
return "";
}
const char*
DataSource::Unit() const
{
return "";
}
rgb_color
DataSource::Color() const
{
return fColor;
}
bool
DataSource::AdaptiveScale() const
{
return false;
}
/*static*/ int32
DataSource::CountSources()
{
return kSourcesCount;
}
/*static*/ const DataSource*
DataSource::SourceAt(int32 index)
{
if (index >= (int32)kSourcesCount || index < 0)
return NULL;
return kSources[index];
}
// #pragma mark -
MemoryDataSource::MemoryDataSource()
{
SystemInfo info;
fMinimum = 0;
fMaximum = info.MaxMemory();
}
MemoryDataSource::~MemoryDataSource()
{
}
void
MemoryDataSource::Print(BString& text, int64 value) const
{
char buffer[32];
snprintf(buffer, sizeof(buffer), "%.1g MB", value / 1048576.0);
text = buffer;
}
const char*
MemoryDataSource::Unit() const
{
return "MB";
}
// #pragma mark -
UsedMemoryDataSource::UsedMemoryDataSource()
{
}
UsedMemoryDataSource::~UsedMemoryDataSource()
{
}
DataSource*
UsedMemoryDataSource::Copy() const
{
return new UsedMemoryDataSource(*this);
}
int64
UsedMemoryDataSource::NextValue(SystemInfo& info)
{
return info.UsedMemory();
}
const char*
UsedMemoryDataSource::Label() const
{
return "Available Memory";
}
// #pragma mark -
CachedMemoryDataSource::CachedMemoryDataSource()
{
fColor = (rgb_color){0, 200, 0};
}
CachedMemoryDataSource::~CachedMemoryDataSource()
{
}
DataSource*
CachedMemoryDataSource::Copy() const
{
return new CachedMemoryDataSource(*this);
}
int64
CachedMemoryDataSource::NextValue(SystemInfo& info)
{
return info.CachedMemory();
}
const char*
CachedMemoryDataSource::Label() const
{
return "Cached Memory";
}
// #pragma mark -
ThreadsDataSource::ThreadsDataSource()
{
SystemInfo info;
fMinimum = 0;
fMaximum = info.MaxThreads();
fColor = (rgb_color){0, 0, 200};
}
ThreadsDataSource::~ThreadsDataSource()
{
}
DataSource*
ThreadsDataSource::Copy() const
{
return new ThreadsDataSource(*this);
}
int64
ThreadsDataSource::NextValue(SystemInfo& info)
{
return info.UsedThreads();
}
const char*
ThreadsDataSource::Label() const
{
return "Threads";
}
bool
ThreadsDataSource::AdaptiveScale() const
{
return true;
}
// #pragma mark -
CpuUsageDataSource::CpuUsageDataSource()
:
fPreviousActive(0),
fPreviousTime(0)
{
fMinimum = 0;
fMaximum = 1000;
fColor = (rgb_color){200, 200, 0};
}
CpuUsageDataSource::CpuUsageDataSource(const CpuUsageDataSource& other)
{
fPreviousActive = other.fPreviousActive;
fPreviousTime = other.fPreviousTime;
}
CpuUsageDataSource::~CpuUsageDataSource()
{
}
DataSource*
CpuUsageDataSource::Copy() const
{
return new CpuUsageDataSource(*this);
}
void
CpuUsageDataSource::Print(BString& text, int64 value) const
{
char buffer[32];
snprintf(buffer, sizeof(buffer), "%.1g%%", value / 10.0);
text = buffer;
}
int64
CpuUsageDataSource::NextValue(SystemInfo& info)
{
int32 running = 0;
bigtime_t active = 0;
for (int32 cpu = 0; cpu < info.Info().cpu_count; cpu++) {
active += info.Info().cpu_infos[cpu].active_time;
running++;
// TODO: take disabled CPUs into account
}
int64 percent = int64(1000.0 * (active - fPreviousActive)
/ (running * (info.Time() - fPreviousTime)));
if (percent < 0)
percent = 0;
if (percent > 1000)
percent = 1000;
fPreviousActive = active;
fPreviousTime = info.Time();
return percent;
}
const char*
CpuUsageDataSource::Label() const
{
return "CPU Usage";
}
+115
View File
@@ -0,0 +1,115 @@
/*
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef DATA_SOURCE_H
#define DATA_SOURCE_H
#include <InterfaceDefs.h>
class BString;
class SystemInfo;
class DataSource {
public:
DataSource(int64 initialMin, int64 initialMax);
DataSource();
DataSource(const DataSource& other);
virtual ~DataSource();
virtual DataSource* Copy() const;
int64 Minimum() const;
int64 Maximum() const;
bigtime_t RefreshInterval() const;
virtual void SetLimits(int64 min, int64 max);
virtual void SetRefreshInterval(bigtime_t interval);
virtual void SetColor(rgb_color color);
virtual int64 NextValue(SystemInfo& info);
virtual void Print(BString& text, int64 value) const;
virtual const char* Label() const;
virtual const char* Unit() const;
virtual rgb_color Color() const;
virtual bool AdaptiveScale() const;
static int32 CountSources();
static const DataSource* SourceAt(int32 index);
protected:
int64 fMinimum;
int64 fMaximum;
bigtime_t fInterval;
rgb_color fColor;
};
class MemoryDataSource : public DataSource {
public:
MemoryDataSource();
virtual ~MemoryDataSource();
virtual void Print(BString& text, int64 value) const;
virtual const char* Unit() const;
};
class UsedMemoryDataSource : public MemoryDataSource {
public:
UsedMemoryDataSource();
virtual ~UsedMemoryDataSource();
virtual DataSource* Copy() const;
virtual int64 NextValue(SystemInfo& info);
virtual const char* Label() const;
};
class CachedMemoryDataSource : public MemoryDataSource {
public:
CachedMemoryDataSource();
virtual ~CachedMemoryDataSource();
virtual DataSource* Copy() const;
virtual int64 NextValue(SystemInfo& info);
virtual const char* Label() const;
};
class ThreadsDataSource : public DataSource {
public:
ThreadsDataSource();
virtual ~ThreadsDataSource();
virtual DataSource* Copy() const;
virtual int64 NextValue(SystemInfo& info);
virtual const char* Label() const;
virtual bool AdaptiveScale() const;
};
class CpuUsageDataSource : public DataSource {
public:
CpuUsageDataSource();
CpuUsageDataSource(const CpuUsageDataSource& other);
virtual ~CpuUsageDataSource();
virtual DataSource* Copy() const;
virtual void Print(BString& text, int64 value) const;
virtual int64 NextValue(SystemInfo& info);
virtual const char* Label() const;
private:
bigtime_t fPreviousActive;
bigtime_t fPreviousTime;
};
#endif // DATA_SOURCE_H
+16
View File
@@ -0,0 +1,16 @@
SubDir HAIKU_TOP src apps activitymonitor ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders shared ;
Application ActivityMonitor :
ActivityMonitor.cpp
ActivityView.cpp
ActivityWindow.cpp
DataSource.cpp
SystemInfo.cpp
: be tracker $(TARGET_LIBSTDC++)
: ActivityMonitor.rdef
;
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "SystemInfo.h"
SystemInfo::SystemInfo()
:
fTime(system_time())
{
get_system_info(&fSystemInfo);
}
SystemInfo::~SystemInfo()
{
}
uint64
SystemInfo::CachedMemory() const
{
return fSystemInfo.cached_pages * B_PAGE_SIZE;
}
uint64
SystemInfo::UsedMemory() const
{
return fSystemInfo.used_pages * B_PAGE_SIZE;
}
uint64
SystemInfo::MaxMemory() const
{
return fSystemInfo.max_pages * B_PAGE_SIZE;
}
uint32
SystemInfo::UsedThreads() const
{
return fSystemInfo.used_threads;
}
uint32
SystemInfo::MaxThreads() const
{
return fSystemInfo.max_threads;
}
uint32
SystemInfo::UsedTeams() const
{
return fSystemInfo.used_teams;
}
uint32
SystemInfo::MaxTeams() const
{
return fSystemInfo.max_teams;
}
+35
View File
@@ -0,0 +1,35 @@
/*
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef SYSTEM_INFO_H
#define SYSTEM_INFO_H
#include <OS.h>
class SystemInfo {
public:
SystemInfo();
~SystemInfo();
uint64 CachedMemory() const;
uint64 UsedMemory() const;
uint64 MaxMemory() const;
uint32 UsedThreads() const;
uint32 MaxThreads() const;
uint32 UsedTeams() const;
uint32 MaxTeams() const;
bigtime_t Time() const { return fTime; }
const system_info& Info() const { return fSystemInfo; }
private:
system_info fSystemInfo;
bigtime_t fTime;
};
#endif // SYSTEM_INFO_H