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")
|
@SuppressWarnings("rawtypes")
|
||||||
public final class ConstructorDetector {
|
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!
|
// Call this to load static methods and prevent errors during startup!
|
||||||
try {
|
try {
|
||||||
Init.start();
|
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.
|
* Initialize the ConstructorDetector, it is called from the Init class.
|
||||||
*/
|
*/
|
||||||
public static void init() {
|
static void init() {
|
||||||
if (constructorHashMap != null) {
|
if (constructorHashMap != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -59,6 +59,7 @@ public final class ConstructorDetector {
|
|||||||
* @return The class related to CONSTRUCTOR.
|
* @return The class related to CONSTRUCTOR.
|
||||||
*/
|
*/
|
||||||
public static Class getClass(int CONSTRUCTOR) {
|
public static Class getClass(int CONSTRUCTOR) {
|
||||||
|
tryInit();
|
||||||
return constructorHashMap.getOrDefault(CONSTRUCTOR, null);
|
return constructorHashMap.getOrDefault(CONSTRUCTOR, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +70,7 @@ public final class ConstructorDetector {
|
|||||||
* @return The CONSTRUCTOR.
|
* @return The CONSTRUCTOR.
|
||||||
*/
|
*/
|
||||||
public static int getConstructor(Class<? extends TdApi.Object> clazz) {
|
public static int getConstructor(Class<? extends TdApi.Object> clazz) {
|
||||||
|
tryInit();
|
||||||
return Objects.requireNonNull(constructorHashMapInverse.get(clazz));
|
return Objects.requireNonNull(constructorHashMapInverse.get(clazz));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,14 +32,16 @@ public final class Init {
|
|||||||
|
|
||||||
public static final Logger LOG = LoggerFactory.getLogger(Init.class);
|
public static final Logger LOG = LoggerFactory.getLogger(Init.class);
|
||||||
|
|
||||||
private static boolean started = false;
|
private static volatile boolean started = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize Tdlib
|
* Initialize Tdlib
|
||||||
*
|
*
|
||||||
* @throws CantLoadLibrary An exception that is thrown when the LoadLibrary class fails to load the library.
|
* @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) {
|
||||||
|
synchronized (Init.class) {
|
||||||
if (!started) {
|
if (!started) {
|
||||||
LoadLibrary.load("tdjni");
|
LoadLibrary.load("tdjni");
|
||||||
ConstructorDetector.init();
|
ConstructorDetector.init();
|
||||||
@ -51,4 +53,6 @@ public final class Init {
|
|||||||
started = true;
|
started = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,6 @@ public final class InternalClientManager implements AutoCloseable {
|
|||||||
private final AtomicLong currentQueryId = new AtomicLong();
|
private final AtomicLong currentQueryId = new AtomicLong();
|
||||||
|
|
||||||
private InternalClientManager(String implementationName) {
|
private InternalClientManager(String implementationName) {
|
||||||
try {
|
|
||||||
Init.start();
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
this.implementationName = implementationName;
|
this.implementationName = implementationName;
|
||||||
responseReceiver = new NativeResponseReceiver(this::handleClientEvents);
|
responseReceiver = new NativeResponseReceiver(this::handleClientEvents);
|
||||||
}
|
}
|
||||||
@ -46,6 +40,12 @@ public final class InternalClientManager implements AutoCloseable {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (startCalled.compareAndSet(false, true)) {
|
if (startCalled.compareAndSet(false, true)) {
|
||||||
|
try {
|
||||||
|
Init.start();
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
responseReceiver.start();
|
responseReceiver.start();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -54,14 +54,12 @@ public final class InternalClientManager implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static InternalClientManager get(String implementationName) {
|
public static InternalClientManager get(String implementationName) {
|
||||||
InternalClientManager clientManager = INSTANCE.updateAndGet(val -> {
|
return INSTANCE.updateAndGet(val -> {
|
||||||
if (val == null) {
|
if (val == null) {
|
||||||
return new InternalClientManager(implementationName);
|
return new InternalClientManager(implementationName);
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
});
|
});
|
||||||
clientManager.startIfNeeded();
|
|
||||||
return clientManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleClientEvents(int clientId,
|
private void handleClientEvents(int clientId,
|
||||||
@ -125,6 +123,7 @@ public final class InternalClientManager implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void registerClient(int clientId, ClientEventsHandler internalClient) {
|
public void registerClient(int clientId, ClientEventsHandler internalClient) {
|
||||||
|
this.startIfNeeded();
|
||||||
boolean replaced = registeredClientEventHandlers.put(clientId, internalClient) != null;
|
boolean replaced = registeredClientEventHandlers.put(clientId, internalClient) != null;
|
||||||
if (replaced) {
|
if (replaced) {
|
||||||
throw new IllegalStateException("Client " + clientId + " already registered");
|
throw new IllegalStateException("Client " + clientId + " already registered");
|
||||||
|
@ -277,6 +277,9 @@ abstract class ResponseReceiver extends Thread implements AutoCloseable {
|
|||||||
if (startCalled.get()) {
|
if (startCalled.get()) {
|
||||||
if (closeCalled.compareAndSet(false, true)) {
|
if (closeCalled.compareAndSet(false, true)) {
|
||||||
this.closeWait.await();
|
this.closeWait.await();
|
||||||
|
if (registeredClients.isEmpty()) {
|
||||||
|
this.interrupt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user