/** * 第一步:通过subscriptionsByEventType得到该事件类型所有订阅者信息队列,根据优先级将当前订阅者信息插入到订阅者队列subscriptionsByEventType中; * 第二步:在typesBySubscriber中得到当前订阅者订阅的所有事件队列,将此事件保存到队列typesBySubscriber中,用于后续取消订阅; 第三步:检查这个事件是否是 * Sticky 事件,如果是则从stickyEvents事件保存队列中取出该事件类型最后一个事件发送给当前订阅者。 * * @param subscriber * @param subscriberMethod * @param sticky * @param priority */ private void subscribe( Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) { Class<?> eventType = subscriberMethod.eventType; CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType); // 通过subscriptionsByEventType得到该事件类型所有订阅者信息队列 Subscription newSubscription = new Subscription(subscriber, subscriberMethod, priority); // 根据当前的eventType,在subscriptionsByEventType生成对应的key-value(没有则加入,有则跳过次处理) if (subscriptions == null) { subscriptions = new CopyOnWriteArrayList<Subscription>(); subscriptionsByEventType.put(eventType, subscriptions); } else { if (subscriptions.contains(newSubscription)) { throw new EventBusException( "Subscriber " + subscriber.getClass() + " already registered to event " + eventType); } } // Starting with EventBus 2.2 we enforced methods to be public (might change with annotations // again) // subscriberMethod.method.setAccessible(true); // 根据优先级将当前订阅者信息插入到订阅者队列subscriptionsByEventType中; int size = subscriptions.size(); for (int i = 0; i <= size; i++) { if (i == size || newSubscription.priority > subscriptions.get(i).priority) { subscriptions.add(i, newSubscription); break; } } // 在typesBySubscriber中得到当前订阅者订阅的所有事件队列,将此事件保存到队列typesBySubscriber中,用于后续取消订阅; List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber); if (subscribedEvents == null) { subscribedEvents = new ArrayList<Class<?>>(); typesBySubscriber.put(subscriber, subscribedEvents); } subscribedEvents.add(eventType); // 检查这个事件是否是 Sticky 事件,如果是,则从stickyEvents事件保存队列中取出该事件类型最后一个事件发送给当前订阅者。 if (sticky) { if (eventInheritance) { // Existing sticky events of all subclasses of eventType have to be considered. // Note: Iterating over all events may be inefficient with lots of sticky events, // thus data structure should be changed to allow a more efficient lookup // (e.g. an additional map storing sub classes of super classes: Class -> List<Class>). Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet(); for (Map.Entry<Class<?>, Object> entry : entries) { Class<?> candidateEventType = entry.getKey(); if (eventType.isAssignableFrom( candidateEventType)) { // 是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或接口 Object stickyEvent = entry.getValue(); checkPostStickyEventToSubscription(newSubscription, stickyEvent); } } } else { Object stickyEvent = stickyEvents.get(eventType); checkPostStickyEventToSubscription(newSubscription, stickyEvent); } } }
private final boolean private_callProcedure( ProcedureCallback callback, int expectedSerializedSize, ProcedureInvocation invocation, long timeoutNanos) throws IOException, NoConnectionsException { if (m_isShutdown) { return false; } if (callback == null) { callback = new NullCallback(); } // Blessed threads (the ones that invoke callbacks) are not subject to backpressure boolean isBlessed = m_blessedThreadIds.contains(Thread.currentThread().getId()); if (m_blockingQueue) { while (!m_distributer.queue(invocation, callback, isBlessed, timeoutNanos)) { try { backpressureBarrier(); } catch (InterruptedException e) { throw new java.io.InterruptedIOException( "Interrupted while invoking procedure asynchronously"); } } return true; } else { return m_distributer.queue(invocation, callback, isBlessed, timeoutNanos); } }
/** * Removes the specified driver from the {@code DriverManager}'s list of registered drivers. * * <p>If a {@code null} value is specified for the driver to be removed, then no action is taken. * * <p>If a security manager exists and its {@code checkPermission} denies permission, then a * {@code SecurityException} will be thrown. * * <p>If the specified driver is not found in the list of registered drivers, then no action is * taken. If the driver was found, it will be removed from the list of registered drivers. * * <p>If a {@code DriverAction} instance was specified when the JDBC driver was registered, its * deregister method will be called prior to the driver being removed from the list of registered * drivers. * * @param driver the JDBC Driver to remove * @exception SQLException if a database access error occurs * @throws SecurityException if a security manager exists and its {@code checkPermission} method * denies permission to deregister a driver. * @see SecurityManager#checkPermission */ @CallerSensitive public static synchronized void deregisterDriver(Driver driver) throws SQLException { if (driver == null) { return; } SecurityManager sec = System.getSecurityManager(); if (sec != null) { sec.checkPermission(DEREGISTER_DRIVER_PERMISSION); } println("DriverManager.deregisterDriver: " + driver); DriverInfo aDriver = new DriverInfo(driver, null); if (registeredDrivers.contains(aDriver)) { if (isDriverAllowed(driver, Reflection.getCallerClass())) { DriverInfo di = registeredDrivers.get(registeredDrivers.indexOf(aDriver)); // If a DriverAction was specified, Call it to notify the // driver that it has been deregistered if (di.action() != null) { di.action().deregister(); } registeredDrivers.remove(aDriver); } else { // If the caller does not have permission to load the driver then // throw a SecurityException. throw new SecurityException(); } } else { println(" couldn't find driver to unload"); } }
private final ClientResponse callProcedure( SyncCallback cb, long nowNanos, long timeout, ProcedureInvocation invocation) throws IOException, NoConnectionsException, ProcCallException { if (m_isShutdown) { throw new NoConnectionsException("Client instance is shutdown"); } if (m_blessedThreadIds.contains(Thread.currentThread().getId())) { throw new IOException( "Can't invoke a procedure synchronously from with the client callback thread " + " without deadlocking the client library"); } m_distributer.queue(invocation, cb, true, nowNanos, timeout); try { cb.waitForResponse(); } catch (final InterruptedException e) { throw new java.io.InterruptedIOException("Interrupted while waiting for response"); } if (cb.getResponse().getStatus() != ClientResponse.SUCCESS) { throw new ProcCallException(cb.getResponse(), cb.getResponse().getStatusString(), null); } // cb.result() throws ProcCallException if procedure failed return cb.getResponse(); }
/** * Add listener using the specified frequency. Must be de-regsitered again using removeListener * * @param listener * @param frequency the frequency to call this listener. One of FREQUENCY_HIGH, FREQUENCY_MEDIUM, * FREQUENCY_LOW */ public void addListener(HeartListener listen, int frequency) { if (!highFrequencyListeners.contains(listen) && !mediumFrequencyListeners.contains(listen) && !lowFrequencyListeners.contains(listen)) { switch (frequency) { case FREQUENCY_HIGH: highFrequencyListeners.add(listen); break; case FREQUENCY_MEDIUM: mediumFrequencyListeners.add(listen); break; case FREQUENCY_LOW: lowFrequencyListeners.add(listen); break; } } }
private final boolean private_callProcedure( ProcedureCallback callback, int expectedSerializedSize, ProcedureInvocation invocation, long timeoutNanos) throws IOException, NoConnectionsException { if (m_isShutdown) { return false; } if (callback == null) { callback = new NullCallback(); } final long nowNanos = System.nanoTime(); // Blessed threads (the ones that invoke callbacks) are not subject to backpressure boolean isBlessed = m_blessedThreadIds.contains(Thread.currentThread().getId()); if (m_blockingQueue) { while (!m_distributer.queue(invocation, callback, isBlessed, nowNanos, timeoutNanos)) { /* * Wait on backpressure honoring the timeout settings */ final long delta = Math.max(1, System.nanoTime() - nowNanos); final long timeout = timeoutNanos == Distributer.USE_DEFAULT_CLIENT_TIMEOUT ? m_distributer.getProcedureTimeoutNanos() : timeoutNanos; try { if (backpressureBarrier(nowNanos, timeout - delta)) { final ClientResponseImpl r = new ClientResponseImpl( ClientResponse.CONNECTION_TIMEOUT, ClientResponse.UNINITIALIZED_APP_STATUS_CODE, "", new VoltTable[0], String.format( "No response received in the allotted time (set to %d ms).", TimeUnit.NANOSECONDS.toMillis(timeoutNanos))); try { callback.clientCallback(r); } catch (Throwable t) { m_distributer.uncaughtException(callback, r, t); } } } catch (InterruptedException e) { throw new java.io.InterruptedIOException( "Interrupted while invoking procedure asynchronously"); } } return true; } else { return m_distributer.queue(invocation, callback, isBlessed, nowNanos, timeoutNanos); } }
@Override public synchronized void add(int index, Layer layer) { if (mLayerList.contains(layer)) throw new IllegalArgumentException("layer added twice"); if (layer instanceof UpdateListener) mMap.events.bind((UpdateListener) layer); if (layer instanceof InputListener) mMap.input.bind((InputListener) layer); mLayerList.add(index, layer); mDirtyLayers = true; }
@Override public void drain() throws InterruptedException { if (m_isShutdown) { return; } if (m_blessedThreadIds.contains(Thread.currentThread().getId())) { throw new RuntimeException( "Can't invoke backpressureBarrier from within the client callback thread " + " without deadlocking the client library"); } m_distributer.drain(); }
@Override public synchronized Layer set(int index, Layer layer) { if (mLayerList.contains(layer)) throw new IllegalArgumentException("layer added twice"); mDirtyLayers = true; Layer remove = mLayerList.set(index, layer); // unbind replaced layer if (remove instanceof UpdateListener) mMap.events.unbind((UpdateListener) remove); if (remove instanceof InputListener) mMap.input.unbind((InputListener) remove); return remove; }
/** * Shutdown the client closing all network connections and release all memory resources. * * @throws InterruptedException */ @Override public void close() throws InterruptedException { if (m_blessedThreadIds.contains(Thread.currentThread().getId())) { throw new RuntimeException( "Can't invoke backpressureBarrier from within the client callback thread " + " without deadlocking the client library"); } m_isShutdown = true; synchronized (m_backpressureLock) { m_backpressureLock.notifyAll(); } m_distributer.shutdown(); }
public void registerEventListener(String event, GeckoEventListener listener) { synchronized (mEventListeners) { CopyOnWriteArrayList<GeckoEventListener> listeners = mEventListeners.get(event); if (listeners == null) { // create a CopyOnWriteArrayList so that we can modify it // concurrently with iterating through it in handleGeckoMessage. // Otherwise we could end up throwing a ConcurrentModificationException. listeners = new CopyOnWriteArrayList<GeckoEventListener>(); } else if (listeners.contains(listener)) { Log.w( LOGTAG, "EventListener already registered for event '" + event + "'", new IllegalArgumentException()); } listeners.add(listener); mEventListeners.put(event, listeners); } }
@Override public void backpressureBarrier() throws InterruptedException { if (m_isShutdown) { return; } if (m_blessedThreadIds.contains(Thread.currentThread().getId())) { throw new RuntimeException( "Can't invoke backpressureBarrier from within the client callback thread " + " without deadlocking the client library"); } if (m_backpressure) { synchronized (m_backpressureLock) { if (m_backpressure) { while (m_backpressure && !m_isShutdown) { m_backpressureLock.wait(); } } } } }
/** * Wait on backpressure with a timeout. Returns true on timeout, false otherwise. Timeout nanos is * the initial timeout quantity which will be adjusted to reflect remaining time on spurious * wakeups */ public boolean backpressureBarrier(final long start, long timeoutNanos) throws InterruptedException { if (m_isShutdown) { return false; } if (m_blessedThreadIds.contains(Thread.currentThread().getId())) { throw new RuntimeException( "Can't invoke backpressureBarrier from within the client callback thread " + " without deadlocking the client library"); } if (m_backpressure) { synchronized (m_backpressureLock) { if (m_backpressure) { while (m_backpressure && !m_isShutdown) { if (start != 0) { // Wait on the condition for the specified timeout remaining m_backpressureLock.wait( timeoutNanos / TimeUnit.MILLISECONDS.toNanos(1), (int) (timeoutNanos % TimeUnit.MILLISECONDS.toNanos(1))); // Condition is true, break and return false if (!m_backpressure) break; // Calculate whether the timeout should be triggered final long nowNanos = System.nanoTime(); final long deltaNanos = Math.max(1, nowNanos - start); if (deltaNanos >= timeoutNanos) { return true; } // Reassigning timeout nanos with remainder of timeout timeoutNanos -= deltaNanos; } else { m_backpressureLock.wait(); } } } } } return false; }
public void addPlanetSelectedListener(OnPlanetSelectedListener listener) { if (!mPlanetSelectedListeners.contains(listener)) { mPlanetSelectedListeners.add(listener); } }
@Override public void addListener(INetworkConnectionListener listener) { if (!listeners.contains(listener)) { listeners.add(listener); } }
public void registerListener(SmilesListener listener) { if (!listeners.contains(listener)) { listeners.add(listener); } }
/** * Add a data callback. * * @param dataCallback the data callback */ public void addDataCallback(OneSheeldDataCallback dataCallback) { if (dataCallback != null && !dataCallbacks.contains(dataCallback)) dataCallbacks.add(dataCallback); }
/** * Add an error callback. * * @param errorCallback the error callback */ public void addErrorCallback(OneSheeldErrorCallback errorCallback) { if (errorCallback != null && !errorCallbacks.contains(errorCallback)) errorCallbacks.add(errorCallback); }
/** * Add a version query callback. * * @param versionQueryCallback the version query callback */ public void addVersionQueryCallback(OneSheeldVersionQueryCallback versionQueryCallback) { if (versionQueryCallback != null && !versionQueryCallbacks.contains(versionQueryCallback)) versionQueryCallbacks.add(versionQueryCallback); }
/** * @param String * @return boolean */ public boolean contains(String str) { return (m_channelTopics.contains(str)); }
/** * Remove a connection callback. * * @param connectionCallback the connection callback */ public void removeConnectionCallback(OneSheeldConnectionCallback connectionCallback) { if (connectionCallback != null && connectionCallbacks.contains(connectionCallback)) connectionCallbacks.remove(connectionCallback); }
/** * Remove an error callback. * * @param errorCallback the error callback */ public void removeErrorCallback(OneSheeldErrorCallback errorCallback) { if (errorCallback != null && errorCallbacks.contains(errorCallback)) errorCallbacks.remove(errorCallback); }
/** * Remove a data callback. * * @param dataCallback the data callback */ public void removeDataCallback(OneSheeldDataCallback dataCallback) { if (dataCallback != null && dataCallbacks.contains(dataCallback)) dataCallbacks.remove(dataCallback); }
/** * Add a connection callback. * * @param connectionCallback the connection callback */ public void addConnectionCallback(OneSheeldConnectionCallback connectionCallback) { if (connectionCallback != null && !connectionCallbacks.contains(connectionCallback)) connectionCallbacks.add(connectionCallback); }
public void addDialog(DialogWrapper d) { if (!dialogs.contains(d)) { dialogs.add(d); } }
/** * Remove a version query callback. * * @param versionQueryCallback the version query callback */ public void removeVersionQueryCallback(OneSheeldVersionQueryCallback versionQueryCallback) { if (versionQueryCallback != null && versionQueryCallbacks.contains(versionQueryCallback)) versionQueryCallbacks.remove(versionQueryCallback); }
@Override public boolean contains(final Object o) { return copyOnWriteArrayList.contains(o); }
@Override public void onNewShieldFrameReceived(ShieldFrame frame) { if (frame.getShieldId() == UIShield.DATA_LOGGER.getId()) { switch (frame.getFunctionId()) { case START_LOGGING: if (frame.getArguments().size() > 0) fileName = frame.getArgumentAsString(0); else fileName = null; headerList = new CopyOnWriteArrayList<String>(); dataSet = new ArrayList<Map<String, String>>(); rowData = new HashMap<String, String>(); currentStatus = LOGGING; isStarted = true; if (eventHandler != null) { eventHandler.onStartLogging(); } break; case STOP_LOGGING: saveData(); break; case ADD_STRING: if (isStarted) { currentStatus = LOGGING; String key = frame.getArgumentAsString(0); String value = frame.getArgumentAsString(1); if (!headerList.contains(key)) headerList.add(key); rowData.put(key, value); if (eventHandler != null) { eventHandler.onAdd(key, value); } } break; case ADD_FLOAT: if (isStarted) { currentStatus = LOGGING; String keyFloat = frame.getArgumentAsString(0); String valueFloat = frame.getArgumentAsFloat(1) + ""; if (!headerList.contains(keyFloat)) headerList.add(keyFloat); rowData.put(keyFloat, valueFloat); if (eventHandler != null) { eventHandler.onAdd(keyFloat, valueFloat); } } break; case LOG: if (isStarted) { currentStatus = LOGGING; if (eventHandler != null) { eventHandler.onLog(new HashMap<>(rowData)); } if (!headerList.contains("Time")) headerList.add("Time"); rowData.put( "Time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US) .format(new Date()) .toString()); // rowData.remove("Time"); dataSet.add(new HashMap<>(rowData)); rowData = new HashMap<>(); } break; default: break; } } }