Home | History | Annotate | Download | only in selection
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.documentsui.selection;
     17 
     18 import static android.support.v4.util.Preconditions.checkState;
     19 import static com.android.documentsui.selection.Shared.DEBUG;
     20 import static com.android.documentsui.selection.Shared.TAG;
     21 
     22 import android.annotation.MainThread;
     23 import android.annotation.Nullable;
     24 import android.content.Loader;
     25 import android.util.Log;
     26 
     27 /**
     28  * ContentLock provides a mechanism to block content from reloading while selection
     29  * activities like gesture and band selection are active. Clients using live data
     30  * (data loaded, for example by a {@link Loader}), should route calls to load
     31  * content through this lock using {@link ContentLock#runWhenUnlocked(Runnable)}.
     32  */
     33 public final class ContentLock {
     34 
     35     private int mLocks = 0;
     36     private @Nullable Runnable mCallback;
     37 
     38     /**
     39      * Increment the block count by 1
     40      */
     41     @MainThread
     42     public synchronized void block() {
     43         mLocks++;
     44         if (DEBUG) Log.v(TAG, "Incremented content lock count to " + mLocks + ".");
     45     }
     46 
     47     /**
     48      * Decrement the block count by 1; If no other object is trying to block and there exists some
     49      * callback, that callback will be run
     50      */
     51     @MainThread
     52     public synchronized void unblock() {
     53         checkState(mLocks > 0);
     54 
     55         mLocks--;
     56         if (DEBUG) Log.v(TAG, "Decremented content lock count to " + mLocks + ".");
     57 
     58         if (mLocks == 0 && mCallback != null) {
     59             mCallback.run();
     60             mCallback = null;
     61         }
     62     }
     63 
     64     /**
     65      * Attempts to run the given Runnable if not-locked, or else the Runnable is set to be ran next
     66      * (replacing any previous set Runnables).
     67      */
     68     public synchronized void runWhenUnlocked(Runnable runnable) {
     69         if (mLocks == 0) {
     70             runnable.run();
     71         } else {
     72             mCallback = runnable;
     73         }
     74     }
     75 
     76     /**
     77      * Returns true if locked.
     78      */
     79     synchronized boolean isLocked() {
     80         return mLocks > 0;
     81     }
     82 
     83     /**
     84      * Allows other selection code to perform a precondition check asserting the state is locked.
     85      */
     86     final void checkLocked() {
     87         checkState(isLocked());
     88     }
     89 
     90     /**
     91      * Allows other selection code to perform a precondition check asserting the state is unlocked.
     92      */
     93     final void checkUnlocked() {
     94         checkState(!isLocked());
     95     }
     96 }
     97