Deadlockproblem

Hello,

i'm trying to realize asynchronous communication, but the sender have to
wait until the answer is recieved.
Although it is only one kind of message allowed at each time. Here is my
code and the output.

using ruby-1.8.5 on winxp

···

-----
require 'thread'

$msgQueueGlobal = Queue.new
$recieverList = Array.new

# ################################
# simulating the communication hardware
def sendMsgGlobal(msg)
   $msgQueueGlobal.push(msg)
end

def recvMsgGlobal
   $msgQueueGlobal.pop
end

recvThread = Thread.new {
   puts "start recvThread ..."
   loop do
      msg = recvMsgGlobal()
      $recieverList[msg[0]].handleRecv(msg)
   end
}
puts "recvThread started"

# ################################
# Object holding sendMessagefunction wich have to be executed only once
a
# time
class Card
   def initialize(number)
      @nr = number
      $recieverList[@nr] = self

      @waitLock = false
      @waitMutex = Mutex.new
      @waitConditional = ConditionVariable.new

      @syncMutex = Mutex.new
      @syncConditional = ConditionVariable.new
   end

   def sendMsg
      @syncMutex.synchronize {
         msg = [@nr, " Message: #{Thread.current[:name]}"]
         puts "#{Thread.current[:name]}) sending message ... <#{msg}>"

         @waitMutex.synchronize {
            @waitConditional.wait(@waitMutex) if @waitQueue
            @waitLock = true
         }

         sendMsgGlobal(msg)

         puts "#{Thread.current[:name]}) message send and waiting for
answer ..."
         @syncConditional.wait(@syncMutex)
         puts "#{Thread.current[:name]}) answer recieved <#{msg}>"
      }
   end

   def handleRecv(msg)
      @syncMutex.synchronize {
         @syncConditional.signal
      }
      @waitMutex.synchronize {
         @waitLock = false
         @waitConditional.signal
      }
   end
end

Thread.current[:name] = "Main"
a = Card.new(0)

t1 = Thread.new { Thread.current[:name] = "t1"; a.sendMsg }
t2 = Thread.new { Thread.current[:name] = "t2"; a.sendMsg }
t3 = Thread.new { Thread.current[:name] = "t3"; a.sendMsg }
t4 = Thread.new { Thread.current[:name] = "t4"; a.sendMsg }
t5 = Thread.new { Thread.current[:name] = "t5"; a.sendMsg }
t6 = Thread.new { Thread.current[:name] = "t6"; a.sendMsg }
t7 = Thread.new { Thread.current[:name] = "t7"; a.sendMsg }
t8 = Thread.new { Thread.current[:name] = "t8"; a.sendMsg }
t9 = Thread.new { Thread.current[:name] = "t9"; a.sendMsg }

Thread.list.each{ |t| t.join if t }

-------
output:
start recvThread ...
recvThread started
t1) sending message ... <0 Message: t1>
t1) message send and waiting for answer ...
t4) sending message ... <0 Message: t4>
t4) message send and waiting for answer ...
t3) sending message ... <0 Message: t3>
t3) message send and waiting for answer ...
t2) sending message ... <0 Message: t2>
t2) message send and waiting for answer ...
t1) answer recieved <0 Message: t1>
t5) sending message ... <0 Message: t5>
t5) message send and waiting for answer ...
t8) sending message ... <0 Message: t8>
t8) message send and waiting for answer ...
t7) sending message ... <0 Message: t7>
t7) message send and waiting for answer ...
t6) sending message ... <0 Message: t6>
t6) message send and waiting for answer ...
t4) answer recieved <0 Message: t4>
t9) sending message ... <0 Message: t9>
t9) message send and waiting for answer ...
t3) answer recieved <0 Message: t3>
t2) answer recieved <0 Message: t2>
t5) answer recieved <0 Message: t5>
t8) answer recieved <0
deadlock 0x277c804: sleep:J(0x2817bd8) (main) -
D:/_studium/diplom/adios/AdiosTester.rb:79
deadlock 0x2817bd8: sleep:- - C:/ruby_1.8.5/lib/ruby/1.8/thread.rb:318
C:/ruby_1.8.5/lib/ruby/1.8/thread.rb:318: Thread(0x2817bd8): deadlock
(fatal)
  from D:/_studium/diplom/adios/AdiosTester.rb:79
Message: t8>
t7) answer recieved <0 Message: t7>
t6) answer recieved <0 Message: t6>
t9) answer recieved <0 Message: t9>

------------------------

My questions:
- why did this deadlock occur, and how can it be fixed
- is there another/better way for reaching this goal

with regards
Asterix

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

Hello,

i'm trying to realize asynchronous communication, but the sender have to
wait until the answer is recieved.

but that's synchronous! :wink:

seriously, if the send always waits for the answer what good does it do thread
your program?

My questions:
- why did this deadlock occur, and how can it be fixed

among other things, you never do anything with @waitQueue - you simply always
set @waitLock to true.

- is there another/better way for reaching this goal

   harp:~ > cat a.rb
   require 'thread'
   class Oracle
     def initialize
       @questions = Queue.new
       @thread = Thread.new(@questions){|q|
         loop{
           question, answer_with = q.pop
           answer_with[question.to_s + ' 42']
         }
       }
     end
     def ask question, &answer_with
       if answer_with
         @questions.push [question, answer_with]
       else
         q = Queue.new
         ask(question){|answer| q.push answer}
         Thread.new{ q.pop }
       end
     end
     def self.instance(*a, &b) @instance ||= new(*a, &b) end
     def self.ask(*a, &b) instance.ask *a, &b end
   end

···

On Sun, 9 Jul 2006, Asterix Gallier wrote:

   #
   # you can block up front
   #
     n = -1
     p Oracle.ask("something #{ n += 1 }:").value

   #
   # or ask and reap later
   #
     threads =
     7.times{ threads << Oracle.ask("something #{ n += 1 }:") }
     threads.map{|t| p t.value}

   harp:~ > ruby a.rb
   "something 0: 42"
   "something 1: 42"
   "something 2: 42"
   "something 3: 42"
   "something 4: 42"
   "something 5: 42"
   "something 6: 42"
   "something 7: 42"

regards.

-a
--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

Thank you very much for your answer, i will try to solve my problem
based on the code you gave me.

Cheers
Asterixh

···

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