-
Notifications
You must be signed in to change notification settings - Fork 227
Expand file tree
/
Copy pathAbstractReference.java
More file actions
131 lines (115 loc) · 3.91 KB
/
AbstractReference.java
File metadata and controls
131 lines (115 loc) · 3.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* Copyright (c) Jython Developers */
package org.python.modules._weakref;
import org.python.core.JyAttribute;
import org.python.core.Py;
import org.python.core.PyObject;
import org.python.core.PyType;
import org.python.core.Traverseproc;
import org.python.core.Visitproc;
import org.python.modules.gc;
/**
* Base class for weakref types.
*/
public abstract class AbstractReference extends PyObject implements Traverseproc {
PyObject callback;
protected ReferenceBackend gref;
public AbstractReference(PyType subType, ReferenceBackend gref, PyObject callback) {
super(subType);
this.gref = gref;
this.callback = callback;
gref.add(this);
}
void call() {
if (callback == null)
return;
try {
callback.__call__(this);
} catch (Exception exc) {
Py.writeUnraisable(exc, callback);
}
}
protected PyObject py() {
PyObject o = get();
if (o == null) {
throw Py.ReferenceError("weakly-referenced object no longer exists");
}
return o;
}
// Differentiate reference equality (equals) with what is being referred to (__eq__)
@Override
public boolean equals(Object ob_other) {
return ob_other == this;
}
public boolean hasCallback() {
return callback != null;
}
public int hashCode() {
return gref.pythonHashCode();
}
public PyObject __eq__(PyObject other) {
if (other.getClass() != getClass()) {
return null;
}
PyObject pythis = get();
PyObject pyother = ((AbstractReference) other).get();
if (pythis == null || pyother == null) {
return this == other ? Py.True : Py.False;
}
return pythis._eq(pyother);
}
public PyObject __ne__(PyObject other) {
if (other.getClass() != getClass()) {
return Py.True;
}
PyObject pythis = get();
PyObject pyother = ((AbstractReference) other).get();
if (pythis == null || pyother == null) {
return this == other ? Py.False : Py.True;
}
return pythis._eq(pyother).__not__();
}
protected PyObject get() {
PyObject result = gref.get();
if (result == null && gc.delayedWeakrefCallbacksEnabled()) {
if (gref.isCleared()) {
return null;
}
if ((gc.getJythonGCFlags() & gc.VERBOSE_WEAKREF) != 0) {
gc.writeDebug("gc", "pending in get of abstract ref "+this+": "+
Thread.currentThread().getId());
}
JyAttribute.setAttr(this, JyAttribute.WEAKREF_PENDING_GET_ATTR,
Thread.currentThread());
while (!gref.isCleared() && result == null) {
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {}
result = gref.get();
}
JyAttribute.delAttr(this, JyAttribute.WEAKREF_PENDING_GET_ATTR);
if ((gc.getJythonGCFlags() & gc.VERBOSE_WEAKREF) != 0) {
gc.writeDebug("gc", "pending of "+this+" resolved: "+
Thread.currentThread().getId());
if (gref.isCleared()) {
gc.writeDebug("gc", "reference was cleared.");
} else if (result != null){
gc.writeDebug("gc", "reference was restored.");
} else {
gc.writeDebug("gc", "something went very wrong.");
}
}
return result;
} else {
return result;
}
}
/* Traverseproc implementation */
@Override
public int traverse(Visitproc visit, Object arg) {
return callback != null ? visit.visit(callback, arg) : 0;
}
@Override
public boolean refersDirectlyTo(PyObject ob) {
return ob != null && callback == ob;
}
}