Hello,
I'm trying to get this code run, but I'm not getting the results I expect. I running on a 3.10beta image.
semA := Semaphore new. semB := Semaphore new.
[Transcript show: 'b1'; cr. semB signal. semA wait. Transcript show: 'b2'; cr.] fork. [Transcript show: 'a1'; cr. semA signal. semB wait. Transcript show: 'a2'; cr.] fork.
results:
b1
a2
That's all. If I hit cmd-doIt rapidly I do begin to see a1 and b2 as well. The process browser doesn't seem to show anything waiting.
I'm on a amd64, in a 32bit chroot. I'm in Gentoo Linux, so the VM was built from source.
Thanks for any clues,
JTS
On Sun, Sep 30, 2007 at 06:44:29AM +0700, Jason Shoemaker wrote:
Hello,
I'm trying to get this code run, but I'm not getting the results I expect. I running on a 3.10beta image.
semA := Semaphore new. semB := Semaphore new.
[Transcript show: 'b1'; cr. semB signal. semA wait. Transcript show: 'b2'; cr.] fork. [Transcript show: 'a1'; cr. semA signal. semB wait. Transcript show: 'a2'; cr.] fork.
results:
b1
a2
That's all. If I hit cmd-doIt rapidly I do begin to see a1 and b2 as well. The process browser doesn't seem to show anything waiting.
I'm on a amd64, in a 32bit chroot. I'm in Gentoo Linux, so the VM was built from source.
What VM did you build from source?
squeak -version gives me:
Squeak3.9alpha of 4 July 2005 i686 AMD Turion(tm) 64 Mobile Technology ML-30 GNU/Linux
On 9/30/07, Matthew Fulmer tapplek@gmail.com wrote:
On Sun, Sep 30, 2007 at 06:44:29AM +0700, Jason Shoemaker wrote:
Hello,
I'm trying to get this code run, but I'm not getting the results I expect. I running on a 3.10beta image.
semA := Semaphore new. semB := Semaphore new.
[Transcript show: 'b1'; cr. semB signal. semA wait. Transcript show: 'b2'; cr.] fork. [Transcript show: 'a1'; cr. semA signal. semB wait. Transcript show: 'a2'; cr.] fork.
results:
b1
a2
That's all. If I hit cmd-doIt rapidly I do begin to see a1 and b2 as well. The process browser doesn't seem to show anything waiting.
I'm on a amd64, in a 32bit chroot. I'm in Gentoo Linux, so the VM was built from source.
What VM did you build from source?
-- Matthew Fulmer -- http://mtfulmer.wordpress.com/ Help improve Squeak Documentation: http://wiki.squeak.org/squeak/808 _______________________________________________ Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
Hello,
After Matthew pointed out that Transcript>>show: isn't tread-safe, I changed it to Transcript>>nextPutAll:
The script still wasn't give the expected output. So after playing around a bit, I discovered if I waited just a bit before flushing it would then work. It feels like a hack though.
semA := Semaphore new. semB := Semaphore new.
[Transcript cr; nextPutAll: 'b1'. semB signal. semA wait. Transcript cr; nextPutAll: 'b2'. ] fork. [Transcript cr; nextPutAll: 'a1'. semA signal. semB wait. Transcript cr; nextPutAll: 'a2'.] fork. (Delay forMilliseconds: 1) wait. Transcript flush
Results:
b1 a1 a2 b2
It's kind of strange why this only seems to bite me. :/
Thanks for the help, JTS
This is probably a safer version. It works for me.
semA := Semaphore new. semB := Semaphore new.
thread1 := [Transcript cr; nextPutAll: 'b1'. semB signal. semA wait. Transcript cr; nextPutAll: 'b2'. ] fork. thread2 := [Transcript cr; nextPutAll: 'a1'. semA signal. semB wait. Transcript cr; nextPutAll: 'a2'.] fork.
[thread1 isTerminated and: [thread2 isTerminated]] whileFalse: [(Delay forMilliseconds: 100) wait]. Transcript flush
Now to move on to another pattern.
JTS
Hi Jason,
Im not really sure what you are trying to do but this works too.
semA := Semaphore forMutualExclusion. semB := Semaphore new.
[semA critical: [Transcript show: 'b1'; cr. semB signal. semA wait.].
Transcript show: 'b2'; cr. semB signal. ] fork. [semB critical: [Transcript show: 'a1'; cr. semA signal. semB wait.]. Transcript show: 'a2'; cr. ] fork.
Semaphore forMutualExclusion signals the semaphore so that you can get into the first critical block.
The critical block is what does the code blocking.
SemB signal allows the second thread in while semA wait keeps the block from exiting. Then semA signal allows the first block to continue, but semB wait keeps the second block from exiting. Then semB signal allows the second block to continue, and since both forked blocks complete they disappear.
There are a lot of ways to make this easier, but I think its good to look at these constructs closely, if you are planning to work with threads.
Check out SharedQueue for thread safe processing. Also have a look at Mutex for other Semaphore behavior.
Good luck!
Ron Teitelbaum President / Principal Software Engineer US Medical Record Specialists www.USMedRec.com
________________________________________ From: Jason Shoemaker
This is probably a safer version. It works for me.
semA := Semaphore new. semB := Semaphore new.
thread1 := [Transcript cr; nextPutAll: 'b1'. semB signal. semA wait. Transcript cr; nextPutAll: 'b2'. ] fork. thread2 := [Transcript cr; nextPutAll: 'a1'. semA signal. semB wait. Transcript cr; nextPutAll: 'a2'.] fork.
[thread1 isTerminated and: [thread2 isTerminated]] whileFalse: [(Delay forMilliseconds: 100) wait]. Transcript flush
Now to move on to another pattern.
JTS
Hi Folks,
I think the problem is that we have race conditions due to the fact that Transcript is not thread-safe (as pointed out by Matthew). We can fix this either by making it thread-safe (using a mutex semaphore as suggested by Ron), or by simply enclosing our accesses to Transcript with a mutex. This would allow Jason to safely experiment with the plain semaphores.
This now works the way we expect it to.
semA := Semaphore new. semB := Semaphore new. semT := Semaphore forMutualExclusion.
[ semT critical: [Transcript show: 'b1'; cr]. semB signal. semA wait. semT critical: [Transcript show: 'b2'; cr] ] fork. [ semT critical: [Transcript show: 'a1'; cr]. semA signal. semB wait. semT critical: [Transcript show: 'a2'; cr] ] fork.
Oscar
On Sep 30, 2007, at 4:20, Ron Teitelbaum wrote:
Hi Jason,
I’m not really sure what you are trying to do but this works too.
semA := Semaphore forMutualExclusion. semB := Semaphore new.
[semA critical: [Transcript show: 'b1'; cr. semB signal. semA wait.].
Transcript show: 'b2'; cr. semB signal. ] fork. [semB critical: [Transcript show: 'a1'; cr. semA signal. semB wait.]. Transcript show: 'a2'; cr. ] fork.
Semaphore forMutualExclusion signals the semaphore so that you can get into the first critical block.
The critical block is what does the code blocking.
SemB signal allows the second thread in while semA wait keeps the block from exiting. Then semA signal allows the first block to continue, but semB wait keeps the second block from exiting. Then semB signal allows the second block to continue, and since both forked blocks complete they disappear.
There are a lot of ways to make this easier, but I think it’s good to look at these constructs closely, if you are planning to work with threads.
Check out SharedQueue for thread safe processing. Also have a look at Mutex for other Semaphore behavior.
Good luck!
Ron Teitelbaum President / Principal Software Engineer US Medical Record Specialists www.USMedRec.com
From: Jason Shoemaker
This is probably a safer version. It works for me.
semA := Semaphore new. semB := Semaphore new.
thread1 := [Transcript cr; nextPutAll: 'b1'. semB signal. semA wait. Transcript cr; nextPutAll: 'b2'. ] fork. thread2 := [Transcript cr; nextPutAll: 'a1'. semA signal. semB wait. Transcript cr; nextPutAll: 'a2'.] fork.
[thread1 isTerminated and: [thread2 isTerminated]] whileFalse: [(Delay forMilliseconds: 100) wait]. Transcript flush
Now to move on to another pattern.
JTS
Beginners mailing list Beginners@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/beginners
beginners@lists.squeakfoundation.org