Skip to content

Commit

Permalink
chore: Perform listeners cleanup periodically (#2077)
Browse files Browse the repository at this point in the history
  • Loading branch information
mykola-mokhnach authored Nov 17, 2023
1 parent b082b37 commit 2bd4480
Showing 1 changed file with 21 additions and 4 deletions.
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

0 comments on commit 2bd4480

Please sign in to comment.