1package com.bumptech.glide.load.engine;
2
3import android.os.Looper;
4import com.bumptech.glide.load.Key;
5
6/**
7 * A generic resource that handles reference counting so resources can safely be reused.
8 * <p>
9 *     Public methods are non final only to allow for mocking, subclasses must only override abstract methods.
10 * </p>
11 *
12 * @param <Z> The type of resource wrapped by this class.
13 */
14public abstract class Resource<Z> {
15    private volatile int acquired;
16    private volatile boolean isRecycled;
17    private ResourceListener listener;
18    private Key key;
19    private boolean isCacheable;
20
21    interface ResourceListener {
22        public void onResourceReleased(Key key, Resource resource);
23    }
24
25    public abstract Z get();
26
27    public abstract int getSize();
28
29    protected abstract void recycleInternal();
30
31    void setResourceListener(Key key, ResourceListener listener) {
32        this.key = key;
33        this.listener = listener;
34    }
35
36    void setCacheable(boolean isCacheable) {
37        this.isCacheable = isCacheable;
38    }
39
40    boolean isCacheable() {
41        return isCacheable;
42    }
43
44    public void recycle() {
45        if (acquired > 0) {
46            throw new IllegalStateException("Cannot recycle a resource while it is still acquired");
47        }
48        if (isRecycled) {
49            throw new IllegalStateException("Cannot recycle a resource that has already been recycled");
50        }
51        isRecycled = true;
52        recycleInternal();
53    }
54
55    public void acquire(int times) {
56        if (isRecycled) {
57            throw new IllegalStateException("Cannot acquire a recycled resource");
58        }
59        if (times <= 0) {
60            throw new IllegalArgumentException("Must acquire a number of times >= 0");
61        }
62        if (!Looper.getMainLooper().equals(Looper.myLooper())) {
63            throw new IllegalThreadStateException("Must call acquire on the main thread");
64        }
65        acquired += times;
66    }
67
68    public void release() {
69        if (acquired <= 0) {
70            throw new IllegalStateException("Cannot release a recycled or not yet acquired resource");
71        }
72        if (!Looper.getMainLooper().equals(Looper.myLooper())) {
73            throw new IllegalThreadStateException("Must call release on the main thread");
74        }
75        if (--acquired == 0) {
76            listener.onResourceReleased(key, this);
77        }
78    }
79}
80