一种简单的跨平台互斥锁
前言
互斥锁,用来保证任一时刻只有单个线程或进程拥有对共享资源的互斥访问权,在这里将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 {
补充:软件开发 , C++ ,