T
Tim Becker
Hi,
I'm trying to build a message queue that can receive messages, blocks
until messages arrive and has the ability to only block for a limited
amount of time. Unfortunately, the build-in Queue doesn't support
timeout behaviour, so I went about implementing a queue myself. I
missed java's Object.wait method, i.e. using a plain object to notify
the blocking thread to resume .
I ended up using `thread.join(timeout)` which blocks the current
thread until the thread that `join` was called on finishes (or until
timeout is reached). My queue doesn't need to join any particular
thread, though, it just needs to be notified when a new message is
added to the queue. So I needed to create a `dummy` thread solely to
provide notification. What I came up with is this:
require 'thread'
class MessageQueue
def initialize
@lock = Mutex.new
@t = Thread.new{Thread.stop} # this thread exists solely for notification
@queue = []
end
def enqueue msg
@lock.synchronize {
@queue.push msg
t=@t
@t=Thread.new{Thread.stop}
t.kill# notifiy waiting thread
}
end
def dequeue timeout=nil
msg = nil
stop = Time.now+timeout if timeout
while msg == nil
@lock.synchronize {msg = @queue.shift}
break if timeout && Time.new >= stop
@t.join(timeout) unless msg # wait for new message
end #while
msg
end
end
While this works fine, it seems like a bit of a kludge because I have
to create/misuses threads solely to provided notification to the
blocking thread.
Any thought? Am I missing an easier/build-in method to block a thread
only for a limited about of time?
Thanks,
-tim
I'm trying to build a message queue that can receive messages, blocks
until messages arrive and has the ability to only block for a limited
amount of time. Unfortunately, the build-in Queue doesn't support
timeout behaviour, so I went about implementing a queue myself. I
missed java's Object.wait method, i.e. using a plain object to notify
the blocking thread to resume .
I ended up using `thread.join(timeout)` which blocks the current
thread until the thread that `join` was called on finishes (or until
timeout is reached). My queue doesn't need to join any particular
thread, though, it just needs to be notified when a new message is
added to the queue. So I needed to create a `dummy` thread solely to
provide notification. What I came up with is this:
require 'thread'
class MessageQueue
def initialize
@lock = Mutex.new
@t = Thread.new{Thread.stop} # this thread exists solely for notification
@queue = []
end
def enqueue msg
@lock.synchronize {
@queue.push msg
t=@t
@t=Thread.new{Thread.stop}
t.kill# notifiy waiting thread
}
end
def dequeue timeout=nil
msg = nil
stop = Time.now+timeout if timeout
while msg == nil
@lock.synchronize {msg = @queue.shift}
break if timeout && Time.new >= stop
@t.join(timeout) unless msg # wait for new message
end #while
msg
end
end
While this works fine, it seems like a bit of a kludge because I have
to create/misuses threads solely to provided notification to the
blocking thread.
Any thought? Am I missing an easier/build-in method to block a thread
only for a limited about of time?
Thanks,
-tim