libutil++  1.9.3
 All Classes Functions Variables
TokenBucket.cpp
1 /*
2 ** libutil++
3 ** $Id: TokenBucket.cpp 1653 2016-02-28 19:54:59Z sella $
4 ** Copyright (c) 2011-2016 Digital Genesis, LLC. All Rights Reserved.
5 ** Released under the LGPL Version 2.1 License.
6 ** http://www.digitalgenesis.com
7 */
8 
9 static const char rcsid[] __attribute__((used)) = "$Id: TokenBucket.cpp 1653 2016-02-28 19:54:59Z sella $";
10 
11 #include "TokenBucket.h"
12 
13 #include <sys/time.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 
17 using namespace sella::algo;
18 
19 TokenBucket::TokenBucket(const TokenBucket & chain, double limit) throw () :
20  chain(std::make_shared<TokenBucket>(chain)),
21 
22  stamp(0),
23 
24  limit(limit),
25  value(0.0)
26 { }
27 
28 TokenBucket::TokenBucket(double limit) throw () :
29  chain(),
30 
31  stamp(0),
32 
33  limit(limit),
34  value(0.0)
35 { }
36 
37 bool TokenBucket::sub(double value, bool blocking) throw () {
38  struct timeval stamp;
39  uint64_t usecs;
40 
41 retry:
42  if (this->chain.get() != NULL) {
43  if (this->chain->sub(value, blocking) == false) {
44  return false;
45  }
46  }
47 
48  gettimeofday(&stamp, NULL);
49  usecs = (stamp.tv_sec * 1000000) + stamp.tv_usec;
50 
51  if ((this->value += ((usecs - this->stamp) * this->limit) / 1000000) > this->limit) {
52  this->value = this->limit;
53  }
54  this->stamp = usecs;
55 
56  if (this->value > 0.0) {
57  this->value -= value;
58 
59  return true;
60  }
61 
62  if (this->chain.get() != NULL) {
63  this->chain->add(value);
64  }
65 
66  if (blocking) {
67  usleep((0.0 - value) / this->limit * 1000000);
68  goto retry;
69  }
70  return false;
71 }
72 
73 bool TokenBucket::add(double value) throw () {
74  if ((this->value += value) > this->limit) {
75  this->value = this->limit;
76  }
77  return true;
78 }
79 
80 /*
81 ** vim: noet ts=3 sw=3
82 */