LogCabin
|
00001 /* Copyright (c) 2014-2015 Diego Ongaro 00002 * 00003 * Permission to use, copy, modify, and distribute this software for any 00004 * purpose with or without fee is hereby granted, provided that the above 00005 * copyright notice and this permission notice appear in all copies. 00006 * 00007 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES 00008 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00009 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR 00010 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00011 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00012 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00013 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00014 */ 00015 00016 #ifndef LOGCABIN_CLIENT_BACKOFF_H 00017 #define LOGCABIN_CLIENT_BACKOFF_H 00018 00019 #include <cinttypes> 00020 #include <deque> 00021 #include <mutex> 00022 00023 #include "Core/Time.h" 00024 00025 namespace LogCabin { 00026 namespace Client { 00027 00028 /** 00029 * A simple backoff mechanism. Currently used in the client library to 00030 * rate-limit the creation of new TCP connections. 00031 */ 00032 class Backoff { 00033 public: 00034 /// Clock used for keeping track of when operations started. 00035 typedef Core::Time::SteadyClock Clock; 00036 /// Point in time on #Clock. Used for timeouts. 00037 typedef Clock::time_point TimePoint; 00038 00039 /** 00040 * Constructor. 00041 * \param windowCount 00042 * At most this many operations are allowed in any windowNanos period 00043 * of time. 00044 * \param windowNanos 00045 * The duration over which at most windowCount operations are allowed. 00046 * \warning 00047 * The memory usage of this class is proportional to windowCount. 00048 */ 00049 Backoff(uint64_t windowCount, uint64_t windowNanos); 00050 00051 /** 00052 * Destructor. 00053 */ 00054 ~Backoff(); 00055 00056 /** 00057 * This is invoked before beginning a new operation. If the operation may 00058 * not proceed yet, this method sleeps until starting the operation becomes 00059 * permissible. 00060 * \param timeout 00061 * Maximum time at which to stop sleeping and return, without marking 00062 * the operation as having started. 00063 */ 00064 void delayAndBegin(TimePoint timeout); 00065 00066 private: 00067 00068 /** 00069 * Protects all of the following member variables in this class. 00070 */ 00071 std::mutex mutex; 00072 00073 /** 00074 * At most #windowCount operations are allowed in any #windowDuration 00075 * period of time. 00076 */ 00077 uint64_t windowCount; 00078 00079 /** 00080 * See #windowCount. 00081 */ 00082 std::chrono::nanoseconds windowDuration; 00083 00084 /** 00085 * The times when the last #windowCount operations were initiated. If fewer 00086 * than #windowCount operations have been initiated, this is padded with 00087 * negative infinity. The front time is the oldest, and the back is the 00088 * most recent. 00089 */ 00090 std::deque<TimePoint> startTimes; 00091 }; 00092 00093 } // namespace LogCabin::Client 00094 } // namespace LogCabin 00095 00096 #endif /* LOGCABIN_CLIENT_BACKOFF_H */