Created
July 22, 2016 09:32
-
-
Save arkangelx/e9399f4100f8dc2393d6b9cdd31ea366 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package io.socket.emitter; | |
import java.util.ArrayList; | |
import java.util.Iterator; | |
import java.util.List; | |
import java.util.concurrent.ConcurrentHashMap; | |
import java.util.concurrent.ConcurrentLinkedQueue; | |
import java.util.concurrent.ConcurrentMap; | |
/** | |
* The event emitter which is ported from the JavaScript module. This class is thread-safe. | |
* | |
* @see <a href="https://github.com/component/emitter">https://github.com/component/emitter</a> | |
*/ | |
public class Emitter { | |
private ConcurrentMap<String, ConcurrentLinkedQueue<Listener>> callbacks | |
= new ConcurrentHashMap<String, ConcurrentLinkedQueue<Listener>>(); | |
/** | |
* Listens on the event. | |
* @param event event name. | |
* @param fn | |
* @return a reference to this object. | |
*/ | |
public Emitter on(String event, Listener fn) { | |
ConcurrentLinkedQueue<Listener> callbacks = this.callbacks.get(event); | |
if (callbacks == null) { | |
callbacks = new ConcurrentLinkedQueue <Listener>(); | |
ConcurrentLinkedQueue<Listener> _callbacks = this.callbacks.putIfAbsent(event, callbacks); | |
if (_callbacks != null) { | |
callbacks = _callbacks; | |
} | |
} | |
callbacks.add(fn); | |
return this; | |
} | |
/** | |
* Adds a one time listener for the event. | |
* | |
* @param event an event name. | |
* @param fn | |
* @return a reference to this object. | |
*/ | |
public Emitter once(final String event, final Listener fn) { | |
this.on(event, new OnceListener(event, fn)); | |
return this; | |
} | |
/** | |
* Removes all registered listeners. | |
* | |
* @return a reference to this object. | |
*/ | |
public Emitter off() { | |
this.callbacks.clear(); | |
return this; | |
} | |
/** | |
* Removes all listeners of the specified event. | |
* | |
* @param event an event name. | |
* @return a reference to this object. | |
*/ | |
public Emitter off(String event) { | |
this.callbacks.remove(event); | |
return this; | |
} | |
/** | |
* Removes the listener. | |
* | |
* @param event an event name. | |
* @param fn | |
* @return a reference to this object. | |
*/ | |
public Emitter off(String event, Listener fn) { | |
ConcurrentLinkedQueue<Listener> callbacks = this.callbacks.get(event); | |
if (callbacks != null) { | |
Iterator<Listener> it = callbacks.iterator(); | |
while (it.hasNext()) { | |
Listener internal = it.next(); | |
if (Emitter.sameAs(fn, internal)) { | |
it.remove(); | |
break; | |
} | |
} | |
} | |
return this; | |
} | |
private static boolean sameAs(Listener fn, Listener internal) { | |
if (fn.equals(internal)) { | |
return true; | |
} else if (internal instanceof OnceListener) { | |
return fn.equals(((OnceListener) internal).fn); | |
} else { | |
return false; | |
} | |
} | |
/** | |
* Executes each of listeners with the given args. | |
* | |
* @param event an event name. | |
* @param args | |
* @return a reference to this object. | |
*/ | |
public Emitter emit(String event, Object... args) { | |
ConcurrentLinkedQueue<Listener> callbacks = this.callbacks.get(event); | |
if (callbacks != null) { | |
for (Listener fn : callbacks) { | |
fn.call(args); | |
} | |
} | |
return this; | |
} | |
/** | |
* Returns a list of listeners for the specified event. | |
* | |
* @param event an event name. | |
* @return a reference to this object. | |
*/ | |
public List<Listener> listeners(String event) { | |
ConcurrentLinkedQueue<Listener> callbacks = this.callbacks.get(event); | |
return callbacks != null ? | |
new ArrayList<Listener>(callbacks) : new ArrayList<Listener>(0); | |
} | |
/** | |
* Check if this emitter has listeners for the specified event. | |
* | |
* @param event an event name. | |
* @return a reference to this object. | |
*/ | |
public boolean hasListeners(String event) { | |
ConcurrentLinkedQueue<Listener> callbacks = this.callbacks.get(event); | |
return callbacks != null && !callbacks.isEmpty(); | |
} | |
public static interface Listener { | |
public void call(Object... args); | |
} | |
private class OnceListener implements Listener { | |
public final String event; | |
public final Listener fn; | |
public OnceListener(String event, Listener fn) { | |
this.event = event; | |
this.fn = fn; | |
} | |
@Override | |
public void call(Object... args) { | |
Emitter.this.off(this.event, this); | |
this.fn.call(args); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment