181f45f5dSWill Gardner/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
281f45f5dSWill Gardner/*
381f45f5dSWill Gardner *     Copyright 2016 Couchbase, Inc
481f45f5dSWill Gardner *
581f45f5dSWill Gardner *   Licensed under the Apache License, Version 2.0 (the "License");
681f45f5dSWill Gardner *   you may not use this file except in compliance with the License.
781f45f5dSWill Gardner *   You may obtain a copy of the License at
881f45f5dSWill Gardner *
981f45f5dSWill Gardner *       http://www.apache.org/licenses/LICENSE-2.0
1081f45f5dSWill Gardner *
1181f45f5dSWill Gardner *   Unless required by applicable law or agreed to in writing, software
1281f45f5dSWill Gardner *   distributed under the License is distributed on an "AS IS" BASIS,
1381f45f5dSWill Gardner *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1481f45f5dSWill Gardner *   See the License for the specific language governing permissions and
1581f45f5dSWill Gardner *   limitations under the License.
1681f45f5dSWill Gardner */
1781f45f5dSWill Gardner/** \file
1881f45f5dSWill Gardner * This file is internal to the inner workings of
1981f45f5dSWill Gardner * Phosphor and is not intended for public consumption.
2081f45f5dSWill Gardner */
2181f45f5dSWill Gardner
2281f45f5dSWill Gardner#pragma once
2381f45f5dSWill Gardner
2481f45f5dSWill Gardner#include <atomic>
2581f45f5dSWill Gardner
2681f45f5dSWill Gardnernamespace phosphor {
2781f45f5dSWill Gardner
2881f45f5dSWill Gardner    template <typename T>
2981f45f5dSWill Gardner    class RelaxedAtomic {
3081f45f5dSWill Gardner    public:
3181f45f5dSWill Gardner        RelaxedAtomic() = default;
3281f45f5dSWill Gardner
3381f45f5dSWill Gardner        RelaxedAtomic(const T& initial) {
3481f45f5dSWill Gardner            value.store(initial, std::memory_order_relaxed);
3581f45f5dSWill Gardner        }
3681f45f5dSWill Gardner
3781f45f5dSWill Gardner        RelaxedAtomic(const RelaxedAtomic& other) {
3881f45f5dSWill Gardner            value.store(other.value.load(std::memory_order_relaxed),
3981f45f5dSWill Gardner                        std::memory_order_relaxed);
4081f45f5dSWill Gardner        }
4181f45f5dSWill Gardner
4281f45f5dSWill Gardner        operator T() const {
4381f45f5dSWill Gardner            return value.load(std::memory_order_relaxed);
4481f45f5dSWill Gardner        }
4581f45f5dSWill Gardner
4681f45f5dSWill Gardner        T load() const {
4781f45f5dSWill Gardner            return value.load(std::memory_order_relaxed);
4881f45f5dSWill Gardner        }
4981f45f5dSWill Gardner
5081f45f5dSWill Gardner        RelaxedAtomic& operator=(const RelaxedAtomic& rhs) {
5181f45f5dSWill Gardner            value.store(rhs.load(), std::memory_order_relaxed);
5281f45f5dSWill Gardner            return *this;
5381f45f5dSWill Gardner        }
5481f45f5dSWill Gardner
5581f45f5dSWill Gardner        RelaxedAtomic& operator=(T val) {
5681f45f5dSWill Gardner            value.store(val, std::memory_order_relaxed);
5781f45f5dSWill Gardner            return *this;
5881f45f5dSWill Gardner        }
5981f45f5dSWill Gardner
601fae1f13SWillGardner        T operator++() {
611fae1f13SWillGardner            return value.fetch_add(1, std::memory_order_relaxed) + 1;
621fae1f13SWillGardner        }
641fae1f13SWillGardner        T operator++(int) {
651fae1f13SWillGardner            return value.fetch_add(1, std::memory_order_relaxed);
661fae1f13SWillGardner        }
681fae1f13SWillGardner        T operator--() {
691fae1f13SWillGardner            return value.fetch_sub(1, std::memory_order_relaxed) - 1;
701fae1f13SWillGardner        }
721fae1f13SWillGardner        T operator--(int) {
731fae1f13SWillGardner            return value.fetch_sub(1, std::memory_order_relaxed);
741fae1f13SWillGardner        }
7681f45f5dSWill Gardner    protected:
7781f45f5dSWill Gardner        std::atomic<T> value;
7881f45f5dSWill Gardner    };
7981f45f5dSWill Gardner
8081f45f5dSWill Gardner    class RelaxedAtomicCString : public RelaxedAtomic<const char *> {
8181f45f5dSWill Gardner    public:
8281f45f5dSWill Gardner        RelaxedAtomicCString() = default;
8381f45f5dSWill Gardner
8481f45f5dSWill Gardner        RelaxedAtomicCString(const char* initial) {
8581f45f5dSWill Gardner            value.store(initial, std::memory_order_relaxed);
8681f45f5dSWill Gardner        }
8781f45f5dSWill Gardner
8881f45f5dSWill Gardner        RelaxedAtomicCString(const RelaxedAtomicCString& other) {
89a6a21dccSWill Gardner            value.store(other.load(), std::memory_order_relaxed);
9081f45f5dSWill Gardner        }
9181f45f5dSWill Gardner
9281f45f5dSWill Gardner        operator std::string() const {
9381f45f5dSWill Gardner            return std::string(value.load(std::memory_order_relaxed));
9481f45f5dSWill Gardner        }
9581f45f5dSWill Gardner    };
9681f45f5dSWill Gardner
9781f45f5dSWill Gardner}