[#5218] Ruby Book Eng tl, ch1 question — Jon Babcock <jon@...>

13 messages 2000/10/02

[#5404] Object.foo, setters and so on — "Hal E. Fulton" <hal9000@...>

OK, here is what I think I know.

14 messages 2000/10/11

[#5425] Ruby Book Eng. tl, 9.8.11 -- seishitsu ? — Jon Babcock <jon@...>

18 messages 2000/10/11
[#5427] RE: Ruby Book Eng. tl, 9.8.11 -- seishitsu ? — OZAWA -Crouton- Sakuro <crouton@...> 2000/10/11

At Thu, 12 Oct 2000 03:49:46 +0900,

[#5429] Re: Ruby Book Eng. tl, 9.8.11 -- seishitsu ? — Jon Babcock <jon@...> 2000/10/11

Thanks for the input.

[#5432] Re: Ruby Book Eng. tl, 9.8.11 -- seishitsu ? — Yasushi Shoji <yashi@...> 2000/10/11

At Thu, 12 Oct 2000 04:53:41 +0900,

[#5516] Re: Some newbye question — ts <decoux@...>

>>>>> "D" == Davide Marchignoli <marchign@di.unipi.it> writes:

80 messages 2000/10/13
[#5531] Re: Some newbye question — matz@... (Yukihiro Matsumoto) 2000/10/14

Hi,

[#5544] Re: Some newbye question — Davide Marchignoli <marchign@...> 2000/10/15

On Sat, 14 Oct 2000, Yukihiro Matsumoto wrote:

[#5576] Re: local variables (nested, in-block, parameters, etc.) — Dave Thomas <Dave@...> 2000/10/16

matz@zetabits.com (Yukihiro Matsumoto) writes:

[#5617] Re: local variables (nested, in-block, parameters, etc.) — "Brian F. Feldman" <green@...> 2000/10/16

Dave Thomas <Dave@thomases.com> wrote:

[#5705] Dynamic languages, SWOT ? — Hugh Sasse Staff Elec Eng <hgs@...>

There has been discussion on this list/group from time to time about

16 messages 2000/10/20
[#5712] Re: Dynamic languages, SWOT ? — Charles Hixson <charleshixsn@...> 2000/10/20

Hugh Sasse Staff Elec Eng wrote:

[#5882] [RFC] Towards a new synchronisation primitive — hipster <hipster@...4all.nl>

Hello fellow rubyists,

21 messages 2000/10/26

[ruby-talk:5284] Re: Proper ConditionVariable usage?

From: hipster <hipster@...4all.nl>
Date: 2000-10-04 09:00:46 UTC
List: ruby-talk #5284
On Wed, 04 Oct 2000  07:05:22 +0900, Aleksi Niemelwrote:
> How one should be using condition variables in concurrent programming? Few
> examples that I don't understand what's going on, and probably highlight the
> lack of concurrent programming knowledge of the author of this mail.

The concurrent programming that does not bend the brain
is not the true concurrent programming.

> 1)
[snip]
> I'm suprised, however, by the following program. It creates threads B...
> which immediately start to wait. I'd expect all threads will wait until the
> cv is signalled, which won't happen, or until the program terminates.
> Instead the waiting ends unexpectedly for every second thread.

scenario:
- CV::wait calls Mutex::exclusive_unlock
- then exclusive_unlock unlocks m and yields to CV::wait, which
  suspends, _leaving m unlocked_
- next thread calls CV::wait -> calls excl. unlock -> 'return unless
  @locked' so the block passed to excl. unlock is never yielded...
  Thread is never suspended: wait ends immediately.

Apperently CV::wait should use mutex.synchronize instead of exclusive
unlock.

This next scrap of code does not answer your CV question, but it
works.

require "semaphore" # see rt4997

Thread.abort_on_exception = true

def test_cv(th_count)
	s = Semaphore.new th_count, 0

	threads = []
	th_count.times do |i|
		th = Thread.start do
			i_local = i
			puts "#{i_local} waiting"
			s.wait
			puts "#{i_local} waiting ends"
		end
		threads << th
	end

	puts "sleeping"
	sleep 2

	puts "broadcast"
	th_count.times{ s.signal }

	puts "final sleep"
	sleep 2

	puts "killing threads"
	threads.each { |th| th.exit }
	puts "threads killed", ""
end

10.times do |th_count|
	test_cv(th_count+1)   # skip the zero case
end


> 2)
> Then my second problem. I think the current ConditionVariable is inadequate
> for anything but the most basic needs. For example if one wants to use it to
> create synchronization points there will be surprises.
> 
> This example is borrowed from Dave&Andy's article about Mutual exclusions at
> http://dev.rubycentral.com/articles/mutex.html. I modified it a bit to let
> the "feature" show up. The trick is to get thread B's signal execute before
> A will wait. For that I added couple lines of code to expose threads for
> context switching, and run the test many times to be captured in the
> deadlock eventually.

[snip]
Broken As Designed  ;)
The current CV implementation has an implicit precondition that wait
is called before signal: there's no state kept about the number of
signals received, any waiters are run and that's it. Your code
obviously doesn't satisfy this precond (eventually).

IOW: CV is the wrong primitive for what you want to achieve.

> ===
> Lastly I have few ideas for the future versions. 
> 
> * I'd like to see a version of CV where signalling is queued 
>   (optionally) so that cv.signal followed by later cv.wait 
>   would not get lost. This solves the bug case 2 might be suffer.
> * The first solution could be extended. The CV would count 
>   signals, and CV#wait_for(n) is introduced. That would allow 
>   one to write code like next example easily.
> 
>         A                B           C
>     cv.wait_for(2)       |           |
>                       cv.signal      |
>                          |           |
>         =                |        cv.signal
>         |                |           |

In both cases a Semaphore would come in handy, though you'd have an
upper limit to the number of signals kept. An unlimited sem is
feasible anyway.

>    I'm not sure how CV#broadcast should be done. Maybe it should
>    release all waiters.
>    Second extension could be for CV#signal(n) to pass a integer with
>    approximately same semantics as n.times{cv.signal} (done atomicly). 

A sem.signal_all could do this.


Regards,
Michel

In This Thread