一種簡單的跨平臺訊號量
● 訊號量擁有一個計數值,表示可用的資源數量,僅當該值為0或1時,則相當於互斥鎖。
● 訊號量是條件式加鎖,即僅當計數值不大於0時才會鎖住當前執行緒或程序,而互斥鎖則是無條件。
● 訊號量的加鎖和解鎖不必是同一執行緒或程序,而互斥鎖則必須是同一個。
● 任何執行緒或程序都可以掛出一個訊號,即使當前沒有執行緒或程序正在等待該訊號值變成正數,而互斥鎖在沒有加鎖後解鎖則會發生錯誤。
本文展示了基於Posix、PThread、SystemV和Win32四種平臺的封裝實現。
介面
所有訊號量操作,成功返回0,失敗返回-1,對應的錯誤碼,win32可呼叫getlasterror獲取,其它平臺則是errno。對於win32平臺的wait和trywait操作,廢棄返回1,超時返回2;因當前沒有獲取訊號值的API,sema_getvalue操作簡單地返回-1。 1
2#include <semaphore.h> 3typedef struct 4{
5 union
6 {
7 sem_t* proc_sem_;
8 sem_t thr_sem_;
9 };
10 char* name_;
11} sema_t;
12
13typedef void SECURITY_ATTRIBUTES;
14
15#elif defined(_SYSV_SEM)16typedef struct17{
18 int id_;
20}sema_t;
21
22typedef void SECURITY_ATTRIBUTES;
23
24#elif defined(_PTHREAD_SEM)25#include <pthread.h>26typedef struct27{
28 pthread_cond_t cond_;
29 pthread_mutex_t lock_;
30 int value_;
31}sem_t;
32
33typedef struct34{
35 union {
36 sem_t* proc_sem_;
38 };
39 char* name_;
40}sema_t;
41
42typedef void SECURITY_ATTRIBUTES;
43
44#elif defined(_WIN32_SEM)45#include <windows.h>46typedef HANDLE sema_t;
47
48#else49#error Currently only support posix,system v,pthread and win32 semaphore.50#endif51
52int sema_init(sema_t* s,constchar* name,unsigned int value,unsigned int max,SECURITY_ATTRIBUTES* sa);
53
54int sema_wait(sema_t* s);
55
56int sema_trywait(sema_t* s);
57
58int sema_post(sema_t* s);
59
60int sema_getvalue(sema_t*s,int* val);
61
62int sema_destroy(sema_t* s);
實現
1int sema_init(sema_t* s,constchar* name,unsigned int value,unsigned int max,SECURITY_ATTRIBUTES* sa)
2{
3#ifdef _POSIX_SEM
4 if(name){
5 s->name_ = strdup(name);
6 if(0==s->name_)
7 return-1;
8 s->proc_sem_ = sem_open(name,O_CREAT,DEFAULT_FILE_PERMS,value);
9 if(SEM_FAILED==s->proc_sem_) {
10 free(s->name_);
11 return-1;
12 } 13 }else{
14 if(-1==sem_init(&s->thr_sem_,0,value))
15 return-1;
16 s->name_ =0;
17 } 18 return0;
19#elif defined(_SYSV_SEM) 20 if(name){
21 s->name_ = strdup(name);
22 if(0==s->name_)
23 return-1;
24 if(-1==__sysv_sem_open(&s->id_,name,value)){
25 free(s->name_);
26 return-1;
27 } 28 return0;
29 }else{
30 if(-1==__sysv_init(&s->id_,value))
31 return-1;
32 s->name_ =0;
33 } 34 return0;
35#elif defined(_PTHREAD_SEM) 36 if(name){
37 s->name_ = strdup(name);
38 if(0==s->name_)
39 return-1;
40 s->proc_sem_ = __pthread_sem_open(name,value);
41 if(0==s->proc_sem_){
42 free(s->name_);
43 return-1;
44 } 45 }else{
46 if(-1==__pthread_init(&s->thr_sem_,value))
47 return-1;
48 s->name_ =0;
49 } 50 return0;
51#else 52 return (*s = CreateSemaphoreA(sa,value,max,name)) ?0 : -1;
53#endif 54} 55
56int sema_wait(sema_t* s)
57{
58#ifdef _POSIX_SEM
59 sem_t* sem = s->name_ ? s->proc_sem_ : &s->thr_sem_;
60 return sem_wait(sem);
61#elif defined(_SYSV_SEM) 62 struct sembuf op;
63 int ret;
64 op.sem_num =0;
65 op.sem_op =-1;
66 op.sem_flg =0;
67 return semop(s->id_, &op, 1);
68#elif defined(_PTHREAD_SEM) 69 sem_t* sem = s->name_ ?
相關推薦
一種簡單的跨平臺訊號量
訊號量是一種用於併發環境同步手段的原語,分為無名訊號量和有名訊號量兩種,前者只能用於執行緒間同步,而後者還可用於程序間同步。它包括建立、等待、掛出、取值和銷燬5種基本操作。與互斥鎖不同的是: ● 訊號量擁有一個計數值,表示可用的資源數量,僅當該值為0或1時,則相當於互斥鎖。
一種簡單的跨平臺使用者態自旋鎖
自旋鎖作為一種併發同步的手段,特別適用於競爭少和鎖時間短的情況,在驅動及核心程式碼中經常被用到,本文講述一種適合使用者態程式的自旋鎖,支援Windows和Linux(GCC>=4.1.2)平臺,並提供了C語言的介面和實現。 介面 spin_trylock如果獲取成功返回1,否
一種簡單的跨平臺互斥鎖
互斥鎖,用來保證任一時刻只有單個執行緒或程序擁有對共享資源的互斥訪問權,在這裡將posix thread中的互斥體、win32中的互斥體和臨界區,統稱為互斥鎖,其特點如下: ● 範圍:執行緒鎖和程序鎖,前者僅用於同一程序內多執行緒間,而後者用於程序間,顯然,它也能用於同一程序內多執行緒間
一種簡單的跨平臺套接字管道
{ 49 SOCKET client = INVALID_SOCKET,server=INVALID_SOCKET; 50 struct addrinfo addr,*res = NULL; 51 constchar* address; 52 int opt =1; 53 54
一種簡單,輕量,靈活的C#物件轉Json物件的方案
簡單,是因為只有一個類 輕量,是因為整個類程式碼只有300行 靈活,是因為擴充套件方式只需要繼承重寫某個方法即可 首先我將這個類稱之為JsonBuilder,我希望它以StringBuilder的方式來實現Json字串的轉換 public class JsonBu
一種簡單的hook方法--LD_PRELOAD變量
返回結果 其他 深入 分系統 nebula style 就是 evel 動態鏈接 LD_PRELOAD這個變量允許你定義在程序運行時優先加載的動態鏈接庫,從而在程序運行時的動態鏈接 下面程序的看一個例子-getuid.c //getuid.c #include<s
一種簡單的加解密算法
coder 額外 lai hack crypt decrypt pro simple 無需 此算法源碼最初由 Borland 的 Delphi 語言編寫,似乎 Allen Bauer 是原作者,源碼如下。 const cMulKey = 52845; cA
SpringBank 開發日誌 一種簡單的攔截器設計實現
exp bst 一個 pin factory span 之前 system request 當交易由Action進入Service之前,需要根據不同的Service實際負責業務的不同,真正執行Service的業務邏輯之前,做一些檢查工作。這樣的攔截器應該是基於配置的,與Se
一種簡單的生產環境部署Node.js程序方法
set process 一次 ann 來安 環境配置 load 修改 evel 最近在部署Node.js程序時,寫了段簡單的腳本,發覺還挺簡單的,忍不住想與大家分享。 配置文件 首先,本地測試環境和生產環境的數據庫連接這些配置信息是不一樣的,需要將其分開為兩個文件存儲
一種簡單的對象賦值方法,定義實例後以{}賦值,比傳統方法更簡潔
method ott static set num arr nbsp st2 () public class Rectangle { public Point TopLeft { get; set; } public Point Botto
一種簡單的圖像修復方法
col nes gb2 tle .com splay 產生 end left 該方法可以用於美顏中的祛斑,通過快速叠代的方式去除斑點。 假設輸入圖像為: 計算方向權重: 對於其他方向,操作類似We。 最終的輸出為: 對要修復的區域,反復進行同樣的操作即可。 簡單
php生成excel的另一種簡單方法
.com com span 來看 nbsp pan blog table content 之前我用table的方式寫過excel,還用php-excel這個類庫寫過excel。今天,我再向大家推薦一個超級簡單的寫excel的方法。 代碼: $xstr = "問題id\t問
java安全性的一種簡單思路
授權 安全 時間格式 判斷 第三方接口 對比 當前時間 服務 格式 關於接口安全性的考慮。這客戶端在調用接口時,將acId授權碼以加密的方式(可逆加密方式)傳遞過來, 服務端這邊接收後進行解密,然後在服務器端這邊的授權名單中進行匹配,判斷該授權碼是否被授權,從而判斷第三方調
數獨問題的一種簡單演算法程式碼實現
五一期間無聊時想起去年考研複試有一道上機題目當時沒作出來,於是一時興起想重新拾起看看是當時太緊張,還是自己能力不足。然後發現這道題目還真稍微有些難度,相當於一道數獨問題(sudoku)的簡化版。自己想來想去也只能想到兩種演算法,一種是拿剩餘元素做全排列測試,一種是回溯法測試。最後只實現了一個全排
關於ASP.NET MVC 5 的一種簡單的身份驗證方式:FormsAuthentication.Authenticate
在ASP.NET MVC 5中,身份驗證分別有三種方式。分別為使用FormsAuthentication、MemberShip和Identity進行驗證。 (PS:本系列的邏輯程式碼請勿直接用於生產,請自己多加一層抽象後再投入使用) 為了展示這三種方式,我們先新建一個MVC
Python單例的一種簡單寫法
this args self. name 創建方式 方法 沒有 easily 獲取 最原始的想法就是每個類都重寫new方法。 class Dog: dog = None def __new__(cls, *args, **kwargs):
判斷中文文字編碼格式是gbk還是utf-8的一種簡單方式
import java.io.*; public class charsetTest { public static String charsetType(String fileName) throws IOException { BufferedReader reader =
LCG(linear congruential generator): 一種簡單的隨機數生成演算法
目錄 LCG演算法 python 實現 LCG演算法 LCG(linear congruential generator)線性同餘演算法,是一個古老的產生隨機數的演算法。由以下引數組成: 引數 m a c X
LCG(linear congruential generator): 一種簡單的隨機數生成算法
ble 優點 line 寫入 head 速度 body generator 上一個 目錄 LCG算法 python 實現 LCG算法 LCG(linear congruential generator)線性同余算法,是一個古老的產生隨機數的算法。由以下參數組成:
什麼是REST——適合初學者的一種簡單解釋,第一部分:介紹
原文地址:https://medium.com/extend/what-is-rest-a-simple-explanation-for-beginners-part-1-introduction-b4a072f8740f 這篇文章是解釋REST基本概念的兩篇文章中的第一篇。 閱讀