![JAR search and dependency download from the Maven repository](/logo.png)
co.easimart.CachedCurrentInstallationController Maven / Gradle / Ivy
package co.easimart;
import bolts.Continuation;
import bolts.Task;
/** package */ class CachedCurrentInstallationController
implements EasimartCurrentInstallationController {
/* package */ static final String TAG = "co.easimart.CachedCurrentInstallationController";
/*
* Note about lock ordering:
*
* You must NOT acquire the EasimartInstallation instance mutex (the "mutex" field in EasimartObject)
* while holding this current installation lock. (We used to use the EasimartInstallation.class lock,
* but moved on to an explicit lock object since anyone could acquire the EasimartInstallation.class
* lock as EasimartInstallation is a public class.) Acquiring the instance mutex while holding this
* current installation lock will lead to a deadlock. Here is an example:
* https://phabricator.fb.com/P3251091
*/
private final Object mutex = new Object();
private final TaskQueue taskQueue = new TaskQueue();
private final EasimartObjectStore store;
private final InstallationId installationId;
// The "current installation" is the installation for this device. Protected by
// mutex.
/* package for test */ EasimartInstallation currentInstallation;
public CachedCurrentInstallationController(
EasimartObjectStore store, InstallationId installationId) {
this.store = store;
this.installationId = installationId;
}
@Override
public Task setAsync(final EasimartInstallation installation) {
if (!isCurrent(installation)) {
return Task.forResult(null);
}
return taskQueue.enqueue(new Continuation>() {
@Override
public Task then(Task toAwait) throws Exception {
return toAwait.continueWithTask(new Continuation>() {
@Override
public Task then(Task task) throws Exception {
return store.setAsync(installation);
}
}).continueWithTask(new Continuation>() {
@Override
public Task then(Task task) throws Exception {
installationId.set(installation.getInstallationId());
return task;
}
}, EasimartExecutors.io());
}
});
}
@Override
public Task getAsync() {
synchronized (mutex) {
if (currentInstallation != null) {
return Task.forResult(currentInstallation);
}
}
return taskQueue.enqueue(new Continuation>() {
@Override
public Task then(Task toAwait) throws Exception {
return toAwait.continueWithTask(new Continuation>() {
@Override
public Task then(Task task) throws Exception {
synchronized (mutex) {
if (currentInstallation != null) {
return Task.forResult(currentInstallation);
}
}
return store.getAsync().continueWith(new Continuation() {
@Override
public EasimartInstallation then(Task task) throws Exception {
EasimartInstallation current = task.getResult();
if (current == null) {
current = EasimartObject.create(EasimartInstallation.class);
current.updateDeviceInfo(installationId);
} else {
installationId.set(current.getInstallationId());
EasimartLog.v(TAG, "Successfully deserialized Installation object");
}
synchronized (mutex) {
currentInstallation = current;
}
return current;
}
}, EasimartExecutors.io());
}
});
}
});
}
@Override
public Task existsAsync() {
synchronized (mutex) {
if (currentInstallation != null) {
return Task.forResult(true);
}
}
return taskQueue.enqueue(new Continuation>() {
@Override
public Task then(Task toAwait) throws Exception {
return toAwait.continueWithTask(new Continuation>() {
@Override
public Task then(Task task) throws Exception {
return store.existsAsync();
}
});
}
});
}
@Override
public void clearFromMemory() {
synchronized (mutex) {
currentInstallation = null;
}
}
@Override
public void clearFromDisk() {
synchronized (mutex) {
currentInstallation = null;
}
try {
installationId.clear();
EasimartTaskUtils.wait(store.deleteAsync());
} catch (EasimartException e) {
// ignored
}
}
@Override
public boolean isCurrent(EasimartInstallation installation) {
synchronized (mutex) {
return currentInstallation == installation;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy