1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2016 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 /** \file
18  * This file is internal to the inner workings of
19  * Phosphor and is not intended for public consumption.
20  */
21 
22 #pragma once
23 
24 #include <atomic>
25 
26 namespace phosphor {
27 
28     template <typename T>
29     class RelaxedAtomic {
30     public:
31         RelaxedAtomic() = default;
32 
RelaxedAtomic(const T& initial)33         RelaxedAtomic(const T& initial) {
34             value.store(initial, std::memory_order_relaxed);
35         }
36 
RelaxedAtomic(const RelaxedAtomic& other)37         RelaxedAtomic(const RelaxedAtomic& other) {
38             value.store(other.value.load(std::memory_order_relaxed),
39                         std::memory_order_relaxed);
40         }
41 
operator T() const42         operator T() const {
43             return value.load(std::memory_order_relaxed);
44         }
45 
load() const46         T load() const {
47             return value.load(std::memory_order_relaxed);
48         }
49 
operator =(const RelaxedAtomic& rhs)50         RelaxedAtomic& operator=(const RelaxedAtomic& rhs) {
51             value.store(rhs.load(), std::memory_order_relaxed);
52             return *this;
53         }
54 
operator =(T val)55         RelaxedAtomic& operator=(T val) {
56             value.store(val, std::memory_order_relaxed);
57             return *this;
58         }
59 
operator ++()60         T operator++() {
61             return value.fetch_add(1, std::memory_order_relaxed) + 1;
62         }
63 
operator ++(int)64         T operator++(int) {
65             return value.fetch_add(1, std::memory_order_relaxed);
66         }
67 
operator --()68         T operator--() {
69             return value.fetch_sub(1, std::memory_order_relaxed) - 1;
70         }
71 
operator --(int)72         T operator--(int) {
73             return value.fetch_sub(1, std::memory_order_relaxed);
74         }
75 
76     protected:
77         std::atomic<T> value;
78     };
79 
80     class RelaxedAtomicCString : public RelaxedAtomic<const char *> {
81     public:
82         RelaxedAtomicCString() = default;
83 
RelaxedAtomicCString(const char* initial)84         RelaxedAtomicCString(const char* initial) {
85             value.store(initial, std::memory_order_relaxed);
86         }
87 
RelaxedAtomicCString(const RelaxedAtomicCString& other)88         RelaxedAtomicCString(const RelaxedAtomicCString& other) {
89             value.store(other.load(), std::memory_order_relaxed);
90         }
91 
operator std::string() const92         operator std::string() const {
93             return std::string(value.load(std::memory_order_relaxed));
94         }
95     };
96 
97 }