• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      * True if the instance should record when it was closed.  Tracking closure can be expensive,
35      * so it is best reserved for subclasses that have long lifetimes.
36      * @hide
37      */
38     protected boolean mTrackClosure = false;
39 
40     /**
41      * The caller that finally released this instance.  If this is not null, it is supplied as the
42      * cause to the IllegalStateException that is thrown when the object is reopened.  Subclasses
43      * are responsible for populating this field, if they wish to use it.
44      */
45     private Throwable mClosedBy = null;
46 
47     /**
48      * Called when the last reference to the object was released by
49      * a call to {@link #releaseReference()} or {@link #close()}.
50      */
onAllReferencesReleased()51     protected abstract void onAllReferencesReleased();
52 
53     /**
54      * Called when the last reference to the object was released by
55      * a call to {@link #releaseReferenceFromContainer()}.
56      *
57      * @deprecated Do not use.
58      */
59     @Deprecated
onAllReferencesReleasedFromContainer()60     protected void onAllReferencesReleasedFromContainer() {
61         onAllReferencesReleased();
62     }
63 
64     /**
65      * Acquires a reference to the object.
66      *
67      * @throws IllegalStateException if the last reference to the object has already
68      * been released.
69      */
acquireReference()70     public void acquireReference() {
71         synchronized(this) {
72             if (mReferenceCount <= 0) {
73                 throw new IllegalStateException(
74                     "attempt to re-open an already-closed object: " + this, mClosedBy);
75             }
76             mReferenceCount++;
77         }
78     }
79 
80     /**
81      * Releases a reference to the object, closing the object if the last reference
82      * was released.
83      *
84      * @see #onAllReferencesReleased()
85      */
releaseReference()86     public void releaseReference() {
87         boolean refCountIsZero = false;
88         synchronized(this) {
89             refCountIsZero = --mReferenceCount == 0;
90         }
91         if (refCountIsZero) {
92             onAllReferencesReleased();
93         }
94     }
95 
96     /**
97      * Releases a reference to the object that was owned by the container of the object,
98      * closing the object if the last reference was released.
99      *
100      * @see #onAllReferencesReleasedFromContainer()
101      * @deprecated Do not use.
102      */
103     @Deprecated
releaseReferenceFromContainer()104     public void releaseReferenceFromContainer() {
105         boolean refCountIsZero = false;
106         synchronized(this) {
107             refCountIsZero = --mReferenceCount == 0;
108         }
109         if (refCountIsZero) {
110             onAllReferencesReleasedFromContainer();
111         }
112     }
113 
114     /**
115      * Releases a reference to the object, closing the object if the last reference
116      * was released.
117      *
118      * Calling this method is equivalent to calling {@link #releaseReference}.
119      *
120      * @see #releaseReference()
121      * @see #onAllReferencesReleased()
122      */
close()123     public void close() {
124         releaseReference();
125         synchronized (this) {
126             if (mTrackClosure && (mClosedBy == null)) {
127                 String name = getClass().getName();
128                 mClosedBy = new Exception("closed by " + name + ".close()").fillInStackTrace();
129             }
130         }
131     }
132 }
133