On Sun, Aug 28, 2011 at 5:04 PM, Mathieu Bouchard
<matju@artengine.ca> wrote:
On Sun, 28 Aug 2011, Peter Brinkmann wrote:
One major simplification is the use of built-in data types vs custom structs and unions.
You mean you simplify by making things more low-level ?
const char * is rarely ever called high-level...
Well, I'm taking a complicated implementation detail (t_symbol) and I'm providing an API that lets application developers to refer to this detail by name, without having to think about the data structure behind it. I consider that an abstraction, even if the name is given as const char *.
Incidentally, I've also gotten flak for not baking any multi-instance support into the initial version of libpd (I did consider it, but it seemed pointless because with the current version of Pd it would still have just one single instance).
The point would be to make all the backward-compat and forward-compat you need for supporting a future version of pd that will include features that you're already thinking about.
Nah, that would have been a clear case of overdesign, preparing for some future development that may never happen. We'll figure out how to support multiple instances when multiple instances become a possibility.
But you don't have to add an argument everywhere. I bet that you'll add a libpd_set_current_pd_instance(t_pd_interpreter *) function that will set a global variable used by the rest of the pd api. That would be consistent with the stateful message-passing in many small steps using a hidden global array. Later you can make all of that thread-safe by making all of those functions call pthread_self() to figure out which thread they're in, and replace the globals by threadwise-locals.
I thought I had already explained this when we had our little chat over at pd-everywhere, but I'll try again. Calling the message assembly API of libpd stateful is technically true but completely misleading because the hidden state is only meant to be used in a very specific and limited way. Here's the problem that it is supposed to solve: You want to translate a heterogeneous list of objects in Java into an array of type t_atom in C. That's all.
Doing the entire conversion in JNI would be a huge pain, and dynamically allocating t_atom arrays in JNI would be a pain, too. So, I chose to allocate one array up front and then provide a set of functions that will populate the array with values, in a way that's easy to wrap for Java. The fact that it's a global array does not cause any problems because the entire calling sequence needs to be protected by a lock, and so there is only one method that will ever access the array at one time. The lock would be required in any case, because any access to the symbol table needs to be locked.
The upshot is, the array you mention really acts as a local variable for a couple of methods in languages like Java or Python or Objective-C. The fact that it's currently a hidden global variable is an implementation detail that does not add problematic global state to libpd. (I can't even think of a way to creatively misuse this mechanism to introduce global statue through the back door.) Believe me, I've agonized over this, but it's been working very nicely for more than a year now, and I still can't think of a simpler way to assemble compound messages in Java.
It's more of a general consideration, and I don't have any road map in mind. Right now I'm just hoping to have a conversation about this.
Well, does that involve multiple interpreters, with one interpreter per core, but still in the same process, with a way to pass messages quickly from one interpreter to the other?
That's not at all what I have in mind. What I'm really thinking about is one interpreter that does a topological sort on the signal processing chain and then parallelizes the computation on the fly, but that's a topic for another day. I'm outta here.
Cheers,
Peter