A
Asterix Gallier
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
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