1 /*
2  *  Copyright (C) 2017-2019 Savoir-faire Linux Inc.
3  *  Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include "utils.h"
22 #include <queue>
23 
24 namespace dht {
25 
26 template<size_t Quota, unsigned long Period=1>
27 class RateLimiter {
28 public:
29     /** Clear outdated records and return current quota usage */
maintain(const time_point & now)30     size_t maintain(const time_point& now) {
31         auto limit = now - std::chrono::seconds(Period);
32         while (not records.empty() and records.front() < limit)
33             records.pop();
34         return records.size();
35     }
36     /** Return false if quota is reached, insert record and return true otherwise. */
limit(const time_point & now)37     bool limit(const time_point& now) {
38         if (maintain(now) >= Quota)
39             return false;
40         records.emplace(now);
41         return true;
42     }
empty()43     bool empty() const {
44         return records.empty();
45     }
46 private:
47     std::queue<time_point> records {};
48 };
49 
50 }
51