diff --git a/src/main/java/it/tdlight/common/ConstructorDetector.java b/src/main/java/it/tdlight/common/ConstructorDetector.java index ca0904e..03d4c73 100644 --- a/src/main/java/it/tdlight/common/ConstructorDetector.java +++ b/src/main/java/it/tdlight/common/ConstructorDetector.java @@ -28,7 +28,10 @@ import java.util.concurrent.ConcurrentHashMap; @SuppressWarnings("rawtypes") public final class ConstructorDetector { - static { + private static ConcurrentHashMap constructorHashMap; + private static ConcurrentHashMap constructorHashMapInverse; + + private static void tryInit() { // Call this to load static methods and prevent errors during startup! try { Init.start(); @@ -37,13 +40,10 @@ public final class ConstructorDetector { } } - private static ConcurrentHashMap constructorHashMap; - private static ConcurrentHashMap constructorHashMapInverse; - /** * Initialize the ConstructorDetector, it is called from the Init class. */ - public static void init() { + static void init() { if (constructorHashMap != null) { return; } @@ -59,6 +59,7 @@ public final class ConstructorDetector { * @return The class related to CONSTRUCTOR. */ public static Class getClass(int CONSTRUCTOR) { + tryInit(); return constructorHashMap.getOrDefault(CONSTRUCTOR, null); } @@ -69,6 +70,7 @@ public final class ConstructorDetector { * @return The CONSTRUCTOR. */ public static int getConstructor(Class clazz) { + tryInit(); return Objects.requireNonNull(constructorHashMapInverse.get(clazz)); } diff --git a/src/main/java/it/tdlight/common/Init.java b/src/main/java/it/tdlight/common/Init.java index 018e97a..4e6b4fc 100644 --- a/src/main/java/it/tdlight/common/Init.java +++ b/src/main/java/it/tdlight/common/Init.java @@ -32,23 +32,27 @@ public final class Init { public static final Logger LOG = LoggerFactory.getLogger(Init.class); - private static boolean started = false; + private static volatile boolean started = false; /** * Initialize Tdlib * * @throws CantLoadLibrary An exception that is thrown when the LoadLibrary class fails to load the library. */ - public synchronized static void start() throws CantLoadLibrary { + public static void start() throws CantLoadLibrary { if (!started) { - LoadLibrary.load("tdjni"); - ConstructorDetector.init(); - try { - NativeClientAccess.execute(new SetLogVerbosityLevel(1)); - } catch (Throwable ex) { - LOG.error("Can't set verbosity level on startup", ex); + synchronized (Init.class) { + if (!started) { + LoadLibrary.load("tdjni"); + ConstructorDetector.init(); + try { + NativeClientAccess.execute(new SetLogVerbosityLevel(1)); + } catch (Throwable ex) { + LOG.error("Can't set verbosity level on startup", ex); + } + started = true; + } } - started = true; } } } diff --git a/src/main/java/it/tdlight/common/internal/InternalClientManager.java b/src/main/java/it/tdlight/common/internal/InternalClientManager.java index 056cc2c..3182722 100644 --- a/src/main/java/it/tdlight/common/internal/InternalClientManager.java +++ b/src/main/java/it/tdlight/common/internal/InternalClientManager.java @@ -28,12 +28,6 @@ public final class InternalClientManager implements AutoCloseable { private final AtomicLong currentQueryId = new AtomicLong(); private InternalClientManager(String implementationName) { - try { - Init.start(); - } catch (Throwable ex) { - ex.printStackTrace(); - System.exit(1); - } this.implementationName = implementationName; responseReceiver = new NativeResponseReceiver(this::handleClientEvents); } @@ -46,6 +40,12 @@ public final class InternalClientManager implements AutoCloseable { return false; } if (startCalled.compareAndSet(false, true)) { + try { + Init.start(); + } catch (Throwable ex) { + ex.printStackTrace(); + System.exit(1); + } responseReceiver.start(); return true; } else { @@ -54,14 +54,12 @@ public final class InternalClientManager implements AutoCloseable { } public static InternalClientManager get(String implementationName) { - InternalClientManager clientManager = INSTANCE.updateAndGet(val -> { + return INSTANCE.updateAndGet(val -> { if (val == null) { return new InternalClientManager(implementationName); } return val; }); - clientManager.startIfNeeded(); - return clientManager; } private void handleClientEvents(int clientId, @@ -125,6 +123,7 @@ public final class InternalClientManager implements AutoCloseable { } public void registerClient(int clientId, ClientEventsHandler internalClient) { + this.startIfNeeded(); boolean replaced = registeredClientEventHandlers.put(clientId, internalClient) != null; if (replaced) { throw new IllegalStateException("Client " + clientId + " already registered"); diff --git a/src/main/java/it/tdlight/common/internal/ResponseReceiver.java b/src/main/java/it/tdlight/common/internal/ResponseReceiver.java index 22e2081..9445a82 100644 --- a/src/main/java/it/tdlight/common/internal/ResponseReceiver.java +++ b/src/main/java/it/tdlight/common/internal/ResponseReceiver.java @@ -277,6 +277,9 @@ abstract class ResponseReceiver extends Thread implements AutoCloseable { if (startCalled.get()) { if (closeCalled.compareAndSet(false, true)) { this.closeWait.await(); + if (registeredClients.isEmpty()) { + this.interrupt(); + } } } }