mirror of https://github.com/sipwise/jitsi.git
Delivers SystemActivity events in different thread and on windows give time to the underlying jvm to dispatch the same message and populate its interfaces.
parent
ea647d25f1
commit
78cefa3a27
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
|
||||
*
|
||||
* Distributable under LGPL license.
|
||||
* See terms of license at gnu.org.
|
||||
*/
|
||||
package net.java.sip.communicator.impl.sysactivity;
|
||||
|
||||
import net.java.sip.communicator.service.sysactivity.*;
|
||||
import net.java.sip.communicator.service.sysactivity.event.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The class implements a dispatch event thread. The thread will
|
||||
* fire event every time it is added through the <tt>fireSystemActivityEvent()</tt>
|
||||
* method and would then deliver it to a registered listener if any.
|
||||
* If the event has time set we used it as a delay before dispatching the event.
|
||||
* <p>
|
||||
* @author Damian Minkov
|
||||
*/
|
||||
public class SystemActivityEventDispatcher
|
||||
implements Runnable
|
||||
{
|
||||
/**
|
||||
* Our class logger.
|
||||
*/
|
||||
private static Logger logger =
|
||||
Logger.getLogger(SystemActivityEventDispatcher.class);
|
||||
|
||||
/**
|
||||
* A list of listeners registered for system activity events.
|
||||
*/
|
||||
private final List<SystemActivityChangeListener> listeners =
|
||||
new LinkedList<SystemActivityChangeListener>();
|
||||
|
||||
/**
|
||||
* start/stop indicator.
|
||||
*/
|
||||
private boolean stopped = true;
|
||||
|
||||
/**
|
||||
* The thread that runs this dispatcher.
|
||||
*/
|
||||
private Thread dispatcherThread = null;
|
||||
|
||||
/**
|
||||
* The events to dispatch.
|
||||
*/
|
||||
private Map<SystemActivityEvent, Integer> eventsToDispatch
|
||||
= new LinkedHashMap<SystemActivityEvent, Integer>();
|
||||
|
||||
/**
|
||||
* Registers a listener that would be notified of changes that have occurred
|
||||
* in the underlying system.
|
||||
*
|
||||
* @param listener the listener that we'd like to register for changes in
|
||||
* the underlying system.
|
||||
*/
|
||||
public void addSystemActivityChangeListener(
|
||||
SystemActivityChangeListener listener)
|
||||
{
|
||||
synchronized(listeners)
|
||||
{
|
||||
if(!listeners.contains(listener))
|
||||
{
|
||||
listeners.add(listener);
|
||||
|
||||
if(dispatcherThread == null)
|
||||
{
|
||||
dispatcherThread = new Thread(this);
|
||||
dispatcherThread.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified listener so that it won't receive further
|
||||
* notifications of changes that occur in the underlying system
|
||||
*
|
||||
* @param listener the listener to remove.
|
||||
*/
|
||||
public void removeSystemActivityChangeListener(
|
||||
SystemActivityChangeListener listener)
|
||||
{
|
||||
synchronized(listeners)
|
||||
{
|
||||
listeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupts this dispatcher so that it would no longer disptach events.
|
||||
*/
|
||||
public void stop()
|
||||
{
|
||||
synchronized(eventsToDispatch)
|
||||
{
|
||||
stopped = true;
|
||||
eventsToDispatch.notifyAll();
|
||||
|
||||
dispatcherThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivers the specified event to all registered listeners.
|
||||
*
|
||||
* @param evt the <tt>SystemActivityEvent</tt> that we'd like delivered to
|
||||
* all registered message listeners.
|
||||
*/
|
||||
protected void fireSystemActivityEvent(SystemActivityEvent evt)
|
||||
{
|
||||
fireSystemActivityEvent(evt, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivers the specified event to all registered listeners.
|
||||
*
|
||||
* @param evt the <tt>SystemActivityEvent</tt> that we'd like delivered to
|
||||
* all registered message listeners.
|
||||
* @param wait time in ms. to wait before firing the event.
|
||||
*/
|
||||
protected void fireSystemActivityEvent(SystemActivityEvent evt, int wait)
|
||||
{
|
||||
synchronized(eventsToDispatch)
|
||||
{
|
||||
eventsToDispatch.put(evt, wait);
|
||||
|
||||
eventsToDispatch.notifyAll();
|
||||
|
||||
if(dispatcherThread == null && listeners.size() > 0)
|
||||
{
|
||||
dispatcherThread = new Thread(this);
|
||||
dispatcherThread.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivers the specified event to the <tt>listener</tt>.
|
||||
*
|
||||
* @param evt the <tt>SystemActivityEvent</tt> that we'd like delivered to
|
||||
* the listener.
|
||||
* @param listener that will receive the event.
|
||||
*/
|
||||
private void fireSystemActivityEvent(SystemActivityEvent evt,
|
||||
SystemActivityChangeListener listener)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Dispatching SystemActivityEvent Listeners="
|
||||
+ listeners.size() + " evt=" + evt);
|
||||
|
||||
try
|
||||
{
|
||||
listener.activityChanged(evt);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
logger.error("Error delivering event", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the waiting thread.
|
||||
*/
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
stopped = false;
|
||||
|
||||
while(!stopped)
|
||||
{
|
||||
Map.Entry<SystemActivityEvent, Integer> eventToProcess = null;
|
||||
List<SystemActivityChangeListener> listenersCopy;
|
||||
|
||||
synchronized(eventsToDispatch)
|
||||
{
|
||||
if(eventsToDispatch.size() == 0)
|
||||
{
|
||||
try {
|
||||
eventsToDispatch.wait();
|
||||
}
|
||||
catch (InterruptedException iex){}
|
||||
}
|
||||
|
||||
//no point in dispatching if there's no one
|
||||
//listening
|
||||
if (listeners.size() == 0)
|
||||
continue;
|
||||
|
||||
//store the ref of the listener in case someone resets
|
||||
//it before we've had a chance to notify it.
|
||||
listenersCopy = new ArrayList
|
||||
<SystemActivityChangeListener>(listeners);
|
||||
|
||||
Iterator<Map.Entry<SystemActivityEvent, Integer>> iter =
|
||||
eventsToDispatch.entrySet().iterator();
|
||||
if(iter.hasNext())
|
||||
{
|
||||
eventToProcess = iter.next();
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if(eventToProcess != null && listenersCopy != null)
|
||||
{
|
||||
if(eventToProcess.getValue() > 0)
|
||||
synchronized(this)
|
||||
{
|
||||
try{
|
||||
wait(eventToProcess.getValue());
|
||||
}catch(Throwable t){}
|
||||
}
|
||||
|
||||
for (int i = 0; i < listenersCopy.size(); i++)
|
||||
{
|
||||
fireSystemActivityEvent(
|
||||
eventToProcess.getKey(),
|
||||
listenersCopy.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
eventToProcess = null;
|
||||
listenersCopy = null;
|
||||
}
|
||||
} catch(Throwable t)
|
||||
{
|
||||
logger.error("Error dispatching thread ended unexpectedly", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue