Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,23 @@

package io.appium.java_client.proxy;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.lang.ref.WeakReference;
import java.time.Duration;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Semaphore;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
class ProxyListenersContainer {
private static final Duration LISTENERS_CLEANUP_INTERVAL = Duration.ofMinutes(1);

private static ProxyListenersContainer INSTANCE;

public static synchronized ProxyListenersContainer getInstance() {
Expand All @@ -40,6 +42,21 @@ public static synchronized ProxyListenersContainer getInstance() {
return INSTANCE;
}

private ProxyListenersContainer() {
var task = new TimerTask() {
@Override
public void run() {
getListeners(null);
}
};
// Listeners are cleaned up lazily, e.g. every time getListeners API
// is called we also remove garbage-collected items. Although, due to an
// unpredictable nature of the garbage collector and no guarantees about the
// frequency of getListeners API calls we schedule the below loop to be executed every
// minute, and make sure there are no extra references to obsolete listeners
new Timer().scheduleAtFixedRate(task, 0, LISTENERS_CLEANUP_INTERVAL.toMillis());
}

private final Semaphore listenersGuard = new Semaphore(1);
private final List<Pair<WeakReference<?>, Collection<MethodCallListener>>> listenerPairs = new LinkedList<>();

Expand All @@ -55,7 +72,7 @@ private static class Pair<K, V> {
* Assign listeners for the particular proxied instance.
*
* @param proxyInstance The proxied instance.
* @param listeners Collection of listeners.
* @param listeners Collection of listeners.
* @return The same given instance.
*/
public <T> T setListeners(T proxyInstance, Collection<MethodCallListener> listeners) {
Expand Down