Add random number generator support to the IO interface
This commit is contained in:
parent
48ee40ce87
commit
881e914b92
@ -47,10 +47,15 @@ class SimulatorTransport {
|
||||
return simulator_handle_->template Send<M>(address, address_, request_id, message);
|
||||
}
|
||||
|
||||
std::time_t Now() { return std::time(nullptr); }
|
||||
uint64_t Now() { return simulator_handle_->Now(); }
|
||||
|
||||
bool ShouldShutDown() { return simulator_handle_->ShouldShutDown(); }
|
||||
|
||||
template <class D = std::poisson_distribution<>, class Return = uint64_t>
|
||||
Return Rand(D distrib) {
|
||||
return simulator_handle_->Rand<D, Return>(distrib);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<SimulatorHandle> simulator_handle_;
|
||||
Address address_;
|
||||
@ -58,7 +63,7 @@ class SimulatorTransport {
|
||||
|
||||
class Simulator {
|
||||
public:
|
||||
void SetConfig(SimulatorConfig config) { simulator_handle_->SetConfig(config); }
|
||||
Simulator(SimulatorConfig config) { simulator_handle_->SetConfig(config); }
|
||||
|
||||
void ShutDown() { simulator_handle_->ShutDown(); }
|
||||
|
||||
|
@ -227,6 +227,11 @@ class SimulatorHandle {
|
||||
return false;
|
||||
}
|
||||
|
||||
// clock ticks forwards by 400 microseconds on average
|
||||
std::poisson_distribution<> time_distrib(400);
|
||||
uint64_t clock_advance = time_distrib(rng_);
|
||||
cluster_wide_time_microseconds_ += clock_advance;
|
||||
|
||||
if (in_flight_.empty()) {
|
||||
return false;
|
||||
}
|
||||
@ -263,6 +268,7 @@ class SimulatorHandle {
|
||||
|
||||
void SetConfig(SimulatorConfig config) {
|
||||
std::unique_lock<std::mutex> lock(mu_);
|
||||
rng_ = std::mt19937{config.rng_seed};
|
||||
config_ = config;
|
||||
cv_.notify_all();
|
||||
}
|
||||
@ -340,6 +346,17 @@ class SimulatorHandle {
|
||||
in_flight_.emplace_back(std::make_pair(std::move(to_address), std::move(om)));
|
||||
}
|
||||
|
||||
uint64_t Now() {
|
||||
std::unique_lock<std::mutex> lock(mu_);
|
||||
return cluster_wide_time_microseconds_;
|
||||
}
|
||||
|
||||
template <class D = std::poisson_distribution<>, class Return = uint64_t>
|
||||
Return Rand(D distrib) {
|
||||
std::unique_lock<std::mutex> lock(mu_);
|
||||
return distrib(rng_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex mu_{};
|
||||
std::condition_variable cv_;
|
||||
@ -360,4 +377,5 @@ class SimulatorHandle {
|
||||
size_t servers_ = 0;
|
||||
std::set<Address> server_addresses_;
|
||||
SimulatorConfig config_;
|
||||
std::mt19937 rng_{};
|
||||
};
|
||||
|
@ -14,6 +14,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <concepts>
|
||||
#include <random>
|
||||
#include <variant>
|
||||
|
||||
#include "utils/result.hpp"
|
||||
@ -120,13 +121,21 @@ class Io {
|
||||
return implementation_.template Send<M>(address, request_id, message);
|
||||
}
|
||||
|
||||
/// The current system time. This time source should be preferred over
|
||||
/// any other time source.
|
||||
std::time_t Now() { return implementation_.Now(); }
|
||||
/// The current system time in microseconds since the unix epoch.
|
||||
/// This time source should be preferred over any other, because it
|
||||
/// lets us deterministically control clocks from tests for making
|
||||
/// things like timeouts deterministic.
|
||||
uint64_t Now() { return implementation_.Now(); }
|
||||
|
||||
/// Returns true of the system should shut-down.
|
||||
bool ShouldShutDown() { return implementation_.ShouldShutDown(); }
|
||||
|
||||
/// Returns a random number within the specified distribution.
|
||||
template <class D = std::poisson_distribution<>, class Return = uint64_t>
|
||||
Return Rand(D distrib) {
|
||||
return implementation_.template Rand<D, Return>(distrib);
|
||||
}
|
||||
|
||||
private:
|
||||
I implementation_;
|
||||
Address address_;
|
||||
|
Loading…
Reference in New Issue
Block a user