我正在创建一个使用mplayer
播放音乐的脚本。我试图让它工作的方式是允许多个线程(通过HTTP请求)可以播放一首歌。但是,我不想一次播放多首歌曲,我不想要一个队列。我只是想播放最近的请求。不过,我遇到了问题,我的互斥量。当我期望它时,它并不总是返回锁定状态。
Class Handler
def initialize
@read_io, @write_io = IO.pipe
@child = nil
@mutex = Mutex.new
end
def play_song_with_id(id)
if @mutex.locked? then # this doesn't always return as expected
stop_mplayer # this is how I interupt the child
@mutex.unlock
end
if @mutex.lock then
@child = fork do
STDIN.reopen(@read_io)
`mplayer -really-quiet "#{id}"`
exit
end
Process.detatch(@child)
end
end
def stop_mplayer()
@write_io.write "q" # mplayer takes input 'q' to quit
end
end
只是为了全面了解,这是我如何路由请求。一个简单的WEBrick服务器:
if $0 == __FILE__ then
# Create the server
server = WEBrick::HTTPServer.new(:Port=>port)
ip = IPSocket.getaddress(Socket.gethostname)
# Create a handler
handler = Handler.new
# Define routes
server.mount "/handle", Routes::HandleRoute, handler
# Handle interuptions
trap "INT" do
server.shutdown
end
# Start the server
puts "\n===================="
puts " * Server running at #{ip} on port #{port}"
puts "====================\n\n"
server.start
end
路线:
class HandleRoute < WEBrick::HTTPServlet::AbstractServlet
def initialize server, handler
@handler = handler
end
def do_POST(request, response)
if(request.body)
@handler.play_song_with_id(request.body)
end
end
end
TL; DR - 不知何故,有时两首歌会一次播放,我想用@mutex
来防止这种情况发生。我想播放最近的请求,并停止当前正在播放的任何播放。我想知道我试图停止播放的方式是问题,而不是互斥体?如果是这样,什么是打断孩子的更好方法?
答案 0 :(得分:2)
我会尝试简化你对互斥锁的使用。您的当前实现在互斥锁解锁和再次锁定之间看起来容易受到计时问题的影响。
class Handler
def play_song_with_id(id)
@mutex.synchronize do
stop_mplayer
@child = fork do
STDIN.reopen(@read_io)
`mplayer -really-quiet "#{id}"`
exit
end
Process.detach(@child)
end
end
end
答案 1 :(得分:0)
在这种情况下,我认为你真的不需要互斥锁。由于您只想播放最新的,因此无论何时新请求完成,您都可以终止mplayer。所以:
def play_song_with_id(id)
stop_mplayer_if_any
start_mplayer
end
def stop_mplayer_if_any()
@write_io.write "q"
rescue => e # Please do a better job here, rescuing only the really expected exceptions
logger.info "Rescuing from #{e.inspect} and ignoring"
end
def start_mplayer
@child = fork do
STDIN.reopen(@read_io)
`mplayer -really-quiet "#{id}"`
exit
end
end
没有必要时没有同步问题。