From 067d6e404587973f503876a15471b7639a8194ea Mon Sep 17 00:00:00 2001 From: KingToolbox <kingtoolbox@yandex.com> Date: Tue, 28 Jul 2020 01:43:10 +0800 Subject: [PATCH] Add a high-performance spin mutex class. --- src/README.md | 6 +++- src/Spin.h | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/Spin.h diff --git a/src/README.md b/src/README.md index 38a3f55..b0ad536 100644 --- a/src/README.md +++ b/src/README.md @@ -10,4 +10,8 @@ A quick circular buffer template class. ## Onigmo -An improved version based on Onigmo 5.13.5. In particular, **the addition of iterator makes it possible to match gap buffer or nonadjacent memory blocks.** Please refer to the sample files for how to use. \ No newline at end of file +An improved version based on Onigmo 5.13.5. In particular, **the addition of iterator makes it possible to match gap buffer or nonadjacent memory blocks.** Please refer to the sample files for how to use. + +## Spin.h + +A high-performance spin mutex and locker. \ No newline at end of file diff --git a/src/Spin.h b/src/Spin.h new file mode 100644 index 0000000..2ffbc44 --- /dev/null +++ b/src/Spin.h @@ -0,0 +1,79 @@ + /* + * Copyright 2020, WindTerm. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SPIN_H +#define SPIN_H + +#pragma once + +#include <atomic> +#include <thread> + +class SpinMutex { +public: + SpinMutex() { + unlock(); + } + + void yield(size_t nCount) { + if (nCount < 2) { + } else if (nCount < 16) { + std::this_thread::yield(); + } else if (nCount < 32) { + std::this_thread::sleep_for(std::chrono::nanoseconds(100)); + } else { + std::this_thread::sleep_for(std::chrono::microseconds(10)); + } + } + + void lock() { + for (size_t i = 0; !try_lock(); i++) { + yield(i); + } + } + + void unlock() { + flag.clear(std::memory_order_release); + } + + bool try_lock() { + return flag.test_and_set(std::memory_order_acquire) == false; + } + +private: + SpinMutex(const SpinMutex &) = delete; + SpinMutex &operator=(const SpinMutex &) = delete; + + std::atomic_flag flag; +}; + +template <typename LockType> +class ThreadLocker { +public: + ThreadLocker(LockType& m_, bool bLock_ = true) : m(m_), bLock(bLock_) { + if (bLock) m.lock(); + } + + ~ThreadLocker() { + if (bLock) m.unlock(); + } + +private: + LockType& m; + bool bLock; +}; + +#endif // SPIN_H \ No newline at end of file