2008-09-02 26 views
10

Thực ra, câu hỏi này dường như có hai phần:Làm cách nào bạn triển khai Erlang giống như gửi và nhận trong C++?

  • Làm cách nào để thực hiện khớp mẫu?
  • Cách triển khai send and receive (ví dụ: mô hình diễn viên)?

Đối với phần khớp mẫu, tôi đã xem xét các dự án khác nhau như AppProp. Chúng trông khá đẹp, nhưng không thể khiến chúng hoạt động trên phiên bản gần đây (4.x) của g ++. Ngôn ngữ Felix cũng dường như hỗ trợ mẫu phù hợp khá tốt, nhưng không thực sự là C++.

Đối với Actor model, có hiện thực hiện như ACT ++ và Theron, nhưng tôi không thể tìm thấy bất cứ điều gì nhưng giấy tờ về cựu , và sau này là đơn luồng chỉ [xem câu trả lời].

Cá nhân, tôi đã triển khai các diễn viên sử dụng luồng và hàng đợi tin nhắn an toàn. Các thông báo là các cấu trúc giống như băm và sử dụng chúng cùng với một số macro tiền xử lý để thực hiện khớp mẫu đơn giản.

Ngay bây giờ, tôi có thể sử dụng đoạn mã sau để gửi một thông điệp:

(new Message(this)) 
    ->set("foo", "bar") 
    ->set("baz", 123) 
    ->send(recipient); 

Và sau đây để làm mô hình đơn giản phù hợp với (qDebugqPrintable là Qt cụ thể):

receive_and_match(m) 
    match_key("foo") { qDebug("foo: %s", qPrintable(m->value("foo").toString())); } 
    or_match_key("baz") { qDebug("baz: %d", m->value("baz").toInt()); } 
    or_match_ignore 
end_receive 

Tuy nhiên, điều này trông hơi khó hiểu với tôi, và không phải là rất mạnh mẽ.

Bạn sẽ làm như thế nào? Tôi đã bỏ lỡ bất kỳ công việc hiện có?

Trả lời

4

Một trong những điều quan trọng về erlang là cách các tính năng được sử dụng để tạo hệ thống mạnh mẽ.

Mô hình gửi/nhận không chia sẻ và sao chép rõ ràng. Các quy trình là các luồng nhẹ.

Nếu bạn đã mong muốn các đặc tính mạnh mẽ của mô hình erlang, bạn nên sử dụng các quy trình thực và IPC thay vì các luồng.

Nếu bạn muốn gửi thư mạnh mẽ mặc dù bạn có thể muốn tuần tự hóa và deserialise nội dung. Đặc biệt với loại an toàn.

Đối sánh mẫu trong C++ không phải lúc nào cũng đẹp nhưng sẽ có mẫu tốt cho việc này - bạn sẽ kết thúc việc tạo đối tượng điều phối sử dụng một dạng đa hình để có được thứ bạn muốn.

Mặc dù nếu bạn không cẩn thận bạn kết thúc với xml qua ống :)

Thực sự, nếu bạn muốn mô hình erlang bạn thực sự muốn sử dụng erlang. Nếu có các bit chậm, tôi chắc chắn bạn có thể tăng cường chương trình của bạn bằng cách sử dụng một internet chức năng nước ngoài.

Vấn đề về việc triển khai lại các bộ phận, là bạn sẽ không nhận được thư viện và giải pháp gắn kết tốt. Các giải pháp bạn đã không nhìn giống như C++ nữa.

11

Đối với các mô hình diễn viên, có hiện thực hiện như ACT ++ và Theron, nhưng tôi không thể tìm thấy bất cứ điều gì nhưng giấy tờ về cựu, và sau này là đơn luồng duy nhất.

Là tác giả của Theron, tôi đã tò mò tại sao bạn cho rằng đó là một luồng đơn?

diễn viên Cá nhân, tôi đã thực hiện sử dụng luồng và một hàng đợi nhắn thread-safe

Đó là cách Theron được thực hiện .. :-)

Ash

+0

Thành thật mà nói, tôi không biết tại sao tôi đoán Theron là đơn luồng. Đọc lại trang web không cho tôi ấn tượng đó. Lời xin lỗi của tôi cho sự nhầm lẫn, và tôi nghĩ rằng nó sẽ là công bằng nếu tôi cho Theron một shot! –

+0

Đã có một kinh nghiệm hạnh phúc khi sử dụng Theron cho Actors concurrency trong các tệp Matlab mex. – Chinasaur

4

tôi Hiện tại, tôi đang triển khai thư viện diễn viên cho C++ có tên là "acedia" (chưa có gì về nó trên google) sử dụng "type matching". Thư viện là một dự án cho luận văn thạc sĩ của tôi và bạn có thể gửi bất kỳ loại dữ liệu nào cho một diễn viên với nó.

Một đoạn nhỏ:

recipient.send(23, 12.23f); 

Và ở phía người nhận bạn có thể phân tích được thông báo nhận được như thế này:

Message msg = receive(); 
if (msg.match<int, float>() { ... } 

... hoặc bạn có thể định nghĩa một tập quy tắc đó gọi một chức năng hoặc phương pháp cho bạn:

void doSomething(int, float); 

InvokeRuleSet irs; 
irs.add(on<int, float>() >> doSomething); 
receiveAndInvoke(irs); 

Cũng có thể đối sánh cả về loại và giá trị:

Message msg = receive(); 
if (msg.match<int, float>(42, WILDCARD) { ... } 
else if (msg.match<int, float>() { ... } 

Hằng số "WILDCARD" có nghĩa là mọi giá trị sẽ được chấp nhận. Vượt qua không có đối số nào bằng nhau đặt tất cả các đối số thành "WILDCARD"; có nghĩa là bạn chỉ muốn khớp các loại.

Đây chắc chắn là một đoạn mã nhỏ. Ngoài ra, bạn có thể sử dụng "trường hợp các lớp học" như trong Scala. Chúng có thể so sánh với "nguyên tử" trong erlang. Dưới đây là một ví dụ chi tiết hơn:

ACEDIA_DECLARE_CASE_CLASS(ShutdownMessage) 
ACEDIA_DECLARE_CASE_CLASS(Event1) 
ACEDIA_DECLARE_CASE_CLASS(Event2) 

Để phản ứng với các lớp trường hợp được xác định bạn có thể viết một diễn viên như thế này:

class SomeActor : public Actor 
{ 

    void shutdown() { done = true; } 
    void handleEvent1(); 
    void handleEvent1(); 

    public: 

    SomeActor() : done(false) { } 

    virtual void act() 
    { 
     InvokeRuleSet irs; 
     irs 
     .add(on<ShutdownMessage>() >> method(&SomeActor::shutdown)) 
     .add(on<Event1>() >> method(&SomeActor::handleEvent1)) 
     .add(on<Event2>() >> method(&SomeActor::handleEvent2)) 
     ; 
     while (!done) receiveAndInvoke(irs); 
    } 

}; 

Để tạo một diễn viên mới và bắt đầu nó, tất cả các bạn phải viết là:

Acedia::spawn<SomeActor>(); 

Mặc dù thư viện thậm chí không đạt đến sân vận động beta đoạn trích hiển thị và tôi có ứng dụng đầu tiên chạy trên đó. Một mục tiêu chính của thư viện là hỗ trợ lập trình phân tán (cũng trên một mạng).

Câu hỏi của bạn cách đây một thời gian, nhưng nếu bạn quan tâm đến nó: hãy cho tôi biết! :)

+0

Tôi chắc chắn quan tâm; nó trông khá đẹp. Có một trang web nơi tôi có thể tải xuống thư viện/xem tài liệu không? Bạn sẽ mở tìm nguồn cung ứng nó? –

0

Tôi chắc chắn sẽ quan tâm đến việc xem thư viện "acedia" của bạn và muốn giúp đỡ bằng mọi cách có thể. Erlang có một số cấu trúc tuyệt vời và C++ chắc chắn có thể hưởng lợi từ một thư viện như vậy.

0

Hôm nay tôi hostet thư viện tại SourceForge: https://sourceforge.net/projects/acedia/

Như tôi đã nói trước khi nó được thả sớm. Nhưng cảm thấy tự do để phê bình nó!

+0

Tôi đã tải xuống và tôi sẽ dùng thử ngay khi có cơ hội. –

+1

Cập nhật: acedia đã lỗi thời, thanh toán libcppa thay thế: [https://sourceforge.net/projects/acedia/](https://github.com/neverlord/libcppa) – neverlord

2

Bạn có thể bắt chước hành vi bằng cách sử dụng cơ chế tín hiệu/khe của Qt, đặc biệt là khi tín hiệu/khe của Qt hỗ trợ đa luồng.

0

Hôm nay, nếu bạn muốn diễn viên mạnh mẽ phong cách erlang trong C++ và đối sánh mẫu, có thể Rust là câu trả lời.

Tất nhiên điều này không được công khai khi OP hỏi ~ 5 năm trước, và tính đến tháng 4 năm 2014 nó vẫn chưa được v1.0 - nhưng nó đang tiến triển rất tốt và chắc chắn là ổn định, đủ ngôn ngữ cốt lõi là ổn định tôi nghĩ.

Và ok nó không phải C++, nhưng nó có cách tiếp cận tương tự như quản lý bộ nhớ như C++, ngoại trừ nó hỗ trợ các tác vụ nhẹ không có bộ nhớ chia sẻ theo mặc định (sau đó cung cấp các tính năng thư viện được điều khiển để chia sẻ - "Arc"); Nó có thể gọi trực tiếp (và trực tiếp phơi bày) các chức năng 'extern C'. Bạn không thể chia sẻ tiêu đề thư viện templated với C++ - nhưng bạn có thể viết generics mà bắt chước các lớp thu C++ (và vica versa) để chuyển tham chiếu đến các cấu trúc dữ liệu trên.

Các vấn đề liên quan