xref: /5.5.2/phosphor/src/chunk_lock.cc (revision db031a8a)
1/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *     Copyright 2017 Couchbase, Inc
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 */
17
18#include <cassert>
19
20#include <phosphor/chunk_lock.h>
21
22namespace phosphor {
23
24ChunkLock::ChunkLock(non_trivial_constructor_t t)
25    : state(State::Unlocked) {
26}
27
28ChunkLock::ChunkLock(const ChunkLock& other)
29   : state(other.state.load()) {
30}
31
32ChunkLock& ChunkLock::operator=(const ChunkLock& other) {
33    state = other.state.load();
34    return *this;
35}
36
37void ChunkLock::lockSlave() {
38    auto expected = State::Unlocked;
39    while (!state.compare_exchange_weak(expected, State::SlaveLocked)) {
40        expected = State::Unlocked;
41    }
42}
43
44bool ChunkLock::tryLockSlave() {
45    auto expected = State::Unlocked;
46    while (!state.compare_exchange_weak(expected, State::SlaveLocked)) {
47        if (expected == State::MasterLocked) {
48            return false;
49        }
50        expected = State::Unlocked;
51    }
52    return true;
53}
54
55void ChunkLock::unlockSlave() {
56#ifdef NDEBUG
57    state.store(State::Unlocked, std::memory_order_release);
58#else
59    auto expected = State::SlaveLocked;
60    assert(state.compare_exchange_strong(expected, State::Unlocked) &&
61           "ChunkLock::unlockSlave() should only be called while State::SlaveLocked");
62    (void)expected;
63#endif
64}
65
66SlaveChunkLock& ChunkLock::slave() {
67    return static_cast<SlaveChunkLock&>(*this);
68}
69
70void ChunkLock::lockMaster() {
71    auto expected = State::Unlocked;
72    while (!state.compare_exchange_weak(expected, State::MasterLocked)) {
73        expected = State::Unlocked;
74    }
75}
76
77void ChunkLock::unlockMaster() {
78#ifdef NDEBUG
79    state.store(State::Unlocked, std::memory_order_release);
80#else
81    auto expected = State::MasterLocked;
82    assert(state.compare_exchange_strong(expected, State::Unlocked) &&
83           "ChunkLock::unlockMaster() should only be called while State::MasterLocked");
84    (void)expected;
85#endif
86}
87
88MasterChunkLock& ChunkLock::master() {
89    return static_cast<MasterChunkLock&>(*this);
90}
91
92void SlaveChunkLock::lock() {
93    lockSlave();
94}
95
96bool SlaveChunkLock::try_lock() {
97    return tryLockSlave();
98}
99
100void SlaveChunkLock::unlock() {
101    unlockSlave();
102}
103
104void MasterChunkLock::lock() {
105    lockMaster();
106}
107
108void MasterChunkLock::unlock() {
109    unlockMaster();
110}
111
112ChunkTenant::ChunkTenant(non_trivial_constructor_t t)
113    : lck(non_trivial_constructor), chunk(nullptr), initialised(true) {
114}
115}
116