Mercurial > hg > pulseaudio
changeset 45:c3802b8ed541
fixed the deadlock which occurred when adding multiple listeners during the open() call of the PulseAudioMixer
author | Omair Majid <omajid@redhat.com> |
---|---|
date | Wed, 06 Aug 2008 14:55:15 -0400 |
parents | 4a01f1203d48 |
children | 2331da2e5f6a |
files | .hgignore src/org/classpath/icedtea/pulseaudio/EventLoop.java src/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java |
diffstat | 3 files changed, 64 insertions(+), 50 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Wed Aug 06 14:55:15 2008 -0400 @@ -0,0 +1,8 @@ +# use glob syntax. +syntax: glob + +*.class +*.o +*~ +org_classpath_icedtea_*.h +*.log
--- a/src/org/classpath/icedtea/pulseaudio/EventLoop.java Wed Aug 06 14:08:52 2008 -0400 +++ b/src/org/classpath/icedtea/pulseaudio/EventLoop.java Wed Aug 06 14:55:15 2008 -0400 @@ -45,8 +45,8 @@ import org.classpath.icedtea.pulseaudio.ContextEvent.Type; /* - * any methods that can obstruct the behaviour of pa_mainloop - * should run synchronized + * any methods that can obstruct the behaviour of pa_mainloop should run + * synchronized * * */ @@ -68,7 +68,7 @@ private String serverString; private int status; - // private boolean eventLoopIsRunning = false; + // private boolean eventLoopIsRunning = false; public Semaphore finished = new Semaphore(0); @@ -214,25 +214,16 @@ private void fireEvent(final ContextEvent e) { System.out.println(this.getClass().getName() + "firing event: " + e.getType().toString()); - Thread th = new Thread(new Runnable() { + System.out.println("notifying listeners"); - @Override - public void run() { - System.out.println("notifying listeners"); - - synchronized (contextListeners) { - System.out.println(contextListeners.size()); - for (ContextListener listener : contextListeners) { - listener.update(e); - System.out.println("updating listeners"); - } - } + synchronized (contextListeners) { + System.out.println(contextListeners.size()); + for (ContextListener listener : contextListeners) { + listener.update(e); + System.out.println("updating listeners"); } - - }); + } - th.start(); - } public void setVolume(long streamPointer, int volume) {
--- a/src/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java Wed Aug 06 14:08:52 2008 -0400 +++ b/src/org/classpath/icedtea/pulseaudio/PulseAudioMixer.java Wed Aug 06 14:55:15 2008 -0400 @@ -308,12 +308,38 @@ eventLoop.setAppName(appName); eventLoop.setServer(host); + + ContextListener eventListener = new ContextListener() { + + @Override + public void update(ContextEvent e) { + System.out.println("General listener was notified"); + System.out.println(" eventType: " + e.getType()); + if (e.getType() == ContextEvent.Type.READY) { + System.out.println("firing event ready.."); + fireEvent(new LineEvent(PulseAudioMixer.this, + LineEvent.Type.OPEN, AudioSystem.NOT_SPECIFIED)); + System.out.println("done"); + } else if (e.getType() == ContextEvent.Type.FAILED + || e.getType() == ContextEvent.Type.TERMINATED) { + fireEvent(new LineEvent(PulseAudioMixer.this, + LineEvent.Type.CLOSE, AudioSystem.NOT_SPECIFIED)); + } + System.out.println("general listener returning"); + } + + }; + + eventLoop.addContextListener(eventListener); + + final Semaphore ready = new Semaphore(0); ContextListener initListener = new ContextListener() { @Override public void update(ContextEvent e) { + System.out.println("specific listener notifed"); System.out.println(this.getClass().getName() + ": Event detected " + e.getType().toString()); if (e.getType() == ContextEvent.Type.READY @@ -322,6 +348,7 @@ ready.release(); System.out.println("realeasing semaphore ready"); } + System.out.println("specific listener returning"); } }; @@ -355,48 +382,36 @@ } System.out.println(this.getClass().getName() + ": ready"); - + this.isOpen = true; -// ContextListener eventListener = new ContextListener() { -// -// @Override -// public void update(ContextEvent e) { -// if (e.getType() == ContextEvent.Type.READY) { -// -// fireEvent(new LineEvent(PulseAudioMixer.this, -// LineEvent.Type.OPEN, AudioSystem.NOT_SPECIFIED)); -// } else if (e.getType() == ContextEvent.Type.FAILED -// || e.getType() == ContextEvent.Type.TERMINATED) { -// fireEvent(new LineEvent(PulseAudioMixer.this, -// LineEvent.Type.CLOSE, AudioSystem.NOT_SPECIFIED)); -// } -// -// } -// -// }; -// eventLoop.addContextListener(eventListener); } @Override - synchronized public void removeLineListener(LineListener listener) { + public void removeLineListener(LineListener listener) { lineListeners.remove(listener); } - synchronized private void fireEvent(final LineEvent e) { - Thread th = new Thread(new Runnable() { - @Override - public void run() { - synchronized (lineListeners) { - for (LineListener lineListener : lineListeners) { - lineListener.update(e); - } - } + /* + * Should this method be synchronized? I had a few reasons, but i forgot them + * Pros: + * - Thread safety? + * + * Cons: + * - eventListeners are run from other threads, if those then call fireEvent + * while a method is waiting on a listener, this synchronized block wont + * be entered: deadlock! + * + */ + private void fireEvent(final LineEvent e) { + System.out.println(this.getClass().getName() + "fireEvent(): firing event"); + synchronized (lineListeners) { + for (LineListener lineListener : lineListeners) { + lineListener.update(e); } - }); - th.start(); + } } public static void main(String[] args) throws Exception {