Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Zig Mailbox is convenient inter-thread communication mechanizm.

License

NotificationsYou must be signed in to change notification settings

g41797/mailbox

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mailbox - old new way of inter-thread communication.

CI   

A bit of history, a bit of theory

Mailboxes are one of the fundamental parts of theactor model originated in1973:

An actor is an object that carries out its actions in response to communications it receives.Through the mailbox mechanism, actors can decouple the reception of a message from its elaboration.A mailbox is nothing more than the data structure (FIFO) that holds messages.

I first encountered MailBox in the late 80s while working on a real-time system:

"Amailbox is object that can be used for inter-taskcommunication. When task A wants to send an object to task B, task Amust send the object to the mailbox, and task B must visit the mailbox,where, if an object isn't there, it has the option ofwaiting for anydesired length of time..."iRMX 86™ NUCLEUS REFERENCE MANUAL _Copyright @ 1980, 1981 Intel Corporation.

Since than I have used it in:

OSLanguage(s)
iRMXPL/M-86
AIXC
WindowsC++/C#
LinuxGo

Now it's Zig time!!!

Why?

If your thread runs in "Fire and Forget" mode, you don't need Mailbox.

But in real multithreaded applications, threads communicate with each other asmembers of a work team.

Mailbox provides a convenient and simple inter-thread communication:

  • thread safe
  • asynchronous
  • non-blocking
  • cancelable
  • no own allocations
  • unbounded
  • fan-out/fan-in

Example of usage - 'Echo'

// Mbx is Mailbox with usize letter(data)constMbx=mailbox.MailBox(usize);// Echo - runs on own thread// It has two mailboxes// "TO" and "FROM" - from the client point of the view// Receives letter via 'TO' mailbox// Replies letter without change (echo) to "FROM" mailboxconstEcho=struct {constSelf=@This();to:Mbx=undefined,from:Mbx=undefined,thread:Thread=undefined,// Mailboxes creation and start of the thread// Pay attention, that client code does not use// any thread "API" - all embedded within Echopubfnstart(echo:*Self)void {echo.to= .{};echo.from= .{};echo.thread=std.Thread.spawn(.{},run, .{echo})catchunreachable;        }// Echo thread functionfnrun(echo:*Self)void {// Main loop:while (true) {// Receive - exit from the thread if mailbox was closedconstenvelope=echo.to.receive(100000000)catchbreak;// Reply to the client// Exit from the thread if mailbox was closed_=echo.from.send(envelope)catchbreak;            }        }// Wait exit from the threadpubfnwaitFinish(echo:*Self)void {echo.thread.join();        }// Close mailboxes// As result Echo should stop processing// and exit from the thread.pubfnstop(echo:*Self)!void {_=echo.to.close();_=echo.from.close();        }    };varecho=trystd.testing.allocator.create(Echo);// Start Echo(on own thread)echo.start();deferecho.stop();defer {// Wait finish of Echoecho.waitFinish();std.testing.allocator.destroy(echo);    }// because nothing was send to 'TO' mailbox, nothing should be received// from 'FROM' mailboxtrytesting.expectError(error.Timeout,echo.from.receive(100));// Create wrapper for the dataconstenvl=trystd.testing.allocator.create(Mbx.Envelope);deferstd.testing.allocator.destroy(envl);// Send/Receive loopfor (0..6)|indx| {// Set value for send [0-5]envl.letter=indx;// Send to 'TO' mailboxtryecho.to.send(envl);// Wait received data from OUT mailboxconstback=echo.from.receive(1000000);if (back)|val| {// Expected value == index [0-5]trytesting.expect(val.letter==indx);        }else|_| {trytesting.expect(false);        }    }

Boring details

Mailbox of[]const u8 'Letters':

constRumors=mailbox.MailBox([]constu8);constrmrsMbx :Rumors= .{};

Envelope is a wrapper of actual user defined typeLetter.

pubconstEnvelope=struct {prev:?*Envelope=null,next:?*Envelope=null,letter:Letter,        };

In fact Mailbox is a queue(FIFO) of Envelope(s).

MailBox supports following operations:

  • sendEnvelope to MailBox (enqueue) and wakeup waiting receiver(s)
  • receiveEnvelope from Mailbox (dequeue) with time-out
  • close Mailbox:
    • disables further operations
    • first close returns List of non-processedEnvelope(s) for free/reuse etc.

Feel free to suggest improvements in doc and code.

License

MIT

Installation

You finally got to installation!

Submodules

Create folder'deps' under'src' and mailbox submodule:

mkdif src/deps        git submodule add https://github.com/g41797/mailbox src/deps/mailbox

Import mailbox:

constmailbox=@import("deps/mailbox/src/mailbox.zig");

Use mailbox:

constMsgBlock=struct {len:usize=undefined,buff: [1024]u8=undefined,};constMsgs=mailbox.MailBox(MsgBlock);varmsgs:Msgs= .{};..................._=msgs.close();

Periodically update submodule(s):

git submodule update --remote

Package Manager

With an existing Zig project, adding Mailbox to it is easy:

  1. Add mailbox to yourbuild.zig.zon
  2. Add mailbox to yourbuild.zig

To add mailbox tobuild.zig.zon simply run the following in your terminal:

cd my-example-projectzig fetch --save=mailbox git+https://github.com/g41797/mailbox

and in yourbuild.zig.zon you should find a new dependency like:

.{    .name="My example project",    .version="0.0.1",    .dependencies= .{        .mailbox= .{            .url="git+https://github.com/g41797/mailbox#3f794f34f5d859e7090c608da998f3b8856f8329",            .hash="122068e7811ec1bfc2a81c9250078dd5dafa9dca4eb3f1910191ba060585526f03fe",        },    },    .paths= .{"",    },}

Then, in yourbuild.zig'sbuild function, add the following beforeb.installArtifact(exe):

constmailbox=b.dependency("mailbox", .{        .target=target,        .optimize=optimize,    });exe.root_module.addImport("mailbox",mailbox.module("mailbox"));

From then on, you can use the Mailbox package in your project.

Last warning

First rule of multithreading:

If you can do without multithreading - do without.


Powered byclion


[8]ページ先頭

©2009-2025 Movatter.jp