Ensuring canvas safety (using canvas by multiple processes)

Igor Stasenko siguctua at gmail.com
Tue Feb 12 09:23:36 UTC 2008


On 12/02/2008, Michael van der Gulik <mikevdg at gmail.com> wrote:
>
>
> Lots, but it depends on what the problem actually is. Could you describe it
> in more detail?
>
well, when you issuing a command like:

canvas translateBy: offset during: [ ... ].

canvas does following:

gl pushMatrix.
gl translateBy: offset.
aBlock value.
gl popMatrix.

operations with matrix affecting global state, if you try to draw
anything in parallel process, while in current process you evaluating
a block, you will be screwed up.

Another issue is with using glBegin/glEnd pair. These commands can't
be nested, also a number of valid GL operations inside glBegin/glEnd
are limited.

In general, any code, that doing like:

gl changeSomeState.
..some code..
gl revertToPreviousState.

is potentially leading to nirvana, if you can't guarantee a proper
order of commands, issued to OpenGL.

> One option is to modify Canvas (or a subclass) to have a getLock method
> which returns a Mutex (aka Semaphore) unique to that Canvas. Your code can
> then do "mutex critical: [...]" blocks to assure atomicity.
>
> However, it would seem to me that the problem is with the user of the
> Canvas. With any canvas, you need to issue the drawing instructions in the
> right order to preserve the z-index of the elements added. It's the user who
> must make sure that it does not have two threads drawing in the same
> Rectangle concurrently.
>
> Don't be sparing with the use of Semaphores. Correct code is better than
> fast code.

That's what i fear most. Adding semaphores will kill performance :)
In C, i can simply put a canvas var in thread-local storage, so it's
value will be unique for each thread of execution.
Interesting, is something like this can be done for squeak?

So, i can write something like:

object := Processor threadedVariable. "should it be a Smalltalk's method?"
object value: (Array new:5).

object value "should return array with 5 elements"
[ object value ] fork.  "object value should return nil for new
process, since it's not initialized to anything"

if properly implemented, a #value method can be very fast (w/o using
dictionaries or sets).
For instance, by adding a single variable to process , where i can
hold references to these threaded-vars, and threadedVariable then will
hold a slot index. Then #value can be:

value
^ Processor currentProcess slotAt: slotNum

Process slotAt: num
  ^ slots at: num ifAbsent: [nil].

-- 
Best regards,
Igor Stasenko AKA sig.



More information about the Squeak-dev mailing list