~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/openjdk/java/lang/ref/Reference.java

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (C) 2003-2012 Jeroen Frijters
 
3
 
 
4
  This software is provided 'as-is', without any express or implied
 
5
  warranty.  In no event will the authors be held liable for any damages
 
6
  arising from the use of this software.
 
7
 
 
8
  Permission is granted to anyone to use this software for any purpose,
 
9
  including commercial applications, and to alter it and redistribute it
 
10
  freely, subject to the following restrictions:
 
11
 
 
12
  1. The origin of this software must not be misrepresented; you must not
 
13
     claim that you wrote the original software. If you use this software
 
14
     in a product, an acknowledgment in the product documentation would be
 
15
     appreciated but is not required.
 
16
  2. Altered source versions must be plainly marked as such, and must not be
 
17
     misrepresented as being the original software.
 
18
  3. This notice may not be removed or altered from any source distribution.
 
19
 
 
20
  Jeroen Frijters
 
21
  jeroen@frijters.net
 
22
  
 
23
*/
 
24
package java.lang.ref;
 
25
 
 
26
import cli.System.Collections.Hashtable;
 
27
import sun.misc.Cleaner;
 
28
 
 
29
public abstract class Reference<T>
 
30
{
 
31
    // accessed by inner class
 
32
    volatile cli.System.WeakReference weakRef;
 
33
    volatile T strongRef;
 
34
    volatile ReferenceQueue<? super T> queue;
 
35
    volatile Reference next;
 
36
    
 
37
    private static native boolean noclassgc();
 
38
 
 
39
    Reference(T referent)
 
40
    {
 
41
        this(referent, null);
 
42
    }
 
43
 
 
44
    Reference(T referent, ReferenceQueue<? super T> queue)
 
45
    {
 
46
        this.queue = queue == null ? ReferenceQueue.NULL : queue;
 
47
        if (referent != null)
 
48
        {
 
49
            if (referent instanceof Class && noclassgc())
 
50
            {
 
51
                // We don't do Class gc, so no point in using a weak reference for classes.
 
52
                strongRef = referent;
 
53
            }
 
54
            else
 
55
            {
 
56
                weakRef = new cli.System.WeakReference(referent, this instanceof PhantomReference);
 
57
                if (queue != null || referent instanceof Cleaner || this instanceof SoftReference)
 
58
                {
 
59
                    new QueueWatcher(this);
 
60
                }
 
61
            }
 
62
        }
 
63
    }
 
64
 
 
65
    private static final boolean debug = false;
 
66
 
 
67
    private static final class QueueWatcher
 
68
    {
 
69
        private static final Hashtable keepAlive = Hashtable.Synchronized(new Hashtable());
 
70
        private cli.System.WeakReference handle;
 
71
 
 
72
        QueueWatcher(Reference r)
 
73
        {
 
74
            handle = new cli.System.WeakReference(r, true);
 
75
            // FXBUG when a WeakReference is finalizer reachable, it gets cleared by the GC (even if we call GC.SuppressFinalize),
 
76
            // so we have to maintain a strong reference to it to prevent it from being cleared.
 
77
            keepAlive.Add(handle, null);
 
78
        }
 
79
 
 
80
        boolean check(Reference r)
 
81
        {
 
82
            r.strongRef = null;
 
83
            boolean alive = false;
 
84
            try
 
85
            {
 
86
                if (false) throw new cli.System.InvalidOperationException();
 
87
                cli.System.WeakReference referent = r.weakRef;
 
88
                if (referent == null)
 
89
                {
 
90
                    // ref was explicitly cleared, so we don't enqueue
 
91
                    return false;
 
92
                }
 
93
                alive = referent.get_IsAlive();
 
94
            }
 
95
            catch (cli.System.InvalidOperationException x)
 
96
            {
 
97
                // this happens if the reference is already finalized (if we were
 
98
                // the only one still hanging on to it)
 
99
            }
 
100
            if (alive)
 
101
            {
 
102
                // we don't want to keep creating finalizable objects during shutdown
 
103
                if (!cli.System.Environment.get_HasShutdownStarted())
 
104
                {
 
105
                    return true;
 
106
                }
 
107
            }
 
108
            else
 
109
            {
 
110
                if (r instanceof Cleaner)
 
111
                {
 
112
                    ((Cleaner)r).clean();
 
113
                }
 
114
                else if (r.queue != null)
 
115
                {
 
116
                    r.queue.enqueue(r);
 
117
                }
 
118
            }
 
119
            return false;
 
120
        }
 
121
 
 
122
        protected void finalize()
 
123
        {
 
124
            Reference r = (Reference)handle.get_Target();
 
125
            if (debug)
 
126
                cli.System.Console.WriteLine("~QueueWatcher: " + hashCode() + " on " + r);
 
127
            if (r != null && r.next == null && check(r))
 
128
            {
 
129
                cli.System.GC.ReRegisterForFinalize(QueueWatcher.this);
 
130
            }
 
131
            else
 
132
            {
 
133
                handle.set_Target(null);
 
134
                keepAlive.Remove(handle);
 
135
            }
 
136
        }
 
137
    }
 
138
 
 
139
    public T get()
 
140
    {
 
141
        try
 
142
        {
 
143
            if (false) throw new cli.System.InvalidOperationException();
 
144
            cli.System.WeakReference referent = this.weakRef;
 
145
            if (referent == null)
 
146
            {
 
147
                return strongRef;
 
148
            }
 
149
            T value = (T)referent.get_Target();
 
150
            if (value == null)
 
151
            {
 
152
                queue.enqueue(this);
 
153
            }
 
154
            return value;
 
155
        }
 
156
        catch (cli.System.InvalidOperationException x)
 
157
        {
 
158
            // we were already finalized, so we just return null.
 
159
            return null;
 
160
        }
 
161
    }
 
162
 
 
163
    public void clear()
 
164
    {
 
165
        weakRef = null;
 
166
        strongRef = null;
 
167
    }
 
168
 
 
169
    public synchronized boolean isEnqueued()
 
170
    {
 
171
        return queue != ReferenceQueue.NULL && next != null;
 
172
    }
 
173
 
 
174
    public boolean enqueue() 
 
175
    {
 
176
        return queue.enqueue(this);
 
177
    }
 
178
}