Skip to content

Commit

Permalink
Adds unsafe_store operation
Browse files Browse the repository at this point in the history
  • Loading branch information
polytypic committed Sep 24, 2019
1 parent e0a87f8 commit 962187a
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 1 deletion.
4 changes: 3 additions & 1 deletion internals/testing/smoke_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ using namespace trade_v1;

auto smoke_test = test([]() {
atom<int> xA = 1;
atom<float> yA = 2.f;
atom<float> yA = 1.f;
atom<int> zA = 3;
atom<std::shared_ptr<int>> p(std::make_shared<int>(32));

verify(atomically(assume_readonly, []() { return true; }));

yA.unsafe_store(2);

{
verify(1 == xA.unsafe_load());
verify(2 == yA.unsafe_load());
Expand Down
21 changes: 21 additions & 0 deletions provides/include/trade_v1/private/private-methods.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,27 @@ Value &trade_v1::Private::store(atom_t<Value> &atom, Forwardable &&value) {
return access->m_current;
}

template <class Value>
const Value &trade_v1::Private::unsafe_store(atom_t<Value> &atom,
const Value &value) {
auto &lock = s_locks[lock_ix_of(&atom)];
molecular::backoff backoff;
while (true) {
auto u = lock.m_clock.load();
if (0 <= static_cast<signed_clock_t>(u)) {
if (lock.m_clock.compare_exchange_weak(
u, ~u, std::memory_order_acquire)) {
atom.m_value.store(value, std::memory_order_relaxed);
if (auto first = lock.m_first)
signal(first);
lock.m_clock.store(s_clock++, std::memory_order_release);
return value;
}
}
backoff();
}
}

template <class Value> Value &trade_v1::Private::ref(atom_t<Value> &atom) {
auto transaction = s_transaction;
auto access = insert(transaction, &atom);
Expand Down
3 changes: 3 additions & 0 deletions provides/include/trade_v1/private/private.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ class Private {
template <class Value, class Forwardable>
static Value &store(atom_t<Value> &atom, Forwardable &&value);

template <class Value>
static const Value &unsafe_store(atom_t<Value> &atom, const Value &value);

template <class Value> static Value &ref(atom_t<Value> &atom);

template <class Config, class Action>
Expand Down
5 changes: 5 additions & 0 deletions provides/include/trade_v1/synopsis.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ template <class Value> struct atom : Private::atom_t<Value> {
/// value` is equivalent to `atom.store(value)`.
template <class Forwardable> Value &store(Forwardable &&value);

/// Store the given value to the given atom as a single transaction. Note
/// that this cannot be used safely inside an `atomically` block, because it
/// can prevent the `atomically` block from ever completing.
const Value &unsafe_store(const Value &value);

/// Returns a mutable reference to the current value of the atom within a
/// transaction. `atom.ref()` is roughly equivalent to
/// `atom.store(atom.load())`, but accesses the transaction log only once.
Expand Down
5 changes: 5 additions & 0 deletions provides/include/trade_v1/trade.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ Value &trade_v1::atom<Value>::store(Forwardable &&value) {
return Private::store(*this, std::forward<Forwardable>(value));
}

template <class Value>
const Value &trade_v1::atom<Value>::unsafe_store(const Value &value) {
return Private::unsafe_store(*this, value);
}

template <class Config, class Action>
std::invoke_result_t<Action> trade_v1::atomically(Config config,
Action &&action) {
Expand Down

0 comments on commit 962187a

Please sign in to comment.