Neo's Blog

不抽象就无法深入思考
不还原就看不到本来面目!

0%

操作系统-自己实现mutex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <windows.h>
#include <intrin.h>

class Benaphore
{
private:
LONG m_counter;
HANDLE m_semaphore;

public:
Benaphore()
{
m_counter = 0;
m_semaphore = CreateSemaphore(NULL, 0, 1, NULL);
}

~Benaphore()
{
CloseHandle(m_semaphore);
}

void Lock()
{
if (_InterlockedIncrement(&m_counter) > 1) // x86/64 guarantees acquire semantics
{
WaitForSingleObject(m_semaphore, INFINITE);
}
}

void Unlock()
{
if (_InterlockedDecrement(&m_counter) > 0) // x86/64 guarantees release semantics
{
ReleaseSemaphore(m_semaphore, 1, NULL);
}
}
};

If you port this code to another CPU architecture, such as that in the Xbox 360 or a multicore iOS device, you’ll have to replace the _InterlockedIncrement macro with something which explicitly guarantees acquire and release semantics.

支持递归的互斥锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Define this to {} in a retail build:
#define LIGHT_ASSERT(x) { if (!(x)) DebugBreak(); }

class RecursiveBenaphore
{
private:
LONG m_counter;
DWORD m_owner;
DWORD m_recursion;
HANDLE m_semaphore;

public:
RecursiveBenaphore::RecursiveBenaphore()
{
m_counter = 0;
m_owner = 0; // an invalid thread ID
m_recursion = 0;
m_semaphore = CreateSemaphore(NULL, 0, 1, NULL);
}

RecursiveBenaphore::~RecursiveBenaphore()
{
CloseHandle(m_semaphore);
}

void Lock()
{
DWORD tid = GetCurrentThreadId();
if (_InterlockedIncrement(&m_counter) > 1) // x86/64 guarantees acquire semantics
// x86 和 x64 上,_InterlockedIncrement调用会生成一条lock xadd指令,该指令充当完整的内存屏障,保证获取和释放语义
//此属性是 x86/64 独有的
{
if (tid != m_owner)
WaitForSingleObject(m_semaphore, INFINITE);
}
//--- We are now inside the Lock ---
m_owner = tid;
m_recursion++;
}

void Unlock()
{
DWORD tid = GetCurrentThreadId();
LIGHT_ASSERT(tid == m_owner);
DWORD recur = --m_recursion;
if (recur == 0)
m_owner = 0; //先设置为0,再去_InterlockedDecrement
DWORD result = _InterlockedDecrement(&m_counter); // x86/64 guarantees release semantics
if (result > 0)
{
if (recur == 0)
ReleaseSemaphore(m_semaphore, 1, NULL);
}
//--- We are now outside the Lock ---
}

bool TryLock()
{
DWORD tid = GetCurrentThreadId();
if (m_owner == tid)
{
// Already inside the lock
_InterlockedIncrement(&m_counter);
}
else
{
LONG result = _InterlockedCompareExchange(&m_counter, 1, 0);
if (result != 0)
return false;
//--- We are now inside the Lock ---
m_owner = tid;
}
m_recursion++;
return true;
}
};
你的支持是我坚持的最大动力!