1 /*
2  * Copyright (C) 2007 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 
17 package android.database.sqlite;
18 
19 import android.compat.annotation.UnsupportedAppUsage;
20 
21 import java.io.Closeable;
22 
23 /**
24  * An object created from a SQLiteDatabase that can be closed.
25  *
26  * This class implements a primitive reference counting scheme for database objects.
27  */
28 @android.ravenwood.annotation.RavenwoodKeepWholeClass
29 public abstract class SQLiteClosable implements Closeable {
30     @UnsupportedAppUsage
31     private int mReferenceCount = 1;
32 
33     /**
34      * Called when the last reference to the object was released by
35      * a call to {@link #releaseReference()} or {@link #close()}.
36      */
onAllReferencesReleased()37     protected abstract void onAllReferencesReleased();
38 
39     /**
40      * Called when the last reference to the object was released by
41      * a call to {@link #releaseReferenceFromContainer()}.
42      *
43      * @deprecated Do not use.
44      */
45     @Deprecated
onAllReferencesReleasedFromContainer()46     protected void onAllReferencesReleasedFromContainer() {
47         onAllReferencesReleased();
48     }
49 
50     /**
51      * Acquires a reference to the object.
52      *
53      * @throws IllegalStateException if the last reference to the object has already
54      * been released.
55      */
acquireReference()56     public void acquireReference() {
57         synchronized(this) {
58             if (mReferenceCount <= 0) {
59                 throw new IllegalStateException(
60                         "attempt to re-open an already-closed object: " + this);
61             }
62             mReferenceCount++;
63         }
64     }
65 
66     /**
67      * Releases a reference to the object, closing the object if the last reference
68      * was released.
69      *
70      * @see #onAllReferencesReleased()
71      */
releaseReference()72     public void releaseReference() {
73         boolean refCountIsZero = false;
74         synchronized(this) {
75             refCountIsZero = --mReferenceCount == 0;
76         }
77         if (refCountIsZero) {
78             onAllReferencesReleased();
79         }
80     }
81 
82     /**
83      * Releases a reference to the object that was owned by the container of the object,
84      * closing the object if the last reference was released.
85      *
86      * @see #onAllReferencesReleasedFromContainer()
87      * @deprecated Do not use.
88      */
89     @Deprecated
releaseReferenceFromContainer()90     public void releaseReferenceFromContainer() {
91         boolean refCountIsZero = false;
92         synchronized(this) {
93             refCountIsZero = --mReferenceCount == 0;
94         }
95         if (refCountIsZero) {
96             onAllReferencesReleasedFromContainer();
97         }
98     }
99 
100     /**
101      * Releases a reference to the object, closing the object if the last reference
102      * was released.
103      *
104      * Calling this method is equivalent to calling {@link #releaseReference}.
105      *
106      * @see #releaseReference()
107      * @see #onAllReferencesReleased()
108      */
close()109     public void close() {
110         releaseReference();
111     }
112 }
113