// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/AlwaysCallback.java
// public interface AlwaysCallback {
// 
//     void onAlways();
// 
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/CancelCallback.java
// public interface CancelCallback {
// 
//     void onCancel();
// 
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/DoneCallback.java
// public interface DoneCallback<T> {
// 
//     void onDone(T result);
// 
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/FailCallback.java
// public interface FailCallback {
// 
//     void onFail(Exception exception);
// 
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/ProgressCallback.java
// public interface ProgressCallback<Progress> {
// 
//     void onProgress(Progress progress);
// 
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/ThenCallback.java
// public interface ThenCallback<Arg, Result, Progress> {
// 
//     Promise<Result, Progress> then(Arg arg);
// 
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/UIAlwaysCallback.java
// public interface UIAlwaysCallback extends AlwaysCallback {
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/UICancelCallback.java
// public interface UICancelCallback extends CancelCallback {
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/UIDoneCallback.java
// public interface UIDoneCallback<T> extends DoneCallback<T> {
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/UIFailCallback.java
// public interface UIFailCallback extends FailCallback {
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/UIProgressCallback.java
// public interface UIProgressCallback<Progress> extends ProgressCallback<Progress> {
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/transform/Filter.java
// public interface Filter<T> {
//     boolean filter(T value);
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/transform/Mapper.java
// public interface Mapper<T, U> {
//     U map(T value);
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/util/ObjectPool.java
// public class ObjectPool<T> {
//     private final Object mLock = new Object();
//     private final Object[] mPool;
// 
//     private int mPoolSize;
// 
//     /**
//      * Creates a new instance.
//      *
//      * @param maxPoolSize The max pool size.
//      * @throws IllegalArgumentException If the max pool size is less than zero.
//      */
//     public ObjectPool(int maxPoolSize) {
//         if (maxPoolSize <= 0) {
//             throw new IllegalArgumentException("The max pool size must be > 0");
//         }
//         mPool = new Object[maxPoolSize];
//     }
// 
//     @SuppressWarnings("unchecked")
//     public T acquire() {
//         synchronized (mLock) {
//             if (mPoolSize > 0) {
//                 final int lastPooledIndex = mPoolSize - 1;
//                 T instance = (T) mPool[lastPooledIndex];
//                 mPool[lastPooledIndex] = null;
//                 mPoolSize--;
//                 return instance;
//             }
//             return null;
//         }
//     }
// 
//     public boolean release(T element) {
//         synchronized (mLock) {
//             if (isInPool(element)) {
//                 throw new IllegalStateException("Already in the pool!");
//             }
//             if (mPoolSize < mPool.length) {
//                 mPool[mPoolSize] = element;
//                 mPoolSize++;
//                 return true;
//             }
//             return false;
//         }
//     }
// 
//     private boolean isInPool(T element) {
//         for (int i = 0; i < mPoolSize; i++) {
//             if (mPool[i] == element) {
//                 return true;
//             }
//         }
//         return false;
//     }
// }


import com.raycoarana.awex.callbacks.AlwaysCallback;
import com.raycoarana.awex.callbacks.CancelCallback;
import com.raycoarana.awex.callbacks.DoneCallback;
import com.raycoarana.awex.callbacks.FailCallback;
import com.raycoarana.awex.callbacks.ProgressCallback;
import com.raycoarana.awex.callbacks.ThenCallback;
import com.raycoarana.awex.callbacks.UIAlwaysCallback;
import com.raycoarana.awex.callbacks.UICancelCallback;
import com.raycoarana.awex.callbacks.UIDoneCallback;
import com.raycoarana.awex.callbacks.UIFailCallback;
import com.raycoarana.awex.callbacks.UIProgressCallback;
import com.raycoarana.awex.transform.Filter;
import com.raycoarana.awex.transform.Mapper;
import com.raycoarana.awex.util.ObjectPool;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
package com.raycoarana.awex;



/**
 * Implementation of task promise
 */
class AwexPromise<Result, Progress> implements ResolvablePromise<Result, Progress> {

    protected final Awex mAwex;
    private final Task mTask;

    private final ThreadHelper mThreadHelper;
    private final Logger mLogger;
    private final long mId;

    private int mState;
    private Result mResult;
    private Exception mException;
    private Callbacks<Result, Progress> mCallbacks;

    private final Object mProgressInOrderSyncObject = new Object();
    private final Object mBlockingObject = new Object();

    private static class Callbacks<Result, Progress> {
        public static final Callbacks EMPTY = new Callbacks(true);

        private final List<DoneCallback<Result>> mDoneCallbacks;
        private final List<FailCallback> mFailCallbacks;
        private final List<ProgressCallback<Progress>> mProgressCallbacks;
        private final List<CancelCallback> mCancelCallbacks;
        private final List<AlwaysCallback> mAlwaysCallbacks;

// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/AlwaysCallback.java
// public interface AlwaysCallback {
// 
//     void onAlways();
// 
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/CancelCallback.java
// public interface CancelCallback {
// 
//     void onCancel();
// 
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/DoneCallback.java
// public interface DoneCallback<T> {
// 
//     void onDone(T result);
// 
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/FailCallback.java
// public interface FailCallback {
// 
//     void onFail(Exception exception);
// 
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/ProgressCallback.java
// public interface ProgressCallback<Progress> {
// 
//     void onProgress(Progress progress);
// 
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/ThenCallback.java
// public interface ThenCallback<Arg, Result, Progress> {
// 
//     Promise<Result, Progress> then(Arg arg);
// 
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/UIAlwaysCallback.java
// public interface UIAlwaysCallback extends AlwaysCallback {
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/UICancelCallback.java
// public interface UICancelCallback extends CancelCallback {
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/UIDoneCallback.java
// public interface UIDoneCallback<T> extends DoneCallback<T> {
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/UIFailCallback.java
// public interface UIFailCallback extends FailCallback {
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/callbacks/UIProgressCallback.java
// public interface UIProgressCallback<Progress> extends ProgressCallback<Progress> {
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/transform/Filter.java
// public interface Filter<T> {
//     boolean filter(T value);
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/transform/Mapper.java
// public interface Mapper<T, U> {
//     U map(T value);
// }
// 
// Path: awex-core/src/main/java/com/raycoarana/awex/util/ObjectPool.java
// public class ObjectPool<T> {
//     private final Object mLock = new Object();
//     private final Object[] mPool;
// 
//     private int mPoolSize;
// 
//     /**
//      * Creates a new instance.
//      *
//      * @param maxPoolSize The max pool size.
//      * @throws IllegalArgumentException If the max pool size is less than zero.
//      */
//     public ObjectPool(int maxPoolSize) {
//         if (maxPoolSize <= 0) {
//             throw new IllegalArgumentException("The max pool size must be > 0");
//         }
//         mPool = new Object[maxPoolSize];
//     }
// 
//     @SuppressWarnings("unchecked")
//     public T acquire() {
//         synchronized (mLock) {
//             if (mPoolSize > 0) {
//                 final int lastPooledIndex = mPoolSize - 1;
//                 T instance = (T) mPool[lastPooledIndex];
//                 mPool[lastPooledIndex] = null;
//                 mPoolSize--;
//                 return instance;
//             }
//             return null;
//         }
//     }
// 
//     public boolean release(T element) {
//         synchronized (mLock) {
//             if (isInPool(element)) {
//                 throw new IllegalStateException("Already in the pool!");
//             }
//             if (mPoolSize < mPool.length) {
//                 mPool[mPoolSize] = element;
//                 mPoolSize++;
//                 return true;
//             }
//             return false;
//         }
//     }
// 
//     private boolean isInPool(T element) {
//         for (int i = 0; i < mPoolSize; i++) {
//             if (mPool[i] == element) {
//                 return true;
//             }
//         }
//         return false;
//     }
// }


// Path: awex-core/src/main/java/com/raycoarana/awex/AwexPromise.java
import com.raycoarana.awex.callbacks.AlwaysCallback;
import com.raycoarana.awex.callbacks.CancelCallback;
import com.raycoarana.awex.callbacks.DoneCallback;
import com.raycoarana.awex.callbacks.FailCallback;
import com.raycoarana.awex.callbacks.ProgressCallback;
import com.raycoarana.awex.callbacks.ThenCallback;
import com.raycoarana.awex.callbacks.UIAlwaysCallback;
import com.raycoarana.awex.callbacks.UICancelCallback;
import com.raycoarana.awex.callbacks.UIDoneCallback;
import com.raycoarana.awex.callbacks.UIFailCallback;
import com.raycoarana.awex.callbacks.UIProgressCallback;
import com.raycoarana.awex.transform.Filter;
import com.raycoarana.awex.transform.Mapper;
import com.raycoarana.awex.util.ObjectPool;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

package com.raycoarana.awex;



/**
 * Implementation of task promise
 */
class AwexPromise<Result, Progress> implements ResolvablePromise<Result, Progress> {

    protected final Awex mAwex;
    private final Task mTask;

    private final ThreadHelper mThreadHelper;
    private final Logger mLogger;
    private final long mId;

    private int mState;
    private Result mResult;
    private Exception mException;
    private Callbacks<Result, Progress> mCallbacks;

    private final Object mProgressInOrderSyncObject = new Object();
    private final Object mBlockingObject = new Object();

    private static class Callbacks<Result, Progress> {
        public static final Callbacks EMPTY = new Callbacks(true);

        private final List<DoneCallback<Result>> mDoneCallbacks;
        private final List<FailCallback> mFailCallbacks;
        private final List<ProgressCallback<Progress>> mProgressCallbacks;
        private final List<CancelCallback> mCancelCallbacks;
        private final List<AlwaysCallback> mAlwaysCallbacks;

        private static final ObjectPool<Callbacks> sObjectPool = new ObjectPool<>(30);