libutil++  1.9.3
 All Classes Functions Variables
WRR.h
1 /*
2 ** libutil++
3 ** $Id: WRR.h 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 #ifndef __libutilxx__sella__algo__WRR_H__
10 #define __libutilxx__sella__algo__WRR_H__
11 
12 #include "../../common.h"
13 
14 #include <stdio.h>
15 #include <string>
16 #include <map>
17 
18 namespace sella {
19  namespace algo {
20  template <class T> class WRR;
21 
22  template <class T> class WRRNode {
23  friend class WRR<T>;
24 
25  public:
26  WRRNode(const T & data, double weight = 1.0) throw ();
27 
28  private:
29  double weight;
30 
31  double points;
32  double rate;
33 
34  T data;
35  };
36 
37  template <class T> class WRR {
38  public:
39  WRR() throw ();
40 
41  void insert(const std::string & identifier, const T & node, double weight = 1.0) throw ();
42  void remove(const std::string & identifier) throw ();
43  void update(const std::string & identifier, double weight = 1.0) throw ();
44 
45  T & next() throw ();
46 
47  private:
48  double total;
49 
50  typename std::map<std::string, WRRNode<T> > node;
51  typename std::map<std::string, WRRNode<T> >::iterator iter;
52  };
53  }
54 }
55 
56 template <class T> sella::algo::WRR<T>::WRR() throw () :
57  total(0.0),
58 
59  node(),
60  iter(node.end())
61 { }
62 
63 template <class T> sella::algo::WRRNode<T>::WRRNode(const T & data, double weight) throw () :
64  weight(weight),
65 
66  points(0.0),
67  rate(0.0),
68 
69  data(data)
70 { }
71 
72 template <class T> void sella::algo::WRR<T>::insert(const std::string & identifier, const T & node, double weight) throw () {
73  this->node.insert(std::make_pair(identifier, WRRNode<T>(node, weight)));
74  this->total += weight;
75 
76  for (auto iter = this->node.begin(); iter != this->node.end(); ++iter) {
77  iter->second.rate = iter->second.weight / this->total;
78  }
79 }
80 
81 template <class T> void sella::algo::WRR<T>::remove(const std::string & identifier) throw () {
82  auto iter = this->node.find(identifier);
83 
84  if (iter != this->node.end()) {
85  this->total -= iter->second.weight;
86 
87  this->node.erase(iter);
88  }
89 
90  for (iter = this->node.begin(); iter != this->node.end(); ++iter) {
91  iter->second.rate = iter->second.weight / this->total;
92  }
93 }
94 
95 template <class T> void sella::algo::WRR<T>::update(const std::string & identifier, double weight) throw () {
96  auto iter = this->node.find(identifier);
97 
98  if (iter != this->node.end()) {
99  iter->weight = weight;
100 
101  this->total -= iter->second.weight;
102  this->total += weight;
103  }
104 
105  for (iter = this->node.begin(); iter != this->node.end(); ++iter) {
106  iter->second.rate = iter->second.weight / this->total;
107  }
108 }
109 
110 template <class T> T & sella::algo::WRR<T>::next() throw () {
111  while (true) {
112  while (this->iter != this->node.end()) {
113  auto item = this->iter;
114 
115  ++(this->iter);
116 
117  item->second.points += item->second.rate;
118 
119  if (item->second.points >= 1.0) {
120  item->second.points -= 1.0;
121 
122  return item->second.data;
123  }
124  }
125  this->iter = this->node.begin();
126  }
127 }
128 
129 #endif
130 
131 /*
132 ** vim: noet ts=3 sw=3
133 */