All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.parse.CachedCurrentInstallationController Maven / Gradle / Ivy

Go to download

A library that gives you access to the powerful Parse cloud platform from your Android app.

There is a newer version: 1.17.3
Show newest version
/*
 * Copyright (c) 2015-present, Parse, LLC.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
package com.parse;

import bolts.Continuation;
import bolts.Task;

/** package */ class CachedCurrentInstallationController
    implements ParseCurrentInstallationController {

  /* package */ static final String TAG = "com.parse.CachedCurrentInstallationController";

  /*
   * Note about lock ordering:
   *
   * You must NOT acquire the ParseInstallation instance mutex (the "mutex" field in ParseObject)
   * while holding this current installation lock. (We used to use the ParseInstallation.class lock,
   * but moved on to an explicit lock object since anyone could acquire the ParseInstallation.class
   * lock as ParseInstallation 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 ParseObjectStore store;
  private final InstallationId installationId;

  // The "current installation" is the installation for this device. Protected by
  // mutex.
  /* package for test */ ParseInstallation currentInstallation;

  public CachedCurrentInstallationController(
      ParseObjectStore store, InstallationId installationId) {
    this.store = store;
    this.installationId = installationId;
  }

  @Override
  public Task setAsync(final ParseInstallation 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;
          }
        }, ParseExecutors.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 ParseInstallation then(Task task) throws Exception {
                ParseInstallation current = task.getResult();
                if (current == null) {
                  current = ParseObject.create(ParseInstallation.class);
                  current.updateDeviceInfo(installationId);
                } else {
                  installationId.set(current.getInstallationId());
                  PLog.v(TAG, "Successfully deserialized Installation object");
                }

                synchronized (mutex) {
                  currentInstallation = current;
                }
                return current;
              }
            }, ParseExecutors.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();
      ParseTaskUtils.wait(store.deleteAsync());
    } catch (ParseException e) {
      // ignored
    }
  }

  @Override
  public boolean isCurrent(ParseInstallation installation) {
    synchronized (mutex) {
      return  currentInstallation == installation;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy