2012-01-18 44 views
9

Có thực hiện Haskell MVar nào trong C không? Có một example về cách triển khai nó trong C++. Nhưng, tôi sẽ muốn thực hiện nó trong C - chúng ta hãy nói rằng chỉ có MVar CInt tương đương trong C cho bây giờ. Viết nguyên gốc đồng bộ hóa có thể phức tạp. Vì vậy, tôi sẽ muốn tránh trùng lặp nỗ lực nếu ai đó đã thực hiện nó. Tôi không hiểu ví dụ C++ ở trên cũng đủ để tự tin dịch nó thành C - nó ẩn các chi tiết thuật toán rất tốt từ C++ của tôi - tâm thiếu kinh nghiệm :)Thực hiện MVar trong C?

Lý do tôi nghĩ về viết MVar trong C là vì nó làm cho việc sử dụng FFI ràng buộc với thư viện C bên ngoài để lấy luồng dữ liệu và sử dụng các chủ đề Haskell để lấy dữ liệu (từ vectơ Storable để tránh marshaling dữ liệu - MVar CInt ở đây lưu trữ bao nhiêu Storable vectơ đã được lấp đầy). Tôi cần đảm bảo rằng các luồng C ghi vào các vị trí đáng yêu bị chặn trong khi luồng Haskell đang đọc dữ liệu. Đó là nơi đồng bộ MVar trên mặt C giúp. Nó cũng nhanh hơn nhiều khi gọi hàm C không an toàn hoặc thậm chí an toàn từ Haskell (~ 15ns cho không an toàn, ~ 150ns cho an toàn trong thử nghiệm của tôi), hơn gọi lại vào Haskell từ C (~ 5us). Nếu callbacks nhanh, tôi sẽ có chức năng C gọi lại vào Haskell thay vào đó, và chặn Haskell MVar.

Cập nhật:

Thuật toán trong pseudo-code sẽ làm tốt. Nó sẽ được khá dễ dàng để thực hiện nó trong C, cho các thuật toán cho newEmptyMVar, takeMVar và putMVar.

+1

Đối với những người không quen thuộc với 'MVar' của Haskell, hãy xem: [Control.Concurrent.MVar] (http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Concurrent-MVar. html) –

+0

Tôi không thể giúp bạn với câu hỏi của bạn, nhưng nơi mà bạn đã nhận được thời gian cho các cuộc gọi nước ngoài giữa Haskell và C. Hôm qua, tôi đã lang thang như thế nào để chuẩn mực đó bằng cách sử dụng tiêu chí. – jmg

+0

@jmg, mã ở đây (cho haskell-> C): http://hpaste.org/56609. Không có tiêu chuẩn điểm chuẩn ở đó nhưng nên được khá đơn giản để làm, và kết quả nên được khá gần. Đối với C-> Haskell gọi lại, xem mã trong bài đăng này: http://stackoverflow.com/questions/8902568/runtime-performance-degradation-for-c-ffi-callback-when-pthreads-are-enabled – Sal

Trả lời

3

MVAr có thể được thực hiện trong C sử dụng một cấu trúc như dưới đây:

typedef struct{ 
    pthread_cond_t put_cond; 
    pthread_cond_t take_cond; 
    pthread_mutex_t lock; 
    void* value; 
} mvar; 

put_cond được sử dụng bởi chủ đề đó đặt giá trị trong MVAr để báo hiệu đề khác đang chờ đợi để lấy giá trị từ MVAr. take_cond là đối tác tương tự để lấy. Đối với lịch trình, nó là lịch trình mặc định.

value là con trỏ trống - vì vậy, cấu trúc ở trên có thể được sử dụng để bảo vệ bất kỳ loại giá trị nào trong MVar - tất nhiên, C sẽ cho phép bạn viết con trỏ đó bên ngoài MVar - vì vậy, đó là trách nhiệm của chương trình điều này không xảy ra (bằng cách tránh squirreling đi value con trỏ bên ngoài MVar - luôn luôn truy cập nó thông qua các chức năng MVar).

Khởi 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; 
} 

Rỗng MVar - sử dụng trên chức năng:

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 
} 

Mã hoàn chỉnh nằm trên github, với example hiển thị cách sử dụng MVar.

MV là khá nhanh nếu chỉ có một chủ đề truy cập vào nó (và tranh chấp nặng). Nhưng, dưới ganh đua nặng nề, và nhiều chủ đề (thậm chí hai), nó vảy rất kém.Đây không phải là một bất ngờ vì cách làm việc pthreads. Tôi đã tìm thấy MVar trong Haskell rất tốt với nhiều chủ đề. Đây không phải là một sự ngạc nhiên khi các chủ đề trọng lượng nhẹ và các nguyên tắc đồng thời được thực hiện trong GHC.

0

Mã trong ví dụ không phải là rất C++ - cụ thể. Các bit thiết yếu chính xác là pthread -fragments.