Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions include/tscore/Throttler.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,27 @@ class Throttler
private:
/// Base clock.
using Clock = std::chrono::system_clock;
/// Time point type, based on the clock to be used.
using TimePoint = Clock::time_point;

/** A time_point with a noexcept constructor.
*
* This is a workaround for older gcc and clang compilers which implemented an
* older version of the standard which made atomic's noexcept construction
* specification not compatible with time_point's undecorated constructor.
*/
class TimePoint : public Clock::time_point
{
public:
using time_point::time_point;

// This noexcept specification makes TimePoint compatible with older
// compiler implementations of atomic.
constexpr TimePoint() noexcept : time_point() {}

template <class Duration2> constexpr TimePoint(const time_point<Clock, Duration2> &t) : time_point(t) {}
};

/// Time that the last item was emitted.
// It is strange that we need to explicitly default construct this with a
// default constructed TimePoint. Without it, however, I get a compiler error
// in gcc 8.x and 9.x. Playing around in godbolt I notice that neither clang
// nor gcc versions starting from 10.x require this, so I suspect it is a
// compiler bug.
std::atomic<TimePoint> _last_allowed_time{TimePoint{}};
std::atomic<TimePoint> _last_allowed_time;

/// The minimum number of microseconds desired between actions.
std::atomic<std::chrono::microseconds> _interval{std::chrono::microseconds{0}};
Expand Down
2 changes: 1 addition & 1 deletion src/tscore/Throttler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ bool
Throttler::is_throttled(uint64_t &skipped_count)
{
TimePoint const now = Clock::now();
TimePoint last_allowed_time{_last_allowed_time};
TimePoint last_allowed_time{_last_allowed_time.load()};
if ((last_allowed_time + _interval.load()) <= now) {
if (_last_allowed_time.compare_exchange_strong(last_allowed_time, now)) {
skipped_count = _suppressed_count;
Expand Down