aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <mbuland@penny-arcade.com>2018-07-02 11:34:44 -0700
committerMike Buland <mbuland@penny-arcade.com>2018-07-02 11:34:44 -0700
commit74973a93594e4150a827459708895577a795036b (patch)
tree9faff0701bf458144c58f9b9d29ce845dd132aeb
parent9bcbc8f919fc1c779d3b9c649dcbe3606fdbed32 (diff)
downloadlibbu++-74973a93594e4150a827459708895577a795036b.tar.gz
libbu++-74973a93594e4150a827459708895577a795036b.tar.bz2
libbu++-74973a93594e4150a827459708895577a795036b.tar.xz
libbu++-74973a93594e4150a827459708895577a795036b.zip
Added a threadsafe speedometer class.
-rw-r--r--default.bld5
-rw-r--r--src/tests/speedometer.cpp51
-rw-r--r--src/unstable/speedometer.cpp120
-rw-r--r--src/unstable/speedometer.h43
4 files changed, 219 insertions, 0 deletions
diff --git a/default.bld b/default.bld
index dbb3772..c471744 100644
--- a/default.bld
+++ b/default.bld
@@ -34,6 +34,11 @@ action "all"
34 targets("tools"), targets("tests")]; 34 targets("tools"), targets("tests")];
35} 35}
36 36
37action "tests"
38{
39 build: targets("tests");
40}
41
37action "unit" 42action "unit"
38{ 43{
39 build: targets("unit tests"); 44 build: targets("unit tests");
diff --git a/src/tests/speedometer.cpp b/src/tests/speedometer.cpp
new file mode 100644
index 0000000..4532f59
--- /dev/null
+++ b/src/tests/speedometer.cpp
@@ -0,0 +1,51 @@
1#include <bu/sio.h>
2#include <bu/speedometer.h>
3#include <bu/thread.h>
4
5#include <unistd.h>
6
7class Report : public Bu::Thread
8{
9public:
10 Report() :
11 sKeys( 500, 8 )
12 {
13 }
14
15 ~Report()
16 {
17 }
18
19 Bu::Speedometer sKeys;
20 bool bRunning;
21
22protected:
23 virtual void run()
24 {
25 bRunning = true;
26 while( bRunning )
27 {
28 usleep( 500000 );
29// Bu::println("Speed: %1 - %2 k/s").arg( sKeys.getTotalEvents() ).
30// arg( sKeys.getSpeed() );
31 }
32 }
33};
34
35int main( int argc, char *argv[] )
36{
37 Report r;
38
39 r.start();
40
41 for(;;)
42 {
43 getchar();
44 r.sKeys.addEvent();
45 r.sKeys.debug();
46 }
47
48
49 return 0;
50}
51
diff --git a/src/unstable/speedometer.cpp b/src/unstable/speedometer.cpp
new file mode 100644
index 0000000..75e424e
--- /dev/null
+++ b/src/unstable/speedometer.cpp
@@ -0,0 +1,120 @@
1#include "bu/speedometer.h"
2#include "bu/mutexlocker.h"
3#include "bu/sio.h"
4
5#include <sys/time.h>
6#include <string.h>
7
8Bu::Speedometer::Speedometer( int64_t iBucketMs, int32_t iBucketCount ) :
9 aiBucket( NULL ),
10 iTotal( 0 ),
11 iCapacity( iBucketCount ),
12 iFill( 0 ),
13 iStart( 0 ),
14 iCurrent( 0 ),
15 iBucketMs( iBucketMs ),
16 iStartTime( -1 ),
17 iWindowSizeMs( iBucketMs*iBucketCount ),
18 iLastUpdate( -1 )
19{
20 aiBucket = new uint32_t[iCapacity];
21 memset( aiBucket, 0, sizeof(uint32_t)*iCapacity );
22}
23
24Bu::Speedometer::~Speedometer()
25{
26 delete[] aiBucket;
27 aiBucket = NULL;
28}
29
30void Bu::Speedometer::addEvent()
31{
32 Bu::MutexLocker l( mLock );
33 int64_t iNow = getCurrentTime();
34 _updateBuckets( iNow );
35 if( iStartTime < 0 )
36 {
37 iStartTime = iNow;
38 iFill = 1;
39 aiBucket[iCurrent] = 1;
40 iTotal = 1;
41 }
42 else
43 {
44 aiBucket[iCurrent]++;
45 iTotal++;
46 }
47 iLastUpdate = iNow;
48}
49
50void Bu::Speedometer::debug()
51{
52 Bu::MutexLocker l( mLock );
53 Bu::print("%1 of %2: %3:%4: ").
54 arg( iFill ).arg( iCapacity ).arg( iStart ).arg( iCurrent );
55 for( int j = 0; j < iFill; j++ )
56 {
57 Bu::print("%1 | ").arg( aiBucket[(j+iStart)%iCapacity] );
58 }
59 Bu::println(" total = %1").arg( iTotal );
60}
61
62void Bu::Speedometer::_updateBuckets( int64_t iNow )
63{
64 if( iNow > iLastUpdate+iWindowSizeMs )
65 {
66 iLastUpdate = iStartTime = -1;
67 iFill = 0;
68 iStart = iCurrent = 0;
69 aiBucket[iCurrent] = 0;
70 iTotal = 0;
71 }
72 else
73 {
74 int64_t iSkip = (iNow-(iStartTime+iBucketMs*iFill));
75 if( iSkip < 0 )
76 return;
77 iSkip = (iSkip/iBucketMs) + ((iSkip%iBucketMs)?(1):(0));
78
79 for( int64_t j = 0; j < iSkip; j++ )
80 {
81 iCurrent = (iCurrent+1)%iCapacity;
82 if( iFill < iCapacity )
83 {
84 iFill++;
85 }
86 else
87 {
88 iTotal -= aiBucket[iStart];
89 aiBucket[iStart] = 0;
90 iStart = (iStart+1)%iCapacity;
91 iStartTime += iBucketMs;
92 }
93 }
94 }
95}
96
97double Bu::Speedometer::getSpeed()
98{
99 Bu::MutexLocker l( mLock );
100 _updateBuckets( getCurrentTime() );
101
102 if( iStartTime < 0 )
103 return 0.0;
104
105 return (double)iTotal / (double)(iFill*iBucketMs);
106}
107
108int32_t Bu::Speedometer::getTotalEvents()
109{
110 Bu::MutexLocker l( mLock );
111 return iTotal;
112}
113
114int64_t Bu::Speedometer::getCurrentTime() const
115{
116 struct timeval tv;
117 gettimeofday( &tv, NULL );
118 return tv.tv_sec*1000 + tv.tv_usec/1000;
119}
120
diff --git a/src/unstable/speedometer.h b/src/unstable/speedometer.h
new file mode 100644
index 0000000..84d21ed
--- /dev/null
+++ b/src/unstable/speedometer.h
@@ -0,0 +1,43 @@
1#ifndef BU_SPEEDOMETER_H
2#define BU_SPEEDOMETER_H
3
4#include "bu/mutex.h"
5
6#include <stdint.h>
7
8namespace Bu
9{
10 class Speedometer
11 {
12 public:
13 Speedometer( int64_t iBucketMs, int32_t iBucketCount );
14 virtual ~Speedometer();
15
16 void addEvent();
17 double getSpeed();
18 int32_t getTotalEvents();
19 void debug();
20
21 private:
22 void _updateBuckets( int64_t iNow );
23 /**
24 * Gets the current time in milliseconds.
25 */
26 int64_t getCurrentTime() const;
27
28 private:
29 uint32_t *aiBucket;
30 uint32_t iTotal;
31 int32_t iCapacity;
32 int32_t iFill;
33 int32_t iStart;
34 int32_t iCurrent;
35 int64_t iBucketMs;
36 int64_t iStartTime;
37 int64_t iWindowSizeMs;
38 int64_t iLastUpdate;
39 mutable Bu::Mutex mLock;
40 };
41}
42
43#endif