前言
互斥鎖,用來保證任一時刻只有單個線程或進程擁有對共享資源的互斥訪問權,在這裡將posix thread中的互斥體、win32中的互斥體和臨界區,統稱為互斥鎖,其特點如下
● 范圍:線程鎖和進程鎖,前者僅用於同一進程內多線程間,而後者用於進程間,顯然,它也能用於同一進程內多線程間,但效率較低。posix的互斥體既可以是線程鎖,也可以是進程鎖,這由它的一個屬性決定:pthread_process_shared或pthread_process_private。win32中的臨界區是一種線程鎖,而互斥體既可以是線程鎖,也可以是進程鎖,這由它的一個名稱決定:createmutex中的第3個參數。
● 類型:posix中的互斥體,包括普通鎖、遞歸鎖、檢測鎖和適應鎖四種;而win32中的臨界區在同一線程內可多次加鎖和解鎖,相當於遞歸鎖,而互斥體則相當於普通鎖。
● 操作:包括創建鎖、加鎖、解鎖、檢測鎖和銷毀鎖5種操作,其中加鎖操作又可分為永久等待和超時等待2種。對於win32中的臨界區,不存在超時等待的加鎖。
接口
所有鎖操作,成功返回0,失敗posix返回非0的錯誤碼,win32返回-1,調用getlasterror可獲取錯誤碼。對於超時加鎖,第2個參數超時不是時間差,而是絕對到期時間。對於win32中的互斥體,廢棄返回1,超時返回2。
1 #ifdef __cplusplus
2 extern "C" {
3 #endif
4
5 #ifdef _POSIX_THREAD
6 #include <pthread.h>
7 #include <sys/time.h>
8
9 typedef pthread_mutex_t mutex_t;
10 typedef pthread_mutexattr_t mutexattr_t;
11 typedef void SECURITY_ATTRIBUTES;
12
13 #elif defined(_WIN32_THREAD)
14 #ifndef _WIN32_WINNT
15 # define _WIN32_WINNT 0x0501
16 #endif
17 #include <winsock2.h>
18
19 typedef struct
20 {
21 int type_;
22 union
23 {
24 HANDLE proc_lock_;
25 CRITICAL_SECTION thr_lock_;
26 };
27 }mutex_t;
28 typedef void mutexattr_t;
29
30 #else
31 #error Currently only support win32 and posix thread models
32 #endif
33
34 #define MUTEX_THREAD_SHARED 1
35 #define MUTEX_PROCESS_SHARED 2
36
37 int mutex_init(mutex_t* m,int scope,int type,const char* name,mutexattr_t* attr,SECURITY_ATTRIBUTES* sa);
38
39 int mutex_lock(mutex_t* m);
40
41 int mutex_timedlock(mutex_t* m,const struct timeval* val);
42
43 int mutex_trylock(mutex_t* m);
44
45 int mutex_unlock(mutex_t* m);
46
47 int mutex_destroy(mutex_t* m);
48
49 #ifdef __cplusplus
50 }
51 #endif
實現
1 int mutex_init(mutex_t* m,int scope,int type,const char* name,mutexattr_t* attr,SECURITY_ATTRIBUTES* sa)
2 {
3 #ifdef _POSIX_THREAD
4 int ret, init = 0;
5 pthread_mutexattr_t tmp;
6 if(0==attr) attr = &tmp;
7 if(attr==&tmp)
8 {
9 ret = pthread_mutexattr_init(attr);
10 if (0==ret) init = 1;
11 }
12 if(0==ret && 0 != scope)
13 {
14 #ifdef _POSIX_THREAD_PROCESS_SHARED
15 ret = pthread_mutexattr_setpshared(attr,lock_scope);
16 #endif
17 }
18 if(0==ret && 0 != type)
19 {
20 #ifdef __USE_UNIX98
21 ret = pthread_mutexattr_settype(attr,lock_type);
22 #endif
23 }
24 if (0==ret)
25 ret = pthread_mutex_init(m,attr);
26 if (1==init && attr==&tmp)
27 pthread_mutexattr_destroy(attr);
28 return ret;
29 #else
30 m->type_ = scope;
31 switch (m->type_)
32 {
33 case MUTEX_THREAD_SHARED:
34 __try
35 {
36 InitializeCriticalSection(&m->thr_lock_);
37 }
38 __except(EXCEPTION_EXECUTE_HANDLER)
39 {
40 return -1;
41 }
42 return 0;
43
44 case MUTEX_PROCESS_SHARED:
45 m->proc_lock_ = CreateMutexA(sa,FALSE,name);
46 if (0==m->proc_lock_&&ERROR_ACCESS_DENIED==GetLastError())
47 m->proc_lock_ = OpenMutexA(MUTEX_ALL_ACCESS,FALSE,name);
48 if (0==m->proc_lock_)
49 return -1;
50 return 0;
51
52 default: return -1;
53 }
54 #endif
55 }
56
57 int mutex_lock(mutex_t* m)
58 {
59 #ifdef _POSIX_THREAD
60 return pthread_mutex_lock(m);
61 #else
62 switch(m->type_)
63 {
64 case MUTEX_THREAD_SHARED:
65 EnterCriticalSection(&m->thr_lock_);
66 return 0;
67
68 case MUTEX_PROCESS_SHARED:
69 switch (WaitForSingleObject (m->proc_lock_, INFINITE))
70 {
71 case WAIT_OBJECT_0: return 0;
72 case WAIT_ABANDONED: return 1;
73 default: return -1;
74 }
75 break;
76
77 default: return -1;
78 }
79 #endif
80 }
81
82 int mutex_timedlock(mutex_t* m,const struct timeval* val)
83 {
84 //val should be an absolute time.
85 #ifdef _POSIX_THREAD
86 struct timespec ts = {.tv_sec = val->tv_sec,.tv_nsec=val->tv_usec*1000};
87 return pthread_mutex_timedlock(m,&ts);
88 #else
89 switch(m->type_)
90 {
91 // not support CriticalSection,so simply return -1.
92 case MUTEX_THREAD_SHARED:
93 return -1;
94
95 case MUTEX_PROCESS_SHARED:
96 {
97 FILETIME ft;
98 struct timeval cur,diff;
99
100 GetSystemTimeAsFileTime(&ft);
101 cur = FileTime2TimeVal(&ft);
102 diff = timeval_sub(val,&cur);
103
104 switch (WaitForSingleObject (m->proc_lock_, timeval_millsec(&diff)))
105 {
106 case WAIT_OBJECT_0: return 0;
107 case WAIT_ABANDONED: return 1;
108 case WAIT_TIMEOUT: return 2;
109 default: return -1;
110 }
111 }
112 break;
113
114 default: return -1;
115 }
116 #endif
117 }
118
119 int mutex_trylock(mutex_t* m)
120 {
121 #ifdef _POSIX_THREAD
122 return pthread_mutex_trylock(m);
123 #else
124 switch(m->type_)
125 {
126 case MUTEX_THREAD_SHARED:
127 if (!TryEnterCriticalSection(&m->thr_lock_))
128 return -1;
129 return 0;
130
131 case MUTEX_PROCESS_SHARED:
132 switch (WaitForSingleObject (m->proc_lock_, 0))
133 {
134 case WAIT_OBJECT_0: return 0;
135 case WAIT_ABANDONED: return 1;
136 case WAIT_TIMEOUT: return 2;
137 default: return -1;
138 }
139 break;
140
141 default: return -1;
142 }
143 #endif
144 }
145
146 int mutex_unlock(mutex_t* m)
147 {
148 #ifdef _POSIX_THREAD
149 return pthread_mutex_unlock(m);
150 #else
151 switch(m->type_)
152 {
153 case MUTEX_THREAD_SHARED:
154 LeaveCriticalSection(&m->thr_lock_);
155 return 0;
156
157 case MUTEX_PROCESS_SHARED:
158 if (!ReleaseMutex(m->proc_lock_))
159 return -1;
160 return 0;
161
162 default: return -1;
163 }
164 #endif
165 }
166www.2cto.com
167 int mutex_destroy(mutex_t* m)
168 {
169 #ifdef _POSIX_THREAD
170 return pthread_mutex_destroy(m);
171 #else
172 switch(m->type_)
173 {
174 case MUTEX_THREAD_SHARED:
175 DeleteCriticalSection(&m->thr_lock_);
176 return 0;
177
178 case MUTEX_PROCESS_SHARED:
179 if (!CloseHandle(m->proc_lock_))
180 return -1;
181 return 0;
182
183 default: return -1;
184 }
185 #endif
186 }
作者:春秋十二月