# DSL/thread design question

**URL:** <https://rubytalk.org/t/dsl-thread-design-question/47949>\
**Category:** ruby-talk\
**Created:** [26 July 2008 20:53 UTC](https://rubytalk.org/t/dsl-thread-design-question/47949 "2008-07-26T20:53:16Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![David\_Masover](https://avatars.discourse-cdn.com/v4/letter/d/50afbb/32.png) [@David\_Masover](https://rubytalk.org/u/David_Masover)\
**Post date:** [26 July 2008 20:53 UTC](https://rubytalk.org/t/dsl-thread-design-question/47949/1 "2008-07-26T20:53:16Z")

</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:** ![Steven\_Parkes](https://avatars.discourse-cdn.com/v4/letter/s/6de8d8/32.png) [@Steven\_Parkes](https://rubytalk.org/u/Steven_Parkes)\
**Post date:** [26 July 2008 22:10 UTC](https://rubytalk.org/t/dsl-thread-design-question/47949/2 "2008-07-26T22:10:18Z")

</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()

&nbsp;&nbsp;s = Dramatis::Actor.new( ) =\> Dramatis::Actor::Name === s

in dramatis.

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

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

> s[2].now # returns 3

&nbsp;&nbsp;s[2] =\> 3

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

This rather ungainly syntax:  
&nbsp;&nbsp;( interface( s ).continue { |l| puts l } ).length =\> puts 5  
or, in the next release, slightly better:  
&nbsp;&nbsp;( 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:

&nbsp;&nbsp;s = Dramatis::Actor.new( )  
&nbsp;&nbsp;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:** ![David\_Masover](https://avatars.discourse-cdn.com/v4/letter/d/50afbb/32.png) [@David\_Masover](https://rubytalk.org/u/David_Masover)\
**Post date:** [27 July 2008 00:31 UTC](https://rubytalk.org/t/dsl-thread-design-question/47949/3 "2008-07-27T00:31:15Z")

</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/)

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
> 
> &nbsp;&nbsp;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.

> **···**
>
> On Saturday 26 July 2008 17:10:24 Steven Parkes wrote:

---

<div class="post-metadata">

**Author:** ![Steven\_Parkes](https://avatars.discourse-cdn.com/v4/letter/s/6de8d8/32.png) [@Steven\_Parkes](https://rubytalk.org/u/Steven_Parkes)\
**Post date:** [27 July 2008 01:43 UTC](https://rubytalk.org/t/dsl-thread-design-question/47949/4 "2008-07-27T01:43:37Z")

</div>

> From: David Masover [mailto:ninja@slaphack.com]

> 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 ....

> 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%5C). 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%5C)) but if you just want to compare,  
actor-talk is probably better.

---

<div class="post-metadata">

**Author:** ![David\_Masover](https://avatars.discourse-cdn.com/v4/letter/d/50afbb/32.png) [@David\_Masover](https://rubytalk.org/u/David_Masover)\
**Post date:** [27 July 2008 02:28 UTC](https://rubytalk.org/t/dsl-thread-design-question/47949/5 "2008-07-27T02:28:27Z")

</div>

> \> From: David Masover [mailto:ninja@slaphack.com]
> 
> \> 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  
&nbsp;&nbsp;def initialize obj  
&nbsp;&nbsp;&nbsp;&nbsp;...  
&nbsp;&nbsp;&nbsp;&nbsp;@thread = Thread.new do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message = queue.pop  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break if message.nil?  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message.call object  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end

The messages sent are actually blocks. Specifically:

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

And, predictably, the main usage is:

def method\_missing \*arguments, &block  
&nbsp;&nbsp;&nbsp;&nbsp;ReturnPath.new.tap do |path|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread\_eval do |obj|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;path.value = obj.public\_send(\*arguments, &block)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;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]

> \> 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%5C). 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%5C)) 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.

> **···**
>
> On Saturday 26 July 2008 20:43:37 Steven Parkes wrote:
