程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 一種簡單的跨平台互斥鎖

一種簡單的跨平台互斥鎖

編輯:C++入門知識

前言  
   互斥鎖,用來保證任一時刻只有單個線程或進程擁有對共享資源的互斥訪問權,在這裡將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 }

 

作者:春秋十二月

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved