Skip to content

Commit 6d3dcd7

Browse files
committed
[模块升级]: 替换 Mutex 模块为 SpinMutex 模块
- 删除了原有的 Mutex 相关代码,包括 `CMakeLists.txt`、`main.cc` 和 `mutex.hpp`。 - 新建了 SpinMutex 模块,相关文件包括 `CMakeLists.txt`、`spinmutex.hpp` 和 `spinmutex_unittest.cc`。 - 进一步优化了 SpinMutex 的功能,具体如下: - 简化了 SpinMutex 的实现,使其更加轻量化。 - 通过引入 Google Test 框架,为 SpinMutex 增加了单元测试,确保锁行为的正确性。 - 更新了项目文档(`README.md`),替换了 Mutex 的描述为 SpinMutex,并对相关内容进行了调整。
1 parent 42847d8 commit 6d3dcd7

8 files changed

+123
-89
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ add_subdirectory(LinkedList)
6666
add_subdirectory(Memcpy)
6767
add_subdirectory(MonitorDir)
6868
add_subdirectory(MonitorDir_EFSW)
69-
add_subdirectory(Mutex)
7069
add_subdirectory(OpenSSL)
7170
add_subdirectory(SafeCallback)
71+
add_subdirectory(SpinMutex)
7272
add_subdirectory(Thread)
7373

7474
if(CMAKE_HOST_LINUX)

Mutex/CMakeLists.txt

-5
This file was deleted.

Mutex/main.cc

-33
This file was deleted.

Mutex/mutex.hpp

-46
This file was deleted.

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@
3535
1. 获取事件发生文件所在的上级路径中,使用了`open_by_handle_at`这个方法,普通用户下会出现`Operation not permitted`错误,也需要`CAP_SYS_ADMIN`能力,即root权限;
3636
2. 建议使用root权限运行,如果一定要在普通用户下运行,还是建议使用`inotify`而不是`fanotify`,反正在打开一个监控文件描述符(`fd`)的情况下,都无法实现`subtree`监控;
3737
23. [MonitorDir_EFSW](/MonitorDir_EFSW/main.cc)——使用efsw实现的目录监控的简单例子;
38-
24. [Mutex](/Mutex/mutex.hpp)——使用std::atomic_flag实现的简单互斥锁和自旋锁;
39-
25. [OpenSSL](/OpenSSL)——openssl的一些例子;
38+
24. [OpenSSL](/OpenSSL)——openssl的一些例子;
4039
1. [aes](/OpenSSL/openssl_aes.cc)——aes加解密的例子;
4140
2. [base64](/OpenSSL/openssl_base64.cc)——base64编解码的例子;
4241
3. [hash](/OpenSSL/openssl_hash.cc)——sha256的例子;
@@ -46,11 +45,12 @@
4645
7. [sm4](/OpenSSL/openssl_sm4.cc)——sm4加解密的例子;
4746
8. [x509](/OpenSSL/openssl_x509.cc)——x509证书的例子;
4847
9. [bash](/OpenSSL/openssl_bash.sh)——openssl命令行的例子;
49-
26. [SafeCallback](/SafeCallback/safecallback.hpp)——生命周期安全的回调函数的实现,参考[muduo WeakCallback](https://github.com/chenshuo/muduo/blob/cpp17/muduo/base/WeakCallback.h)
50-
27. [Server](/Server)——linux server的一些例子;
48+
25. [SafeCallback](/SafeCallback/safecallback.hpp)——生命周期安全的回调函数的实现,参考[muduo WeakCallback](https://github.com/chenshuo/muduo/blob/cpp17/muduo/base/WeakCallback.h)
49+
26. [Server](/Server)——linux server的一些例子;
5150
1. [server_epoll](/Server/server_epoll.cc)——epoll的例子;
5251
2. [server_poll](/Server/server_poll.cc)——poll的例子;
5352
3. [server_select](/Server/server_select.cc)——select的例子;
53+
27. [SpinMutex](/SpinMutex)——使用std::atomic_flag实现的简单互斥锁和自旋锁;
5454
28. [Thread](/Thread/)——基于std::thread实现的线程类,包括线程池;
5555
1. [Thread](/Thread/thread.hpp)——线程类;
5656
2. [ThreadPool](/Thread/threadpool.hpp)——线程池;

SpinMutex/CMakeLists.txt

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
add_executable(spinmutex_unittest spinmutex_unittest.cc spinmutex.hpp)
2+
target_link_libraries(spinmutex_unittest PRIVATE GTest::gtest GTest::gtest_main
3+
GTest::gmock GTest::gmock_main)
4+
add_test(NAME spinmutex_unittest COMMAND spinmutex_unittest)
5+
6+
if(CMAKE_HOST_UNIX)
7+
target_link_libraries(spinmutex_unittest PRIVATE pthread)
8+
endif()

SpinMutex/spinmutex.hpp

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#pragma once
2+
3+
#include <utils/object.hpp>
4+
5+
#include <atomic>
6+
#include <cassert>
7+
#include <iostream>
8+
#include <thread>
9+
10+
class SpinMutex : noncopyable
11+
{
12+
public:
13+
SpinMutex() { m_atomic_flag.clear(std::memory_order_release); }
14+
15+
~SpinMutex()
16+
{
17+
if (m_atomic_flag.test_and_set(std::memory_order_acquire)) {
18+
assert(false && "SpinLock destroyed while locked!");
19+
std::cerr << "Error: SpinLock destroyed while locked!" << std::endl;
20+
}
21+
m_atomic_flag.clear(std::memory_order_release);
22+
}
23+
24+
void lock()
25+
{
26+
while (m_atomic_flag.test_and_set(std::memory_order_acquire)) {
27+
std::this_thread::yield(); // 有这一行,就是自旋锁;没有这一行,就是互斥锁(忙等待)
28+
}
29+
}
30+
31+
void unlock() { m_atomic_flag.clear(std::memory_order_release); }
32+
33+
private:
34+
std::atomic_flag m_atomic_flag;
35+
};
36+
37+
class SpinMutexLocker : noncopyable
38+
{
39+
SpinMutex *m_mutex = nullptr;
40+
41+
public:
42+
SpinMutexLocker(SpinMutex *mutex)
43+
: m_mutex(mutex)
44+
{
45+
assert(m_mutex);
46+
m_mutex->lock();
47+
}
48+
49+
~SpinMutexLocker()
50+
{
51+
assert(m_mutex);
52+
m_mutex->unlock();
53+
}
54+
};

SpinMutex/spinmutex_unittest.cc

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#include "spinmutex.hpp"
2+
3+
#include <gtest/gtest.h>
4+
5+
TEST(SpinMutexTest, MultiThreadIncrement)
6+
{
7+
SpinMutex mutex;
8+
std::vector<std::thread> threads;
9+
int counter = 0;
10+
11+
for (int i = 0; i < 10; ++i) {
12+
threads.emplace_back([&] {
13+
SpinMutexLocker locker(&mutex);
14+
for (int j = 0; j < 1000; ++j) {
15+
++counter;
16+
}
17+
});
18+
}
19+
20+
for (auto &thread : threads) {
21+
thread.join();
22+
}
23+
24+
EXPECT_EQ(counter, 10000);
25+
}
26+
27+
TEST(SpinMutexTest, DestructionWhileLocked)
28+
{
29+
SpinMutex *mutex = new SpinMutex;
30+
mutex->lock();
31+
ASSERT_THROW({ delete mutex; }, std::logic_error);
32+
}
33+
34+
TEST(SpinMutexTest, ExceptionSafety)
35+
{
36+
SpinMutex mutex;
37+
bool threw = false;
38+
39+
try {
40+
mutex.lock();
41+
throw std::runtime_error("Simulated exception");
42+
mutex.unlock();
43+
} catch (...) {
44+
threw = true;
45+
}
46+
47+
mutex.lock();
48+
mutex.unlock();
49+
EXPECT_TRUE(threw);
50+
}
51+
52+
int main(int argc, char **argv)
53+
{
54+
::testing::InitGoogleTest(&argc, argv);
55+
return RUN_ALL_TESTS();
56+
}

0 commit comments

Comments
 (0)