* Offloaded the data source retrieval into another thread for more accuracy.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26434 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-07-15 17:10:52 +00:00
parent 46fa06b554
commit d421644512
2 changed files with 71 additions and 25 deletions
+65 -23
View File
@@ -14,6 +14,7 @@
# include <AbstractLayoutItem.h>
#endif
#include <Application.h>
#include <Autolock.h>
#include <Bitmap.h>
#include <Dragger.h>
#include <MenuItem.h>
@@ -93,7 +94,6 @@ private:
const bigtime_t kInitialRefreshInterval = 500000LL;
const uint32 kMsgRefresh = 'refr';
const uint32 kMsgToggleDataSource = 'tgds';
const uint32 kMsgToggleLegend = 'tglg';
@@ -392,7 +392,8 @@ ActivityView::LegendLayoutItem::BaseAlignment()
ActivityView::ActivityView(BRect frame, const char* name,
const BMessage* settings, uint32 resizingMode)
: BView(frame, name, resizingMode,
B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS)
B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS),
fSourcesLock("data sources")
{
_Init(settings);
@@ -407,10 +408,12 @@ ActivityView::ActivityView(BRect frame, const char* name,
ActivityView::ActivityView(const char* name, const BMessage* settings)
#ifdef __HAIKU__
: BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS)
: BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS),
#else
: BView(BRect(0,0,300,200), name, B_FOLLOW_NONE, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS)
: BView(BRect(0,0,300,200), name, B_FOLLOW_NONE,
B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS),
#endif
fSourcesLock("data sources")
{
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
@@ -585,6 +588,8 @@ ActivityView::CreateLegendLayoutItem()
DataSource*
ActivityView::FindDataSource(const DataSource* search)
{
BAutolock _(fSourcesLock);
for (int32 i = fSources.CountItems(); i-- > 0;) {
DataSource* source = fSources.ItemAt(i);
if (!strcmp(source->Name(), search->Name()))
@@ -601,6 +606,8 @@ ActivityView::AddDataSource(const DataSource* source, const BMessage* state)
if (source == NULL)
return B_BAD_VALUE;
BAutolock _(fSourcesLock);
int32 insert = DataSource::IndexOf(source);
for (int32 i = 0; i < fSources.CountItems() && i < insert; i++) {
DataSource* before = fSources.ItemAt(i);
@@ -667,6 +674,8 @@ ActivityView::RemoveDataSource(const DataSource* remove)
{
bool removed = false;
BAutolock _(fSourcesLock);
while (true) {
DataSource* source = FindDataSource(remove);
debug_printf("SEARCH %s, found %p\n", remove->Name(), source);
@@ -697,6 +706,8 @@ debug_printf("SEARCH %s, found %p\n", remove->Name(), source);
void
ActivityView::RemoveAllDataSources()
{
BAutolock _(fSourcesLock);
fSources.MakeEmpty();
fValues.MakeEmpty();
}
@@ -708,8 +719,10 @@ ActivityView::AttachedToWindow()
Looper()->AddHandler(fSystemInfoHandler);
fSystemInfoHandler->StartWatching();
BMessage refresh(kMsgRefresh);
fRunner = new BMessageRunner(this, &refresh, fRefreshInterval);
fRefreshSem = create_sem(0, "refresh sem");
fRefreshThread = spawn_thread(&_RefreshThread, "source refresh",
B_NORMAL_PRIORITY, this);
resume_thread(fRefreshThread);
FrameResized(Bounds().Width(), Bounds().Height());
}
@@ -721,7 +734,8 @@ ActivityView::DetachedFromWindow()
fSystemInfoHandler->StopWatching();
Looper()->RemoveHandler(fSystemInfoHandler);
delete fRunner;
delete_sem(fRefreshSem);
wait_for_thread(fRefreshThread, NULL);
}
@@ -896,6 +910,8 @@ ActivityView::MessageReceived(BMessage* message)
Invalidate(_HistoryFrame());
} else {
// check each legend color box
BAutolock _(fSourcesLock);
BRect legendFrame = _LegendFrame();
for (int32 i = 0; i < fSources.CountItems(); i++) {
BRect frame = _LegendColorFrameAt(legendFrame, i);
@@ -923,10 +939,6 @@ ActivityView::MessageReceived(BMessage* message)
ActivityMonitor::ShowAbout();
break;
case kMsgRefresh:
_Refresh();
break;
case kMsgToggleDataSource:
{
int32 index;
@@ -1022,6 +1034,8 @@ ActivityView::_LegendHeight() const
font_height fontHeight;
GetFontHeight(&fontHeight);
BAutolock _(fSourcesLock);
int32 rows = (fSources.CountItems() + 1) / 2;
return rows * (4 + ceilf(fontHeight.ascent)
+ ceilf(fontHeight.descent) + ceilf(fontHeight.leading));
@@ -1056,6 +1070,8 @@ ActivityView::_LegendFrameAt(BRect frame, int32 index) const
else
frame.left = frame.right - floorf(frame.Width() / 2) + 5;
BAutolock _(fSourcesLock);
int32 rows = (fSources.CountItems() + 1) / 2;
float height = floorf((frame.Height() - 5) / rows);
@@ -1146,6 +1162,7 @@ ActivityView::_DrawHistory()
// Draw values
view->SetPenSize(2);
BAutolock _(fSourcesLock);
for (uint32 i = fSources.CountItems(); i-- > 0;) {
DataSource* source = fSources.ItemAt(i);
@@ -1210,6 +1227,7 @@ ActivityView::Draw(BRect /*updateRect*/)
// draw legend
BAutolock _(fSourcesLock);
BRect legendFrame = _LegendFrame();
SetLowColor(fLegendBackgroundColor);
@@ -1252,22 +1270,46 @@ ActivityView::Draw(BRect /*updateRect*/)
void
ActivityView::_Refresh()
{
SystemInfo info(fSystemInfoHandler);
bigtime_t lastTimeout = system_time() - fRefreshInterval;
// TODO: run refresh in another thread to decouple it from the UI!
while (true) {
status_t status = acquire_sem_etc(fRefreshSem, 1, B_ABSOLUTE_TIMEOUT,
lastTimeout + fRefreshInterval);
if (status == B_OK || status == B_BAD_SEM_ID)
break;
if (status == B_INTERRUPTED)
continue;
for (uint32 i = fSources.CountItems(); i-- > 0;) {
DataSource* source = fSources.ItemAt(i);
DataHistory* values = fValues.ItemAt(i);
SystemInfo info(fSystemInfoHandler);
lastTimeout += fRefreshInterval;
int64 value = source->NextValue(info);
values->AddValue(info.Time(), value);
}
fSourcesLock.Lock();
bigtime_t now = info.Time();
if (fLastRefresh + fDrawInterval <= now) {
Invalidate();
fLastRefresh = now;
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);
}
fSourcesLock.Unlock();
bigtime_t now = info.Time();
if (fLastRefresh + fDrawInterval <= now) {
if (LockLooper()) {
Invalidate();
UnlockLooper();
fLastRefresh = now;
}
}
}
}
/*static*/ status_t
ActivityView::_RefreshThread(void* self)
{
((ActivityView*)self)->_Refresh();
return B_OK;
}