Add locks to prevent reading updates when destroying the client
This commit is contained in:
parent
4d909e986e
commit
e92c04098f
@ -22,6 +22,8 @@ public class Client extends NativeClient implements TelegramClient {
|
|||||||
|
|
||||||
private ClientState state = ClientState.of(false, 0, false, false, false);
|
private ClientState state = ClientState.of(false, 0, false, false, false);
|
||||||
private final ReentrantReadWriteLock stateLock = new ReentrantReadWriteLock();
|
private final ReentrantReadWriteLock stateLock = new ReentrantReadWriteLock();
|
||||||
|
private final ReentrantReadWriteLock updatesLock = new ReentrantReadWriteLock();
|
||||||
|
private final ReentrantReadWriteLock responsesLock = new ReentrantReadWriteLock();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new TDLib client.
|
* Creates a new TDLib client.
|
||||||
@ -53,25 +55,35 @@ public class Client extends NativeClient implements TelegramClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Response> receive(double timeout, int eventsSize, boolean receiveResponses, boolean receiveUpdates) {
|
public List<Response> receive(double timeout, int eventsSize, boolean receiveResponses, boolean receiveUpdates) {
|
||||||
long clientId;
|
if (receiveResponses) responsesLock.readLock().lock();
|
||||||
stateLock.readLock().lock();
|
|
||||||
try {
|
try {
|
||||||
if (!state.isInitialized()) {
|
if (receiveUpdates) updatesLock.readLock().lock();
|
||||||
sleep(timeout);
|
try {
|
||||||
return Collections.emptyList();
|
long clientId;
|
||||||
}
|
stateLock.readLock().lock();
|
||||||
requireInitialized();
|
try {
|
||||||
if (!state.isReadyToReceive()) {
|
if (!state.isInitialized()) {
|
||||||
sleep(timeout);
|
sleep(timeout);
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
requireReadyToReceive();
|
requireInitialized();
|
||||||
clientId = state.getClientId();
|
if (!state.isReadyToReceive()) {
|
||||||
} finally {
|
sleep(timeout);
|
||||||
stateLock.readLock().unlock();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
requireReadyToReceive();
|
||||||
|
clientId = state.getClientId();
|
||||||
|
} finally {
|
||||||
|
stateLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
|
||||||
return Arrays.asList(this.internalReceive(clientId, timeout, eventsSize, receiveResponses, receiveUpdates));
|
return Arrays.asList(this.internalReceive(clientId, timeout, eventsSize, receiveResponses, receiveUpdates));
|
||||||
|
} finally {
|
||||||
|
if (receiveUpdates) updatesLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (receiveResponses) responsesLock.readLock().unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sleep(double timeout) {
|
private void sleep(double timeout) {
|
||||||
@ -87,31 +99,41 @@ public class Client extends NativeClient implements TelegramClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response receive(double timeout, boolean receiveResponses, boolean receiveUpdates) {
|
public Response receive(double timeout, boolean receiveResponses, boolean receiveUpdates) {
|
||||||
long clientId;
|
responsesLock.readLock().lock();
|
||||||
stateLock.readLock().lock();
|
|
||||||
try {
|
try {
|
||||||
if (!state.isInitialized()) {
|
updatesLock.readLock().lock();
|
||||||
sleep(timeout);
|
try {
|
||||||
|
long clientId;
|
||||||
|
stateLock.readLock().lock();
|
||||||
|
try {
|
||||||
|
if (!state.isInitialized()) {
|
||||||
|
sleep(timeout);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
requireInitialized();
|
||||||
|
if (!state.isReadyToReceive()) {
|
||||||
|
sleep(timeout);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
requireReadyToReceive();
|
||||||
|
clientId = state.getClientId();
|
||||||
|
} finally {
|
||||||
|
stateLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
Response[] responses = this.internalReceive(clientId, timeout, 1, receiveResponses, receiveUpdates);
|
||||||
|
|
||||||
|
if (responses.length > 0) {
|
||||||
|
return responses[0];
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
} finally {
|
||||||
|
updatesLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
requireInitialized();
|
|
||||||
if (!state.isReadyToReceive()) {
|
|
||||||
sleep(timeout);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
requireReadyToReceive();
|
|
||||||
clientId = state.getClientId();
|
|
||||||
} finally {
|
} finally {
|
||||||
stateLock.readLock().unlock();
|
responsesLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
Response[] responses = this.internalReceive(clientId, timeout, 1, receiveResponses, receiveUpdates);
|
|
||||||
|
|
||||||
if (responses.length > 0) {
|
|
||||||
return responses[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response[] internalReceive(long clientId, double timeout, int eventsSize, boolean receiveResponses, boolean receiveUpdates) {
|
private Response[] internalReceive(long clientId, double timeout, int eventsSize, boolean receiveResponses, boolean receiveUpdates) {
|
||||||
@ -187,30 +209,50 @@ public class Client extends NativeClient implements TelegramClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroyClient() {
|
public void destroyClient() {
|
||||||
stateLock.writeLock().lock();
|
responsesLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
if (state.isInitialized() && state.hasClientId()) {
|
updatesLock.writeLock().lock();
|
||||||
if (state.isReadyToSend() || state.isReadyToReceive()) {
|
try {
|
||||||
throw new IllegalStateException("You need to close the Client before destroying it!");
|
stateLock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
if (state.isInitialized() && state.hasClientId()) {
|
||||||
|
if (state.isReadyToSend() || state.isReadyToReceive()) {
|
||||||
|
throw new IllegalStateException("You need to close the Client before destroying it!");
|
||||||
|
}
|
||||||
|
destroyNativeClient(this.state.getClientId());
|
||||||
|
state = ClientState.of(false, 0, false, false, false);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
stateLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
destroyNativeClient(this.state.getClientId());
|
} finally {
|
||||||
state = ClientState.of(false, 0, false, false, false);
|
updatesLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
stateLock.writeLock().unlock();
|
responsesLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeClient() {
|
public void initializeClient() {
|
||||||
stateLock.writeLock().lock();
|
responsesLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
if (!state.isInitialized() && !state.hasClientId()) {
|
updatesLock.writeLock().lock();
|
||||||
long clientId = createNativeClient();
|
try {
|
||||||
state = ClientState.of(true, clientId, true, true, false);
|
stateLock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
if (!state.isInitialized() && !state.hasClientId()) {
|
||||||
|
long clientId = createNativeClient();
|
||||||
|
state = ClientState.of(true, clientId, true, true, false);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
stateLock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
updatesLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
stateLock.writeLock().unlock();
|
responsesLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user