There's more to it than I can really describe here, but in effect it allows you to treat a thread as an object with methods; calling a method on the object sends a message to the thread. The thread's main code can, at any point, block and wait for a message, or combination of messages.
The handling code looks like this:
...some code...
accept DoSomething(value: in out integer) do
...some code here...
end
...some more code...
That causes the thread to block and wait for the message. When the message is sent, the caller blocks, the receiver runs the handler, then the caller resumes.The beauty here is that inside the message handler, you know that the caller is blocked... which means it's safe to pass parameters by pointer[]. Everywhere the parameter's in scope, the parameter is safe to use. The type system won't let the thread store the pointer anywhere without copying the contents first, so you get zero-copy messaging and* it's failsafe.
You can also do really cool stuff with timeouts, guards, automatic thread termination, etc. Here's a simple multithreaded queue (syntax and logic not guaranteed, it's been a while):
loop
select
when usage < capacity =>
accept Push(value: in integer) do
data[usage] := value;
usage := usage + 1;
end;
or
when usage > 0 =>
accept Pop(value: out integer) do
usage := usage - 1;
value := data[usage];
end;
or
terminate;
end select;
end loop;
Multithreaded! Blocks the client automatically if they pop while the queue's empty or push while it's full! Automatically terminates the thread when the last connection goes away and the thread leaves scope! Thread safe! Readable!I'd love to be able to do this in a more mainstream language.
[*] This is a simplification. Ada's pointers are not like other language's pointers.