39 : std::integral_constant<
41 std::is_trivial<T>::value && sizeof(T) <= sizeof(uint64_t)> {};
44 struct SettingContents {
45 std::string updateReason;
48 template <class... Args>
49 SettingContents(std::string _reason, Args&&... args)
50 : updateReason(std::move(_reason)), value(std::forward<Args>(args)...) {}
55 class SettingCoreBase {
58 using Version = uint64_t;
60 virtual void setFromString(
63 SnapshotBase* snapshot) = 0;
64 virtual std::pair<std::string, std::string> getAsString(
65 const SnapshotBase* snapshot) const = 0;
66 virtual void resetToDefault(SnapshotBase* snapshot) = 0;
67 virtual const SettingMetadata& meta() const = 0;
68 virtual ~SettingCoreBase() {}
74 return reinterpret_cast<Key>(this);
78 void registerSetting(SettingCoreBase& core);
83 SettingCoreBase::Version nextGlobalVersion();
93 BoxedValue() = default;
99 explicit BoxedValue(const SettingContents<T>& value)
100 : value_(std::make_shared<SettingContents<T>>(value)) {}
107 BoxedValue(const T& value, StringPiece reason, SettingCore<T>& core)
108 : value_(std::make_shared<SettingContents<T>>(reason.str(), value)),
109 publish_([value = value_, &core]() {
110 auto& contents = BoxedValue::unboxImpl<T>(value.get());
111 core.set(contents.value, contents.updateReason);
118 const SettingContents<T>& unbox() const {
119 return BoxedValue::unboxImpl<T>(value_.get());
132 std::shared_ptr<void> value_;
133 std::function<void()> publish_;
136 static const SettingContents<T>& unboxImpl(void* value) {
137 return *static_cast<const SettingContents<T>*>(value);
145 void saveValueForOutstandingSnapshots(
146 SettingCoreBase::Key settingKey,
147 SettingCoreBase::Version version,
148 const BoxedValue& value);
153 const BoxedValue* getSavedValue(
154 SettingCoreBase::Key key,
155 SettingCoreBase::Version at);
162 using SettingsInfo = std::pair<std::string, std::string>;
168 virtual void publish() = 0;
178 virtual bool setFromString(
179 StringPiece settingName,
180 StringPiece newValue,
181 StringPiece reason) = 0;
187 virtual Optional<SettingsInfo> getAsString(StringPiece settingName) const = 0;
195 virtual bool resetToDefault(StringPiece settingName) = 0;
201 virtual void forEachSetting(
203 void(const SettingMetadata&, StringPiece, StringPiece)>& func)
206 virtual ~SnapshotBase();
209 detail::SettingCoreBase::Version at_;
210 std::unordered_map<detail::SettingCoreBase::Key, detail::BoxedValue>
213 template <typename T>
214 friend class SettingCore;
219 const SettingContents<T>& get(const detail::SettingCore<T>& core) const {
220 auto it = snapshotValues_.find(core.getKey());
221 if (it != snapshotValues_.end()) {
222 return it->second.template unbox<T>();
228 return core.getSlow();
233 snapshotValues_[core.getKey()] = detail::BoxedValue(t, reason, core);
245 return to<T>(newValue);
256 SnapshotBase* snapshot)
override {
257 set(convertOrConstruct<T>(newValue), reason.
str(), snapshot);
261 const SnapshotBase* snapshot)
const override {
262 auto& contents = snapshot ? snapshot->get(*
this) :
getSlow();
263 return std::make_pair(
264 to<std::string>(contents.value), contents.updateReason);
268 set(defaultValue_,
"default", snapshot);
282 std::atomic<uint64_t>& trivialStorage)
const {
283 return getImpl(IsSmallPOD<T>(), trivialStorage);
294 std::memcpy(&t, &v,
sizeof(T));
303 return const_cast<SettingCore*
>(
this)->tlValue()->value;
306 void set(
const T&
t,
StringPiece reason, SnapshotBase* snapshot =
nullptr) {
311 snapshot->
set(*
this, t, reason);
319 getKey(), *settingVersion_, BoxedValue(*globalValue_));
321 globalValue_ = std::make_shared<Contents>(reason.str(),
t);
324 std::memcpy(&v, &t,
sizeof(T));
325 trivialStorage_.store(v);
331 return defaultValue_;
337 std::atomic<uint64_t>& trivialStorage)
339 defaultValue_(
std::
move(defaultValue)),
340 trivialStorage_(trivialStorage),
343 std::pair<Version, std::shared_ptr<Contents>>>(0,
nullptr);
345 set(defaultValue_,
"default");
366 auto&
value = **localValue_;
370 return tlValueSlow();
373 auto&
value = **localValue_;
374 while (
value.first < *settingVersion_) {
376 value.second.reset();
378 value.first = *settingVersion_;
379 value.second = globalValue_;
SettingCoreBase::Version nextGlobalVersion()
void set(const T &t, StringPiece reason, SnapshotBase *snapshot=nullptr)
void setFromString(StringPiece newValue, StringPiece reason, SnapshotBase *snapshot) override
#define FOLLY_ALWAYS_INLINE
SettingCore(SettingMetadata meta, T defaultValue, std::atomic< uint64_t > &trivialStorage)
constexpr detail::Map< Move > move
static http_parser_settings settings
—— Concurrent Priority Queue Implementation ——
const SettingMetadata & meta() const override
bool_constant< true > true_type
std::atomic< uint64_t > & trivialStorage_
void saveValueForOutstandingSnapshots(SettingCoreBase::Key settingKey, SettingCoreBase::Version version, const BoxedValue &value)
void resetToDefault(SnapshotBase *snapshot) override
FOLLY_ALWAYS_INLINE const std::shared_ptr< Contents > & tlValue() const
const BoxedValue *FOLLY_NULLABLE getSavedValue(SettingCoreBase::Key settingKey, SettingCoreBase::Version at)
ThreadLocal< CachelinePadded< std::pair< Version, std::shared_ptr< Contents > > > > localValue_
const T & defaultValue() const
void registerSetting(SettingCoreBase &core)
static const char *const value
std::enable_if_t< std::is_constructible< T, StringPiece >::value, T > convertOrConstruct(StringPiece newValue)
const T & getImpl(std::false_type, std::atomic< uint64_t > &) const
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
bool_constant< false > false_type
FOLLY_NOINLINE const std::shared_ptr< Contents > & tlValueSlow() const
std::conditional_t< IsSmallPOD< T >::value, T, const T & > getWithHint(std::atomic< uint64_t > &trivialStorage) const
std::pair< std::string, std::string > getAsString(const SnapshotBase *snapshot) const override
SettingContents< T > Contents
std::shared_ptr< Contents > globalValue_
const SettingContents< T > & getSlow() const
T getImpl(std::true_type, std::atomic< uint64_t > &trivialStorage) const