Lazy initialization of tdlib native library
This commit is contained in:
parent
781b00eb1e
commit
9f1a4e5292
@ -28,7 +28,10 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
@SuppressWarnings("rawtypes")
|
||||
public final class ConstructorDetector {
|
||||
|
||||
static {
|
||||
private static ConcurrentHashMap<Integer, Class> constructorHashMap;
|
||||
private static ConcurrentHashMap<Class, Integer> 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<Integer, Class> constructorHashMap;
|
||||
private static ConcurrentHashMap<Class, Integer> 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<? extends TdApi.Object> clazz) {
|
||||
tryInit();
|
||||
return Objects.requireNonNull(constructorHashMapInverse.get(clazz));
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user