35
35
36
36
#include < cmath>
37
37
#include < memory>
38
+ #include < set>
38
39
#include < map>
39
40
#include < deque>
40
41
#include < queue>
@@ -90,17 +91,18 @@ namespace crimson {
90
91
double limit_inv;
91
92
92
93
// order parameters -- min, "normal", max
93
- ClientInfo (double _reservation, double _weight, double _limit) :
94
- reservation (_reservation),
95
- weight (_weight),
96
- limit (_limit),
97
- reservation_inv (0.0 == reservation ? 0.0 : 1.0 / reservation),
98
- weight_inv ( 0.0 == weight ? 0.0 : 1.0 / weight),
99
- limit_inv ( 0.0 == limit ? 0.0 : 1.0 / limit)
100
- {
101
- // empty
94
+ ClientInfo (double _reservation, double _weight, double _limit) {
95
+ update (_reservation, _weight, _limit);
102
96
}
103
97
98
+ inline void update (double _reservation, double _weight, double _limit) {
99
+ reservation = _reservation;
100
+ weight = _weight;
101
+ limit = _limit;
102
+ reservation_inv = (0.0 == reservation) ? 0.0 : 1.0 / reservation;
103
+ weight_inv = (0.0 == weight) ? 0.0 : 1.0 / weight;
104
+ limit_inv = (0.0 == limit) ? 0.0 : 1.0 / limit;
105
+ }
104
106
105
107
friend std::ostream& operator <<(std::ostream& out,
106
108
const ClientInfo& client) {
@@ -771,12 +773,14 @@ namespace crimson {
771
773
Duration idle_age;
772
774
Duration erase_age;
773
775
Duration check_time;
774
- std::deque<MarkPoint> clean_mark_points ;
776
+ std::deque<MarkPoint> idle_erase_mark_points ;
775
777
776
- // NB: All threads declared at end, so they're destructed first!
778
+ using IdleEraseListener = std::function<void (const C&)>;
779
+ std::set<const IdleEraseListener*> idle_erase_listeners;
777
780
778
- std::unique_ptr<RunEvery> cleaning_job;
781
+ // NB: All threads declared at end, so they're destructed first!
779
782
783
+ std::unique_ptr<RunEvery> idle_erase_job;
780
784
781
785
// COMMON constructor that others feed into; we can accept three
782
786
// different variations of durations
@@ -797,15 +801,34 @@ namespace crimson {
797
801
{
798
802
assert (_erase_age >= _idle_age);
799
803
assert (_check_time < _idle_age);
800
- cleaning_job =
804
+ idle_erase_job =
801
805
std::unique_ptr<RunEvery>(
802
806
new RunEvery (check_time,
803
- std::bind (&PriorityQueueBase::do_clean , this )));
807
+ std::bind (&PriorityQueueBase::do_idle_erase , this )));
804
808
}
805
809
806
810
807
811
~PriorityQueueBase () {
808
812
finishing = true ;
813
+
814
+ DataGuard g (data_mtx);
815
+
816
+ ready_heap.clear ();
817
+ limit_heap.clear ();
818
+ #if USE_PROP_HEAP
819
+ prop_heap.clear ();
820
+ #endif
821
+ resv_heap.clear ();
822
+
823
+ for (auto c = client_map.begin (); client_map.end () != c; /* empty */ ) {
824
+ auto current = c++;
825
+ for (auto l : idle_erase_listeners) {
826
+ (*l)(current->second ->client );
827
+ }
828
+ client_map.erase (current);
829
+ }
830
+
831
+ idle_erase_listeners.clear ();
809
832
}
810
833
811
834
@@ -1021,8 +1044,8 @@ namespace crimson {
1021
1044
void reduce_reservation_tags (const C& client_id) {
1022
1045
auto client_it = client_map.find (client_id);
1023
1046
1024
- // means the client was cleaned from map; should never happen
1025
- // as long as cleaning times are long enough
1047
+ // means the client was idle-erased from map; should never
1048
+ // happen as long as idle erase times are long enough
1026
1049
assert (client_map.end () != client_it);
1027
1050
reduce_reservation_tags (*client_it->second );
1028
1051
}
@@ -1116,27 +1139,27 @@ namespace crimson {
1116
1139
* This is being called regularly by RunEvery. Every time it's
1117
1140
* called it notes the time and delta counter (mark point) in a
1118
1141
* deque. It also looks at the deque to find the most recent
1119
- * mark point that is older than clean_age . It then walks the
1120
- * map and delete all server entries that were last used before
1121
- * that mark point.
1142
+ * mark point that is older than idle-erase age . It then walks
1143
+ * the map and delete all server entries that were last used
1144
+ * before that mark point.
1122
1145
*/
1123
- void do_clean () {
1146
+ void do_idle_erase () {
1124
1147
TimePoint now = std::chrono::steady_clock::now ();
1125
1148
DataGuard g (data_mtx);
1126
- clean_mark_points .emplace_back (MarkPoint (now, tick));
1149
+ idle_erase_mark_points .emplace_back (MarkPoint (now, tick));
1127
1150
1128
1151
// first erase the super-old client records
1129
1152
1130
1153
Counter erase_point = 0 ;
1131
- auto point = clean_mark_points .front ();
1154
+ auto point = idle_erase_mark_points .front ();
1132
1155
while (point.first <= now - erase_age) {
1133
1156
erase_point = point.second ;
1134
- clean_mark_points .pop_front ();
1135
- point = clean_mark_points .front ();
1157
+ idle_erase_mark_points .pop_front ();
1158
+ point = idle_erase_mark_points .front ();
1136
1159
}
1137
1160
1138
1161
Counter idle_point = 0 ;
1139
- for (auto i : clean_mark_points ) {
1162
+ for (auto i : idle_erase_mark_points ) {
1140
1163
if (i.first <= now - idle_age) {
1141
1164
idle_point = i.second ;
1142
1165
} else {
@@ -1148,14 +1171,17 @@ namespace crimson {
1148
1171
for (auto i = client_map.begin (); i != client_map.end (); /* empty */ ) {
1149
1172
auto i2 = i++;
1150
1173
if (erase_point && i2->second ->last_tick <= erase_point) {
1174
+ for (auto l : idle_erase_listeners) {
1175
+ (*l)(i2->second ->client );
1176
+ }
1151
1177
delete_from_heaps (i2->second );
1152
1178
client_map.erase (i2);
1153
1179
} else if (idle_point && i2->second ->last_tick <= idle_point) {
1154
1180
i2->second ->idle = true ;
1155
1181
}
1156
1182
} // for
1157
1183
} // if
1158
- } // do_clean
1184
+ } // do_idle_erase
1159
1185
1160
1186
1161
1187
// data_mtx must be held by caller
@@ -1176,6 +1202,21 @@ namespace crimson {
1176
1202
delete_from_heap (client, limit_heap);
1177
1203
delete_from_heap (client, ready_heap);
1178
1204
}
1205
+
1206
+ public:
1207
+
1208
+ void add_idle_erase_listener (const IdleEraseListener& listener) {
1209
+ DataGuard g (data_mtx);
1210
+ if (!finishing) {
1211
+ idle_erase_listeners.insert (&listener);
1212
+ }
1213
+ }
1214
+
1215
+
1216
+ void remove_idle_erase_listener (const IdleEraseListener& listener) {
1217
+ DataGuard g (data_mtx);
1218
+ idle_erase_listeners.erase (&listener);
1219
+ }
1179
1220
}; // class PriorityQueueBase
1180
1221
1181
1222
@@ -1487,7 +1528,6 @@ namespace crimson {
1487
1528
sched_ahead_thd.join ();
1488
1529
}
1489
1530
1490
- public:
1491
1531
1492
1532
inline void add_request (R&& request,
1493
1533
const C& client_id,
0 commit comments