From: Sean Middleditch Date: 2002-06-11T01:46:53+09:00 Subject: RE: multiple instances of Ruby interpreter in my C++ code? On Mon, 2002-06-10 at 12:27, Jean-Hugues ROBERT wrote: > Hello, > > At 23:24 10/06/2002 +0900, you wrote: > >To be honest, I've never really seen the point of cooperative > >multi-tasking. > > When making the code "thread safe" is not worth the trouble, it > becomes handy to revert to cooperative multi-tasking. Not to > mention that the code is much easier to debug (race condition bugs > are very much the modern equivalent of the old C dangling pointer > of the past, in terms of difficulty to debug them, to me). Again, I'd find it simpler to just use a set of callbacks than to go thru the trouble of implementing a cooperative multi-tasking system. I guess I'm alone there tho. :P > > BTW: closures make it much less useful to use preemption, you > achieve the same simplicity/readability with them than with > threads, often, IMO. Minus the preemption, which is often the point of threading - performing multiple tasks simultaneously without having to worry about the other threads. i.e., large tasks that require lots of processing can either just be set to run with a preempted model, or have to broken up into chunks in a cooperative model (or sprinkled with thread yields). > > About embedding Ruby, I would prefer it to be as easy as it is > for other languages, Tcl for example. The more Ruby users, the > better I feel ;-) Yes, but again, Ruby simply is a pita when you are embedding, especially when you need to deal with real multiple OS threads or multiple interpreter instances. I recall Matz saying he'd like to get rid of all the global variables in Rite... search the archives for his exact words. Another thing about embedding languages that I've found a pain with most of them, is when you need to repeatedly call a particular script - most languages, Ruby included (so far as I can tell) you need to call load/eval on the textual implementation over and over (and thus have it reparsed and compiled), or pull some magic to wrap it up in a proc or something (versus having a single, clean, safe API call to do it for you). > > Maybe the multiple instances of Ruby interpreter can be workarounded > with load( file, private_flag), where private_flag deals with > namespaces... I don't know if there is some equivalent for eval() > but I am pretty sure that by enclosing the code inside a "begin"/"end" > the local variables are going to be "local" to each "instance". That doesn't fix the problem that Ruby is not thread safe. The Ruby threads can be dealt with easily enough, but not the OS threads. A coopertively multi-tasked application may be able to pull off sharing Ruby (i.e., it's guaranteed that the last Ruby invocation in thread A is completed before thread B makes an invocation), but that would be ugly, and why in all hell you'd want to cooperatively multi-task an application *anyways* (neither thread can run simultaneously, and you've already broken up the tasks, in order to be cooperative...) > > Switching from one ruby "thread" to another is a matter of calling > the underlying multi-tasker "yield()" function I guess > > Conclusion: With cooperative multi-tasking, multiple instances of > Ruby interpreter can be "simulated". There are probably some data > with "global" scope that need some more handling and that I am > overlooking. And in the end, this is all a lot of work for a hack around a problem that doesn't exist with other languages, which are designed for embedding. Ruby simply isn't made for doing this, you'd have to be either a masochist or a Ruby fanatic (in the bad sense of the word) to try this kind of thing instead of just using a better suited tool. It's the opposite of trying to write a full-scale GUI app in Bash - it's possible, but it's not the right tool for the job. > > Yours, > > Jean-Hugues >