# DSL/thread design question

**URL:** <https://www.ruby-forum.com/t/dsl-thread-design-question/144222>\
**Category:** Ruby\
**Created:** [July 26, 2008, 11:00pm UTC](https://www.ruby-forum.com/t/dsl-thread-design-question/144222 "2008-07-26T23:00:03Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![dgm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/df788c/32.png) [@dgm](https://www.ruby-forum.com/u/dgm)\
**Post date:** [July 26, 2008, 11:00pm UTC](https://www.ruby-forum.com/t/dsl-thread-design-question/144222/1 "2008-07-26T23:00:03Z")

</div>

I am writing something which I am calling “suits” for now – the idea  
being “something you make with threads”. It’s a lightweight actor model.  
Works something like this:

s = Suit.new([])  
s.push(1,2,3,4,5) # asynchronous, so ignoring the return  
value  
s[2].now # returns 3  
s.length.then{|l| puts l} # prints 5, at some point  
s.join # reap the thread

The idea is simple: Map Ruby’s object model onto the actor model.  
(Actually, I  
didn’t know I was doing actors until I found Revactor – I just knew it  
was  
vaguely Erlang-inspired.) Therefore, an actor simply looks and feels  
like an  
object, and message-passing is done through Ruby method calls (which are  
sort  
of message passing anyway).

My motivation is to at least make multithreaded Ruby an attractive  
option, so  
that there is a motivation to remove the Python-esque Global Interpreter  
Lock. I don’t believe separate Unix processes will scale well enough.

There are a few design issues, and I think I’m out of my league here.

Three problems:

First, while I like the syntax of “now” vs “then”, it does require some  
discipline if you were expecting this to behave like the object it’s  
referring to. It also means I can’t drop a Suit-wrapped object into  
something  
expecting the original.

But making things asynchronous by default would force developers to be  
aware  
of how synchronous (or not) they’re actually being.

So, should this be synchronous by default? (Right now, it’s not.) Maybe  
I  
should return a “promise” instead, so that things are asynchronous until  
you  
actually need information out of the returned value.

Second, for asynchronous calls, since I’m using a Queue, things arrive  
in-order. Would there be an advantage to not requiring that behavior?  
Intuitively, I think there would be times when random delivery would be  
an  
asset, but I can’t justify it. About the only reason for attempting  
random  
delivery would be to force the programmer to think about multiple  
threads  
sending messages simultaneously.

And finally, what about exception handling? Right now, exceptions will  
be  
delivered on #join, but that requires explicitly checking for them. The  
thing  
that I love about exceptions in a single-threaded app is that unless you  
do  
something special, the exception kills your program. I would much prefer  
the  
behavior to be similar to that, rather than trying to return an  
exception.

I kind of like how exception handling is done in Erlang, in which  
one “process” (think: actor) is responsible for handling the errors of  
another. But I’m not sure what the simplest way of doing that in Ruby  
would  
be.

---

<div class="post-metadata">

**Author:** ![dgm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/df788c/32.png) [@dgm](https://www.ruby-forum.com/u/dgm)\
**Post date:** [July 27, 2008, 12:17am UTC](https://www.ruby-forum.com/t/dsl-thread-design-question/144222/2 "2008-07-27T00:17:19Z")

</div>

> I am writing something which I am calling “suits” for now – the idea  
> being “something you make with threads”. It’s a lightweight  
> actor model.

You might want to look at dramatis: [http://dramatis.mischance.net/](http://dramatis.mischance.net/)

Of course, I’m biased, but I did create it out of actor-envy towards  
Erlang.

> s = Suit.new([])

s = Dramatis::Actor.new( [] ) =\> Dramatis::Actor::Name === s

in dramatis.

> s.push(1,2,3,4,5) # asynchronous, so ignoring the  
> return value

release( s ).push(1,2,3,4,5) =\> nil

> s[2].now # returns 3

s[2] =\> 3

> s.length.then{|l| puts l} # prints 5, at some point

This rather ungainly syntax:  
( interface( s ).continue { |l| puts l } ).length =\> puts 5  
or, in the next release, slightly better:  
( continuation( s ) { |l| puts l } ).length =\> puts 5

> s.join # reap the thread

There’s no equivalent for this right now … among other things, each  
actor  
doesn’t have a unique thread; they’re shared as necessary. But there  
should  
probably be a way for actors to exit a la Erlang’s exit … or is GC  
enough?  
I’m a little unsure on this.

> My motivation is to at least make multithreaded Ruby an  
> attractive option, so  
> that there is a motivation to remove the Python-esque Global  
> Interpreter

JRuby doesn’t have a GIL. But my results of using threads on JRuby are  
still  
a little strange (but it may be my fault).  
(By the way, dramatis also runs on python and some of the examples run  
on  
jython but I haven’t run the full suite of tests on jython yet).

> So, should this be synchronous by default? (Right now, it’s  
> not.)

In my past work with actors, making things async by default was painful  
(but, then, I didn’t have lambdas, which help). I haven’t made async  
the  
default in dramatis: I prefer to start from something close to serial  
and  
incrementally expose concurrency. But it is possible to code to get it  
async  
by default, for example:

s = Dramatis::Actor.new( [] )  
s = release( s )

would make all subsequent calls on s async by default. The proxy object  
maintains the type of continuation that will be used when calls are made  
against that proxy.

> Maybe I  
> should return a “promise” instead, so that things are  
> asynchronous until you  
> actually need information out of the returned value.

Dramatis has futures, though they’re experimental (actually, all of  
dramatis  
is, they’re just _more_ experimental.)

In my limited tests, each kind of continuation has uses for which it is  
more  
natural than the alternatives.

> Second, for asynchronous calls, since I’m using a Queue,  
> things arrive  
> in-order.

Yeah; you’re relying on that in your example. Otherwise, you can’t  
guarantee  
that the #push has executed before the #[] runs.

> Would there be an advantage to not requiring that behavior?

It generally works out the other way: often people want guaranteed  
ordered  
queuing, at least among messages sent between the same pairs of actors  
(so  
things like your example work). But while this is easy in a single  
process,  
it’s more difficult when you’re exchanging messages over the network.

Writing code that can’t rely on ordering can get tricky (think of what  
you’d  
have to do to your simple example).

Dramatis has selective receive (though implemented differently than  
Erlang)  
which helps loosen the need for in-order delivery in some contexts.

> And finally, what about exception handling?

Right now, dramatis tries to deliver exceptions to the caller where it  
can,  
e.g., on blocking/rpc-style calls. I’m really not sure this is a good  
idea,  
though it’s been helpful in my toy examples. This isn’t what Erlang  
does,  
where you need to catch the exception explicitly and send it to the  
caller;  
otherwise uncaught exceptions kill the actor (Erlang process).

Erlang really sets the bar for this: while one may not completely love  
the  
way they’ve implemented things, they have large systems that perform  
reliability. Their linked actors is a hugely valuable feature. If you  
made  
every actor linked by default, then you’d get the behavior you want,  
where  
killing an actor killed the program (unless they took measure to stop  
that.)

Dramatis doesn’t have this yet but I sure wish it did and hopefully it  
will  
…

---

<div class="post-metadata">

**Author:** ![dgm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/df788c/32.png) [@dgm](https://www.ruby-forum.com/u/dgm)\
**Post date:** [July 27, 2008, 3:52am UTC](https://www.ruby-forum.com/t/dsl-thread-design-question/144222/3 "2008-07-27T03:52:40Z")

</div>

> From: David M. [[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)]

> Keep in mind, I don’t care about implementation at this  
> point, but design.

Well, we’re together on that, though, of course, peoples’ opinion of  
design  
differs.

> (I find Erlang ugly.)

Beyond that, it’s predominantly functional, not object-oriented, and not  
used widely for general purpose development. I could get over the syntax  
but  
…

> > release( s ).push(1,2,3,4,5) =\> nil
> 
> What does “release” do, in this context? And why not make it  
> a method on the  
> wrapped object?

It generates a new name that when used to call methods, calls the  
methods  
asynchronously/with a null continuation.

s.push is a sync/rpc-style call, release( s ).push is async.

release does this by returning a new name with different continuation  
semantics. It’s all encapsulated within the name.

I didn’t make it a method because I didn’t want it to always have to be  
there, i.e., I wanted to be able to use  
s.push in the simple case (as opposed to s.sync.push and s.async.push).

With that constraint, I didn’t want to make it a method because it  
impinges  
on the namespace of the serial behavior of the actor, i.e., if sync is  
the  
default, and you have to say s.async to get async, you can’t (easily)  
use an  
#async method on the actor itself.

It’s important to me that there be no methods on the proxy that are  
aimed at  
the proxy rather than what the proxy points at.

> I would much rather use GC, if it would work. I’m not sure  
> how to make GC work  
> here, though – and certainly not for one thread/actor.

Yeah: you could have a problem with the thread-per-actor because it  
might  
not be clear when the actor is not actually doing anything (it can’t be  
GC’d  
while its doing something)?

But GC is hard when you move to distributed anyway: distributed GC is  
hard,  
which might be reason enough to bag it. I haven’t gone there yet.

> However, Java threads are probably heavier than YARV threads.  
> Just a guess.

Actually, if I had to guess, I’d guess the opposite. They’re both kernel  
scheduled threads and there’s a heck of a lot more experience with  
threads  
in Java than there is in 1.9.

> I do want to know how “async by default” was painful, though.

In my code, sync calls, for example for status, were fairly common.  
Requiring all those to have something explicit to make sync work was  
painful. Taking a trivial call like “other.status” and exploding it to  
lots  
more characters or multiple lines gets old fast. In my eyes, anyway.

I really want code that looks serial to do the right serial thing, even  
if  
the objects are actors. So far, this works in dramatis.

If you’re doing sync calls w/o an explicit receive, you might want to  
look  
at Erlang/OTP’s gen\_server behaviour: it does that (and raises the  
selective  
receive issues).

> s.push(…).now  
> s[…]

Yup; just using a sync call even if you don’t need the value is common  
and  
valid way of generating the necessary control flow.

Brings up selective receive again, though. Can the calling actor receive  
any  
other messages while it’s waiting for #now? That’s one of the trickier  
things to handle in actor programs.

> Well, I think the problem with this is, what happens to  
> anyone else who wants  
> to send something to the actor? Is the actor still in a valid  
> state after  
> this?

If the exception is delivered to the caller, the actor remains in a fine  
state. It’s pretty much what Erlang does if you manually catch the  
exception  
and forward it. But given the wide variety of exceptions that can occur,  
maybe sending the exception up is a poor default. And you can’t do it in  
the  
async case, anyway, so …

But this introduces a big difference between serial and actor code even  
in  
the rpc case, which I don’t like.

So I don’t know …

I\> In single-threaded code, it’s easy – it’s up to the caller.

Right. There’s no ambiguity. No choice. Here there’s a choice. As soon  
as  
you have multiple actors, you have multiple stacks and in theory you can  
send the exception up either. I have cases where both are useful but I  
don’t  
have anyway of making the runtime figure out the right way to handle  
things  
except making it explicit.

> That brings up other interesting problems – how do you  
> handle the main  
> thread?

There are two parts to this. Any thread that the runtime didn’t create  
is  
considered external/exogenous and in order to fit it into the actor  
model, a  
pseudo-actor is created for it if necessary (when, for example, it needs  
to  
accept the response from an rpc-like call).

The other issue unique to main is keeping it from exiting when there is  
actor work to be done. I use an at\_exit handler for that.

> And how are we catching this, then? A method, maybe – something like  
> linked\_process\_died?

Something similar to that. More likely I’ll provide a method that takes  
a  
block: if you want to catch an exception signal (using Erlang  
terminology),  
the actor calls this method with the block that it wants to get the  
signal.  
That block will be called when the signal is received, in which case the  
recipient won’t be killed. This is more or less what Erlang does (I  
forget  
the BIF you call to do this.)

This is getting pretty deep into the guts. I started a list a few weeks  
ago  
for people discussing actor issues across languages/implementations:  
[http://groups.google.com/group/actor-talk](http://groups.google.com/group/actor-talk). Would it make more sense to  
do  
this there? There’s also a list for dramatis  
([http://groups.google.com/group/dramatis](http://groups.google.com/group/dramatis)) but if you just want to  
compare,  
actor-talk is probably better.

---

<div class="post-metadata">

**Author:** ![dgm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/df788c/32.png) [@dgm](https://www.ruby-forum.com/u/dgm)\
**Post date:** [July 27, 2008, 4:35am UTC](https://www.ruby-forum.com/t/dsl-thread-design-question/144222/4 "2008-07-27T04:35:20Z")

</div>

On Saturday 26 July 2008 20:43:37 Steven P. wrote:

> > From: David M. [[mailto:removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)]
> 
> > Keep in mind, I don’t care about implementation at this  
> > point, but design.
> 
> Well, we’re together on that, though, of course, peoples’ opinion of design  
> differs.

That’s part of why I posted. (The other reason is to try to figure out  
the  
exception handling.)

> > > release( s ).push(1,2,3,4,5) =\> nil
> > 
> > What does “release” do, in this context? And why not make it  
> > a method on the  
> > wrapped object?

[snip]

> I didn’t make it a method because I didn’t want it to always have to be  
> there, i.e., I wanted to be able to use  
> s.push in the simple case (as opposed to s.sync.push and s.async.push).

I was thinking it would be easier to be able to do s.sync.push (or  
s.async.push), and still have the semantics you want, as in:

released\_s = s.release  
released\_s.push(…)

In fact, that’s part of where my syntax came from – the object returned  
from  
every method call is a “ReturnPath” object, which can then be used to  
control  
what happens after the call. That’s why I have things like this:

s.length.now

What I’m thinking now is that I should be returning futures instead, so  
that I  
keep the asynchronous-by-default behavior, but no extra effort is needed  
to  
use things synchronously.

The one danger here is (again) exception handling. If something goes  
wrong, I  
don’t know when I actually make the method call, I know when I check the  
future – and one of the appeals of the design is that if I don’t check  
the  
future, it’s a blind call.

> With that constraint, I didn’t want to make it a method because it impinges  
> on the namespace of the serial behavior of the actor, i.e., if sync is the  
> default, and you have to say s.async to get async, you can’t (easily) use an  
> #async method on the actor itself.

Very early on, I realized I was going to end up doing this. I’d much  
rather  
pollute the actor’s namespace than the kernel namespace, and there are  
two  
assumptions being made here: First, that most actors will be  
specifically  
written for that purpose, and second, that there would be some sort of  
standard override – some #actor\_send method.

So far, though, I haven’t actually modified the real objects, only the  
proxy.

> > I would much rather use GC, if it would work. I’m not sure  
> > how to make GC work  
> > here, though – and certainly not for one thread/actor.
> 
> Yeah: you could have a problem with the thread-per-actor because it might  
> not be clear when the actor is not actually doing anything (it can’t be GC’d  
> while its doing something)?

Well, I would love for Ruby to GC them on their own.

> > I do want to know how “async by default” was painful, though.  
> > [snip]  
> > I really want code that looks serial to do the right serial thing, even if  
> > the objects are actors. So far, this works in dramatis.

I agree.

But I also want parallel code to not only be easy to write, I want it to  
be as  
natural as serial code.

> Brings up selective receive again, though. Can the calling actor receive any  
> other messages while it’s waiting for #now?

In short, no. The implementation is absurdly simple – I believe it’s  
something like 100 lines of code and 200 lines of specs.

So, that said, here’s some relevant code:

class Suit  
def initialize obj  
…  
@thread = Thread.new do  
loop do  
message = queue.pop  
break if message.nil?  
message.call object  
end  
end  
end

The messages sent are actually blocks. Specifically:

def thread\_eval &block  
queue \<\< block  
end

And, predictably, the main usage is:

def method\_missing \*arguments, &block  
ReturnPath.new.tap do |path|  
thread\_eval do |obj|  
path.value = obj.public\_send(\*arguments, &block)  
end  
end  
end

So, in short, nothing can happen in that thread outside the loop. The  
loop  
will block calling that method on the object (indirectly). So if the  
method  
itself ever blocks, the entire thread is blocked.

Messages can be sent while this happens, but they will be queued.

This was, in fact, the whole point – from beginning to end of the  
method  
call, nothing else may interfere. Within the object itself, there is no  
concurrency, and you don’t have to think about concurrency.

> But this introduces a big difference between serial and actor code even in  
> the rpc case, which I don’t like.  
> [snip]  
> I\> In single-threaded code, it’s easy – it’s up to the caller.
> 
> Right. There’s no ambiguity. No choice. Here there’s a choice. As soon as  
> you have multiple actors, you have multiple stacks and in theory you can  
> send the exception up either. I have cases where both are useful but I don’t  
> have anyway of making the runtime figure out the right way to handle things  
> except making it explicit.

I see it as more a semantic problem – I started this because I like  
working  
with sequential Ruby, and I want to keep most of the semantics of that.  
But  
concurrency does require at least thinking in a different way…

> > And how are we catching this, then? A method, maybe – something like  
> > linked\_process\_died?
> 
> Something similar to that. More likely I’ll provide a method that takes a  
> block: if you want to catch an exception signal (using Erlang terminology),  
> the actor calls this method with the block that it wants to get the signal.  
> That block will be called when the signal is received, in which case the  
> recipient won’t be killed. This is more or less what Erlang does (I forget  
> the BIF you call to do this.)

I can see that – one advantage is, no pollution of the actor’s own  
namespace.

In what context would it run?

> This is getting pretty deep into the guts. I started a list a few weeks ago  
> for people discussing actor issues across languages/implementations:  
> [http://groups.google.com/group/actor-talk](http://groups.google.com/group/actor-talk). Would it make more sense to do  
> this there? There’s also a list for dramatis  
> ([http://groups.google.com/group/dramatis](http://groups.google.com/group/dramatis)) but if you just want to compare,  
> actor-talk is probably better.

I want to compare, at first, and learn. Dramatis looks more complete,  
but I  
like my syntax better (hey, I’m biased) – ultimately, I’d rather not  
have  
duplicate code. (Unless I dig deeper and find myself hating yours, in  
which  
case, it’s on! :P)

I am specifically interested in doing this in Ruby, so I don’t think  
it’s  
entirely offtopic for ruby-talk, either.

---

<div class="post-metadata">

**Author:** ![dgm](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/df788c/32.png) [@dgm](https://www.ruby-forum.com/u/dgm)\
**Post date:** [July 27, 2008, 2:37am UTC](https://www.ruby-forum.com/t/dsl-thread-design-question/144222/5 "2008-07-27T02:37:43Z")

</div>

On Saturday 26 July 2008 17:10:24 Steven P. wrote:

> > I am writing something which I am calling “suits” for now – the idea  
> > being “something you make with threads”. It’s a lightweight  
> > actor model.
> 
> You might want to look at dramatis: [http://dramatis.mischance.net/](http://dramatis.mischance.net/)

Haven’t seen that; I’ll take a more in-depth look later.

Keep in mind, I don’t care about implementation at this point, but  
design. The  
whole reason I’m using Ruby instead of Erlang for this is beautiful  
syntax.  
(I find Erlang ugly.)

That’s why, for example, I’m using one thread per actor – it’s simpler  
to  
write right now (no need to worry about blocking operations…) and the  
interface shouldn’t change much later, if I have to switch to a  
threadpool.

> > s.push(1,2,3,4,5) # asynchronous, so ignoring the  
> > return value
> 
> release( s ).push(1,2,3,4,5) =\> nil

What does “release” do, in this context? And why not make it a method on  
the  
wrapped object?

> > s.join # reap the thread
> 
> There’s no equivalent for this right now … among other things, each actor  
> doesn’t have a unique thread; they’re shared as necessary. But there should  
> probably be a way for actors to exit a la Erlang’s exit … or is GC enough?  
> I’m a little unsure on this.

I would much rather use GC, if it would work. I’m not sure how to make  
GC work  
here, though – and certainly not for one thread/actor.

> > My motivation is to at least make multithreaded Ruby an  
> > attractive option, so  
> > that there is a motivation to remove the Python-esque Global  
> > Interpreter
> 
> JRuby doesn’t have a GIL. But my results of using threads on JRuby are still  
> a little strange (but it may be my fault).

However, Java threads are probably heavier than YARV threads. Just a  
guess.

Right now, Suits only work on Ruby 1.9 – though I’d like to port to  
1.8,  
there were some problems with those threads. I don’t remember what they  
were,  
though.

> > So, should this be synchronous by default? (Right now, it’s  
> > not.)
> 
> In my past work with actors, making things async by default was painful  
> (but, then, I didn’t have lambdas, which help). I haven’t made async the  
> default in dramatis: I prefer to start from something close to serial and  
> incrementally expose concurrency.

One of the more powerful features of Erlang, I thought, was how easy it  
made  
concurrency – how it was almost a natural feature. So I’m still torn.

I do want to know how “async by default” was painful, though.

> > Second, for asynchronous calls, since I’m using a Queue,  
> > things arrive  
> > in-order.
> 
> Yeah; you’re relying on that in your example. Otherwise, you can’t guarantee  
> that the #push has executed before the #[] runs.

True. What I’m wondering is if it would be better to call

s.push(…).now  
s[…]

> > And finally, what about exception handling?
> 
> Right now, dramatis tries to deliver exceptions to the caller where it can,  
> e.g., on blocking/rpc-style calls. I’m really not sure this is a good idea,

Well, I think the problem with this is, what happens to anyone else who  
wants  
to send something to the actor? Is the actor still in a valid state  
after  
this?

In single-threaded code, it’s easy – it’s up to the caller. If the  
caller  
decides they can handle the exception, they can handle repairing the  
internal  
state of the callee, if that has to happen – or they can drop the  
object and  
let it be collected. If the caller can’t do that, we don’t have to worry  
about anyone else sending a message, because the program’s likely about  
to  
implode.

But with an actor, anyone else might be sending messages at the same  
time. We  
might have to distinguish, then, between a transient error (which would  
simply notify whoever needs to be notified, probably whoever sent the  
message  
which caused it) and a fatal error (which kills that actor).

> If you made  
> every actor linked by default, then you’d get the behavior you want, where  
> killing an actor killed the program (unless they took measure to stop that.)

That brings up other interesting problems – how do you handle the main  
thread?

And how are we catching this, then? A method, maybe – something like  
linked\_process\_died?

The trick is, I want both – I want something that works well for  
one-off  
examples, and something that works well for large clusters of  
independent  
nodes.
