1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17/*
18 * Copyright (C) 2008 The Android Open Source Project
19 *
20 * Licensed under the Apache License, Version 2.0 (the "License");
21 * you may not use this file except in compliance with the License.
22 * You may obtain a copy of the License at
23 *
24 *      http://www.apache.org/licenses/LICENSE-2.0
25 *
26 * Unless required by applicable law or agreed to in writing, software
27 * distributed under the License is distributed on an "AS IS" BASIS,
28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29 * See the License for the specific language governing permissions and
30 * limitations under the License.
31 */
32
33package java.lang.ref;
34
35/**
36 * Provides an abstract class which describes behavior common to all reference
37 * objects. It is not possible to create immediate subclasses of
38 * {@code Reference} in addition to the ones provided by this package. It is
39 * also not desirable to do so, since references require very close cooperation
40 * with the system's garbage collector. The existing, specialized reference
41 * classes should be used instead.
42 *
43 * @since Android 1.0
44 */
45public abstract class Reference<T> {
46
47    /**
48     * The object to which this reference refers.
49     * VM requirement: this field <em>must</em> be called "referent"
50     * and be an object.
51     */
52    volatile T referent;
53
54    /**
55     * If non-null, the queue on which this reference will be enqueued
56     * when the referent is appropriately reachable.
57     * VM requirement: this field <em>must</em> be called "queue"
58     * and be a java.lang.ref.ReferenceQueue.
59     */
60    @SuppressWarnings("unchecked")
61    volatile ReferenceQueue queue;
62
63    /**
64     * Used internally by java.lang.ref.ReferenceQueue.
65     * VM requirement: this field <em>must</em> be called "queueNext"
66     * and be a java.lang.ref.Reference.
67     */
68    @SuppressWarnings("unchecked")
69    volatile Reference queueNext;
70
71    /**
72     * Used internally by Dalvik.
73     * VM requirement: this field <em>must</em> be called "vmData"
74     * and be an int.
75     */
76    @SuppressWarnings("unused")
77    volatile private int vmData;
78
79    /**
80     * Constructs a new instance of this class.
81     */
82    Reference() {
83        super();
84    }
85
86    /**
87     * Makes the referent {@code null}. This does not force the reference
88     * object to be enqueued.
89     *
90     * @since Android 1.0
91     */
92    public void clear() {
93        referent = null;
94    }
95
96    /**
97     * An implementation of .enqueue() that is safe for the VM to call.
98     * If a Reference object is a subclass of any of the
99     * java.lang.ref.*Reference classes and that subclass overrides enqueue(),
100     * the VM may not call the overridden method.
101     * VM requirement: this method <em>must</em> be called "enqueueInternal",
102     * have the signature "()Z", and be private.
103     *
104     * @return {@code true} if this call has caused the {@code Reference} to
105     * become enqueued, or {@code false} otherwise
106     *
107     * @since Android 1.0
108     */
109    @SuppressWarnings("unchecked")
110    private synchronized boolean enqueueInternal() {
111        /* VM requirement:
112         * The VM assumes that this function only does work
113         * if "(queue != null && queueNext == null)".
114         * If that changes, Dalvik needs to change, too.
115         * (see MarkSweep.c:enqueueReference())
116         */
117        if (queue != null && queueNext == null) {
118            queue.enqueue(this);
119            queue = null;
120            return true;
121        }
122        return false;
123    }
124
125    /**
126     * Forces the reference object to be enqueued if it has been associated with
127     * a queue.
128     *
129     * @return {@code true} if this call has caused the {@code Reference} to
130     * become enqueued, or {@code false} otherwise
131     *
132     * @since Android 1.0
133     */
134    public boolean enqueue() {
135        return enqueueInternal();
136    }
137
138    /**
139     * Returns the referent of the reference object.
140     *
141     * @return the referent to which reference refers, or {@code null} if the
142     *         object has been cleared.
143     *
144     * @since Android 1.0
145     */
146    public T get() {
147        return referent;
148    }
149
150    /**
151     * Checks whether the reference object has been enqueued.
152     *
153     * @return {@code true} if the {@code Reference} has been enqueued, {@code
154     *         false} otherwise
155     *
156     * @since Android 1.0
157     */
158    public boolean isEnqueued() {
159        return queueNext != null;
160    }
161
162}
163