MVARは、以下のような構造体を使用して、Cで実装することができる。
typedef struct{
pthread_cond_t put_cond;
pthread_cond_t take_cond;
pthread_mutex_t lock;
void* value;
} mvar;
put_cond
はMVARの値を取るのを待っている他のスレッドを通知するMVARの値を入れスレッドによって使用されています。 take_cond
はtakeの類似のものです。スケジューリングに関しては、デフォルトのスケジューリングです。
value
は無効なポインタなので、上記の構造はMVarの任意のタイプの値を保護するために使用できます - もちろん、CはMVarの外にそのポインタを書き込めるようになります。これは起こりません(value
ポインタをMVarの外側に移動しないでください - 常にMVar関数を通してアクセスしてください)。
初期MVar
:
mvar* newMVar(void* arg){
//create new mvar struct
mvar* var=(mvar*) malloc(sizeof(mvar));
pthread_mutex_init(&var->lock,NULL);
pthread_cond_init(&var->take_cond,NULL);
pthread_cond_init(&var->put_cond,NULL);
var->value = arg;
return (mvar*) var;
}
空MVar
- 機能上記の使用:
mvar* newEmptyMVar(){
return newMVar(NULL);
}
putMVar
:
void putMVar(mvar* var,void* value){
pthread_mutex_lock(&var->lock);
while(var->value != NULL)
pthread_cond_wait(&var->put_cond,&var->lock);//if MVar is full, wait until another thread takes the value - release the mutex, and wait on put_cond to become true
var->value = value;//if here, we got the signal from another thread that took MVar - MVar is empty now. OK to fill
pthread_cond_signal(&var->take_cond);//signal other threads that value is available for taking now
pthread_mutex_unlock(&var->lock);
}
takeMVar
:
void* takeMVar(mvar* var){
void* value;
pthread_mutex_lock(&var->lock);
while(var->value == NULL)
pthread_cond_wait(&var->take_cond,&var->lock);//if MVar is empty, wait until another thread fills it - release the mutex, and wait on take_cond to become true
//take the value
value = var->value;
var->value = NULL; //push NULL value to indicate MVar is empty now
pthread_cond_signal(&var->put_cond);//signal other threads that value is available for filling now
pthread_mutex_unlock(&var->lock);
return value; //return the value that was taken from MVar
}
完全コードはgithubで、exampleはMVarの使い方を示しています。
MVarは、それにアクセスするスレッドが1つしかない場合(および重い競合の場合)は非常に高速です。しかし、重い競合や複数のスレッド(2つでも)の下では、非常にうまく調整できません。これは、pthreadsの仕組みのために驚くことではありません。私はHaskellのMVarが複数のスレッドで非常に優れていることを発見しました。これはGHCで軽量スレッドと同時実行プリミティブがどの程度うまく実装されているかを考えると驚くことではありません。
出典
2012-01-20 13:13:51
Sal
ハスケルの 'MVar'に慣れていない人は、[Control.Concurrent.MVar](http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Concurrent-MVar)を参照してください。 html) –
私はあなたの質問であなたを助けることはできませんが、どこでHaskellとCの間の外貨呼出しの時間を得ましたか。昨日、私は基準を使用してそれをベンチマークする方法をさまよっていました。 – jmg
@jmg、コードはこちら(haskell-> C):http://hpaste.org/56609。そこではベンチマークを行う基準はありませんが、実行するのは非常に簡単で、結果はかなり近いはずです。 C-> Haskellコールバックについては、この記事のコードを参照してください:http://stackoverflow.com/questions/8902568/runtime-performance-degradation-for-c-ffi-callback-when-pthreads-are-enabled – Sal