Mutex

Hi,
I have a trouble using the ConditionVariable and Mutex Class ,
Actualy , I'm tryin' to make a Semaphore to manage Threads
a simple semaphore with its 2 famous methods looks like :

def acquire()

    raise "Interrupted Thread " if (!Thread.current.alive?)
    @mutex.synchronize {
     while @permits < 1
       @cv.wait(@mutex)
     end
    @permits = @permits - 1
    }
end

def release()
    @mutex.synchronize{

      @permits += 1
      @cv.signal

      }

end

But When I call The acquire Method later

I get : `wait': stopping only thread (ThreadError)

SomeOne has an idea ??

Thx;)

···

--
Posted via http://www.ruby-forum.com/.

Not without the full code. What you showed looks OK.

Kind regards

robert

···

2010/2/15 Mido Peace <mido.peace@gmail.com>:

Hi,
I have a trouble using the ConditionVariable and Mutex Class ,
Actualy , I'm tryin' to make a Semaphore to manage Threads
a simple semaphore with its 2 famous methods looks like :

def acquire()

raise "Interrupted Thread " if (!Thread.current.alive?)
@mutex.synchronize {
while @permits < 1
@cv.wait(@mutex)
end
@permits = @permits - 1
}
end

def release()
@mutex.synchronize{

 @permits \+= 1
 @cv\.signal

 \}

end

But When I call The acquire Method later

I get : `wait': stopping only thread (ThreadError)

SomeOne has an idea ??

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

require 'thread'
class Semaphore

  Thread.abort_on_exception = true
  attr_accessor :permits, :mutex, :cv

  def initialize ( permits )

      @permits = permits
      @mutex = Mutex.new
      @cv = ConditionVariable.new

  end

  def acquire()

    raise "Interrupted Thread " if (!Thread.current.alive?)
    @mutex.synchronize {
    while @permits < 1
       @cv.wait(@mutex)
    end
    @permits = @permits - 1
    }
  end

  def release()
    @mutex.synchronize{

      @permits += 1
      @cv.signal

      }

  end

end

...
class Process < Thread
...
def initialize()
  super(){
     ...
     @sem=Semaphore.new(0)
     ...
}
end

def run()

...
@sem.acquire()

end

The problem is that I should call the semaphore later , not within
initialization of the process !!

···

--
Posted via http://www.ruby-forum.com/.

require 'thread'
class Semaphore

Thread.abort_on_exception = true

Why do you place that inside the class? This is a global setting.

attr_accessor :permits, :mutex, :cv

def initialize ( permits )

 @permits = permits
 @mutex = Mutex\.new
 @cv = ConditionVariable\.new

end

def acquire()

raise "Interrupted Thread " if (!Thread.current.alive?)
@mutex.synchronize {
while @permits < 1
@cv.wait(@mutex)
end
@permits = @permits - 1
}
end

def release()
@mutex.synchronize{

 @permits \+= 1
 @cv\.signal

 \}

end

end

...
class Process < Thread
...
def initialize()
super(){
...
@sem=Semaphore.new(0)

IIRC semaphores are typically initialized with a positive value, i.e.
something larger than 0. If you think about it, init with 0 does not
make too much sense.

\.\.\.

}
end

def run()

...
@sem.acquire()

end

The problem is that I should call the semaphore later , not within
initialization of the process !!

You can't define a class Process like this because that class exists already.

One more hint: for more robust access I suggest to add this method to
your Semaphore class:

def synchronize
  acquire

  begin
    yield
  ensure
    release
  end
end

Kind regards

robert

···

2010/2/15 Mido Peace <mido.peace@gmail.com>:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

It depends on what you're using the semaphore for. If it's to be used
for locking, you're right. If it's a signaling semaphore, then 0 for
the init value is exactly what's needed.

Mido, what do you want this for? Mutual exclusion? (But then why not
just use a Mutex?) Signaling? Counting semaphore?

You might consider using a (sigh) Queue or SizedQueue instead. Even
tho it's kinda silly to use a Queue when all you're ever putting on or
taking off the queue is instances of TrueClass.

It used to be possible to fake signaling semaphore behavior by
creating a Mutex then immediately locking it. That doesn't work
anymore, tho; the thread that unlocks a Mutex now has to be the same
one that locked it.

···

On 2/15/10, Robert Klemme <shortcutter@googlemail.com> wrote:

2010/2/15 Mido Peace <mido.peace@gmail.com>:

    @sem=Semaphore.new(0)

IIRC semaphores are typically initialized with a positive value, i.e.
something larger than 0. If you think about it, init with 0 does not
make too much sense.

@sem=Semaphore\.new\(0\)

IIRC semaphores are typically initialized with a positive value, i.e.
something larger than 0. If you think about it, init with 0 does not
make too much sense.

It depends on what you're using the semaphore for. If it's to be used
for locking, you're right. If it's a signaling semaphore, then 0 for
the init value is exactly what's needed.

Right you are. Although I'd say that a condition variable is probably
a better tool for that.

Mido, what do you want this for? Mutual exclusion? (But then why not
just use a Mutex?) Signaling? Counting semaphore?

You might consider using a (sigh) Queue or SizedQueue instead. Even
tho it's kinda silly to use a Queue when all you're ever putting on or
taking off the queue is instances of TrueClass.

Hm, in that case I'd prefer a semaphore.

It used to be possible to fake signaling semaphore behavior by
creating a Mutex then immediately locking it. That doesn't work
anymore, tho; the thread that unlocks a Mutex now has to be the same
one that locked it.

That is not needed. Please see my test - I could not reproduce the
behavior reported.

Kind regards

robert

sem.rb (1.08 KB)

···

2010/2/15 Caleb Clausen <vikkous@gmail.com>:

On 2/15/10, Robert Klemme <shortcutter@googlemail.com> wrote:

2010/2/15 Mido Peace <mido.peace@gmail.com>:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Thx for your Help !!

well , actually , I tried first of all to start a 'p' Process and to
make it wait , ( for the mutex signal ), then later on my code , I will
lunch a function that will increment the Value on the Semaphore , that
my 'p' could enter the Mutex section and do its work !!

So , I think the Error I did , is That I initialize the process without
tellin' him to wait ( without the acquire function ) , and when I tried
to call it later , it give me that error .

now wihtin the Initialize , I added the call to acquire , Somethg like ;

require 'Semaphore'
class MyProcess < Thread
def intializer ()
    super(){
      ... # Init Some Variables
      @semBegin = Semaphore.new(0)
      @semEnd = Semaphore.new(0)
      @semBegin.acquire() # here since the value is 0 , he will wait
...
      ... # Code to be exectured after recieving the Mutex Signal

     }
end
...
end
#SomeWhere I will increment the Semaphore Value to wake up my process
and push it to work !!

in this way , I could keep my process Alive during the Application
(waitin')... otherwise the process will ends when nothing is left to do
!!

:wink:

···

--
Posted via http://www.ruby-forum.com/.

It may be, but I've never understood condition variables properly.
They seem to be semaphores with some additional semantics but it never
made enough sense to me that I felt I could use them with
confidence... the docs never helped. I was raised on semphores, and
that's all I know. :slight_smile: If you actually understand condition variables
and how to use them, could you kindly explain them to me? I would be
grateful.

···

On 2/16/10, Robert Klemme <shortcutter@googlemail.com> wrote:

2010/2/15 Caleb Clausen <vikkous@gmail.com>:

It depends on what you're using the semaphore for. If it's to be used
for locking, you're right. If it's a signaling semaphore, then 0 for
the init value is exactly what's needed.

Right you are. Although I'd say that a condition variable is probably
a better tool for that.

Ah, my posting did not make it through the gateway - probably because I attached the code. Here it is again: sem.rb · GitHub

Basically a condition variable is just a special signaling mechanism - you can use any number of condition variables with a mutex or monitor in order to signal different conditions. Waiting threads are then woken up efficiently. For example, in a bounded queue you can have two condition variables @queue_has_room and @data_available with obvious semantics (@queue_has_room is signaled whenever something is taken from the queue, @data_available is signaled whenever something is put into the queue).

Technically when you wait on a condition variable you must own the monitor / mutex. Your thread is blocked and the lock is released. When a signal occurs for this condition variable, waiting threads are woken and after the signal thread releases the lock any of the waiting thread obtains it and continues. That way you can selectively wake up threads which is more efficient to just wake up all threads waiting for a monitor.

If you want to dig deeper into concurrency I can recommend Doug Lea's excellent book (even though it is about Java). http://g.oswego.edu/

Kind regards

  robert

···

On 02/16/2010 08:19 PM, Caleb Clausen wrote:

On 2/16/10, Robert Klemme <shortcutter@googlemail.com> wrote:

2010/2/15 Caleb Clausen <vikkous@gmail.com>:

It depends on what you're using the semaphore for. If it's to be used
for locking, you're right. If it's a signaling semaphore, then 0 for
the init value is exactly what's needed.

Right you are. Although I'd say that a condition variable is probably
a better tool for that.

It may be, but I've never understood condition variables properly.
They seem to be semaphores with some additional semantics but it never
made enough sense to me that I felt I could use them with
confidence... the docs never helped. I was raised on semphores, and
that's all I know. :slight_smile: If you actually understand condition variables
and how to use them, could you kindly explain them to me? I would be
grateful.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/