001: // Copyright 2001 Finn Bock
002:
003: package org.python.modules;
004:
005: import java.lang.ref.*;
006: import java.util.*;
007: import org.python.core.*;
008:
009: public class _weakref implements ClassDictInit {
010: static ReferenceQueue referenceQueue = new ReferenceQueue();
011:
012: static RefReaperThread reaperThread;
013: static Map objects = new HashMap();
014:
015: public static PyObject ReferenceError = null;
016:
017: static {
018: reaperThread = new RefReaperThread();
019: reaperThread.setDaemon(true);
020: reaperThread.start();
021: }
022:
023: /** <i>Internal use only. Do not call this method explicit.</i> */
024: public static void classDictInit(PyObject dict)
025: throws PyIgnoreMethodTag {
026: ReferenceError = Py.makeClass("ReferenceError",
027: new PyObject[] { Py.RuntimeError }, Py.newJavaCode(
028: _weakref.class, "empty__init__"), Py.None);
029: dict.__setitem__("ReferenceError", ReferenceError);
030: }
031:
032: // An empty __init__ method
033: public static PyObject empty__init__(PyObject[] arg, String[] kws) {
034: PyObject dict = new PyStringMap();
035: dict.__setitem__("__module__", new PyString("_weakref"));
036: return dict;
037: }
038:
039: public static ReferenceType ref(PyObject object) {
040: GlobalRef gref = mkGlobal(object);
041: ReferenceType ret = (ReferenceType) gref
042: .find(ReferenceType.class);
043: if (ret != null) {
044: return ret;
045: }
046: return new ReferenceType(mkGlobal(object), null);
047: }
048:
049: public static ReferenceType ref(PyObject object, PyObject callback) {
050: return new ReferenceType(mkGlobal(object), callback);
051: }
052:
053: public static ProxyType proxy(PyObject object) {
054: GlobalRef gref = mkGlobal(object);
055: ProxyType ret = (ProxyType) gref.find(ProxyType.class);
056: if (ret != null) {
057: return ret;
058: }
059: if (object.isCallable()) {
060: return new CallableProxyType(mkGlobal(object), null);
061: } else {
062: return new ProxyType(mkGlobal(object), null);
063: }
064: }
065:
066: public static ProxyType proxy(PyObject object, PyObject callback) {
067: if (object.isCallable()) {
068: return new CallableProxyType(mkGlobal(object), callback);
069: } else {
070: return new ProxyType(mkGlobal(object), callback);
071: }
072: }
073:
074: public static int getweakrefcount(PyObject o) {
075: GlobalRef ref = (GlobalRef) objects.get(new GlobalRef(o));
076: if (ref == null)
077: return 0;
078: return ref.count();
079: }
080:
081: public static PyList getweakrefs(PyObject o) {
082: GlobalRef ref = (GlobalRef) objects.get(new GlobalRef(o));
083: if (ref == null)
084: return new PyList();
085: return ref.refs();
086: }
087:
088: private static GlobalRef mkGlobal(PyObject object) {
089: GlobalRef ref = (GlobalRef) objects.get(new GlobalRef(object));
090: if (ref == null) {
091: ref = new GlobalRef(object, referenceQueue);
092: objects.put(ref, ref);
093: }
094: return ref;
095: }
096:
097: static class RefReaperThread extends Thread {
098: RefReaperThread() {
099: super ("weakref reaper");
100: }
101:
102: public void collect() throws InterruptedException {
103: GlobalRef gr = (GlobalRef) referenceQueue.remove();
104: gr.call();
105: objects.remove(gr);
106: gr = null;
107: }
108:
109: public void run() {
110: while (true) {
111: try {
112: collect();
113: } catch (InterruptedException exc) {
114: }
115: }
116: }
117: }
118:
119: public static class GlobalRef extends WeakReference {
120: private Vector references = new Vector();
121: private int hash;
122: private boolean realHash; // If the hash value was calculated by the underlying object
123:
124: public GlobalRef(PyObject object) {
125: super (object);
126: calcHash(object);
127: }
128:
129: public GlobalRef(PyObject object, ReferenceQueue queue) {
130: super (object, queue);
131: calcHash(object);
132: }
133:
134: /**
135: * Calculate a hash code to use for this object. If the PyObject we're
136: * referencing implements hashCode, we use that value. If not, we use
137: * System.identityHashCode(refedObject). This allows this object to be
138: * used in a Map while allowing Python ref objects to tell if the
139: * hashCode is actually valid for the object.
140: */
141: private void calcHash(PyObject object) {
142: try {
143: hash = object.hashCode();
144: realHash = true;
145: } catch (PyException e) {
146: if (Py.matchException(e, Py.TypeError)) {
147: hash = System.identityHashCode(object);
148: } else {
149: throw e;
150: }
151: }
152: }
153:
154: public synchronized void add(AbstractReference ref) {
155: Reference r = new WeakReference(ref);
156: references.addElement(r);
157: }
158:
159: private final AbstractReference getReferenceAt(int idx) {
160: WeakReference wref = (WeakReference) references
161: .elementAt(idx);
162: return (AbstractReference) wref.get();
163: }
164:
165: /**
166: * Search for a reusable refrence. To be reused, it must be of the
167: * same class and it must not have a callback.
168: */
169: synchronized AbstractReference find(Class cls) {
170: for (int i = references.size() - 1; i >= 0; i--) {
171: AbstractReference r = getReferenceAt(i);
172: if (r == null) {
173: references.removeElementAt(i);
174: } else if (r.callback == null && r.getClass() == cls) {
175: return r;
176: }
177: }
178: return null;
179: }
180:
181: /**
182: * Call each of the registered references.
183: */
184: synchronized void call() {
185: for (int i = references.size() - 1; i >= 0; i--) {
186: AbstractReference r = getReferenceAt(i);
187: if (r == null)
188: references.removeElementAt(i);
189: else
190: r.call();
191: }
192: }
193:
194: synchronized public int count() {
195: for (int i = references.size() - 1; i >= 0; i--) {
196: AbstractReference r = getReferenceAt(i);
197: if (r == null) {
198: references.removeElementAt(i);
199: }
200: }
201: return references.size();
202: }
203:
204: synchronized public PyList refs() {
205: Vector list = new Vector();
206: for (int i = references.size() - 1; i >= 0; i--) {
207: AbstractReference r = getReferenceAt(i);
208: if (r == null)
209: references.removeElementAt(i);
210: else
211: list.addElement(r);
212: }
213: return new PyList(list);
214: }
215:
216: /**
217: * Allow GlobalRef's to be used as hashtable keys.
218: */
219: public boolean equals(Object o) {
220: if (this == o)
221: return true;
222: if (!(o instanceof GlobalRef))
223: return false;
224: Object t = this .get();
225: Object u = ((GlobalRef) o).get();
226: if ((t == null) || (u == null))
227: return false;
228: if (t == u)
229: return true;
230: return t.equals(u);
231: }
232:
233: /**
234: * Allow GlobalRef's to be used as hashtable keys.
235: */
236: public int hashCode() {
237: return hash;
238: }
239: }
240:
241: public static abstract class AbstractReference extends PyObject {
242: PyObject callback;
243: protected GlobalRef gref;
244:
245: public AbstractReference(GlobalRef gref, PyObject callback) {
246: this .gref = gref;
247: this .callback = callback;
248: gref.add(this );
249: }
250:
251: void call() {
252: if (callback == null)
253: return;
254: try {
255: callback.__call__(this );
256: } catch (Exception exc) {
257: exc.printStackTrace();
258: }
259: }
260:
261: protected PyObject py() {
262: PyObject o = (PyObject) gref.get();
263: if (o == null) {
264: throw new PyException(ReferenceError,
265: "weakly-referenced object no longer exists");
266: }
267: return o;
268: }
269:
270: public int hashCode() {
271: if (gref.realHash) {
272: return gref.hash;
273: }
274: throw Py.TypeError("unhashable instance");
275: }
276:
277: public PyObject __eq__(PyObject other) {
278: if (other.getClass() != getClass())
279: return null;
280: PyObject pythis = (PyObject) gref.get();
281: PyObject pyother = (PyObject) ((AbstractReference) other).gref
282: .get();
283: if (pythis == null || pyother == null)
284: return this == other ? Py.One : Py.Zero;
285: return pythis ._eq(pyother);
286: }
287:
288: }
289:
290: public static class ReferenceType extends AbstractReference {
291: ReferenceType(GlobalRef gref, PyObject callback) {
292: super (gref, callback);
293: }
294:
295: public PyObject __call__() {
296: return Py.java2py(gref.get());
297: }
298:
299: public String toString() {
300: String ret = "<weakref " + Py.idstr(this ) + ";";
301: PyObject obj = (PyObject) gref.get();
302: if (obj != null)
303: ret += " to " + obj.safeRepr() + ">";
304: else
305: ret += " dead>";
306: return ret;
307: }
308: }
309:
310: public static class ProxyType extends AbstractReference {
311: ProxyType(GlobalRef ref, PyObject callback) {
312: super (ref, callback);
313: }
314:
315: public PyObject __findattr__(String name) {
316: return py().__findattr__(name);
317: }
318:
319: public void __setattr__(String name, PyObject value) {
320: py().__setattr__(name, value);
321: }
322:
323: public void __delattr__(String name) {
324: py().__delattr__(name);
325: }
326:
327: public PyString __str__() {
328: return py().__str__();
329: }
330:
331: public PyString __hex__() {
332: return py().__hex__();
333: }
334:
335: public PyString __oct__() {
336: return py().__oct__();
337: }
338:
339: public PyObject __int__() {
340: return py().__int__();
341: }
342:
343: public PyFloat __float__() {
344: return py().__float__();
345: }
346:
347: public PyLong __long__() {
348: return py().__long__();
349: }
350:
351: public PyComplex __complex__() {
352: return py().__complex__();
353: }
354:
355: public PyObject __pos__() {
356: return py().__pos__();
357: }
358:
359: public PyObject __neg__() {
360: return py().__neg__();
361: }
362:
363: public PyObject __abs__() {
364: return py().__abs__();
365: }
366:
367: public PyObject __invert__() {
368: return py().__invert__();
369: }
370:
371: public PyObject __add__(PyObject o) {
372: return py().__add__(o);
373: }
374:
375: public PyObject __radd__(PyObject o) {
376: return py().__radd__(o);
377: }
378:
379: public PyObject __iadd__(PyObject o) {
380: return py().__iadd__(o);
381: }
382:
383: public PyObject __sub__(PyObject o) {
384: return py().__sub__(o);
385: }
386:
387: public PyObject __rsub__(PyObject o) {
388: return py().__rsub__(o);
389: }
390:
391: public PyObject __isub__(PyObject o) {
392: return py().__isub__(o);
393: }
394:
395: public PyObject __mul__(PyObject o) {
396: return py().__mul__(o);
397: }
398:
399: public PyObject __rmul__(PyObject o) {
400: return py().__rmul__(o);
401: }
402:
403: public PyObject __imul__(PyObject o) {
404: return py().__imul__(o);
405: }
406:
407: public PyObject __div__(PyObject o) {
408: return py().__div__(o);
409: }
410:
411: public PyObject __rdiv__(PyObject o) {
412: return py().__rdiv__(o);
413: }
414:
415: public PyObject __idiv__(PyObject o) {
416: return py().__idiv__(o);
417: }
418:
419: public PyObject __mod__(PyObject o) {
420: return py().__mod__(o);
421: }
422:
423: public PyObject __rmod__(PyObject o) {
424: return py().__rmod__(o);
425: }
426:
427: public PyObject __imod__(PyObject o) {
428: return py().__imod__(o);
429: }
430:
431: public PyObject __divmod__(PyObject o) {
432: return py().__divmod__(o);
433: }
434:
435: public PyObject __rdivmod__(PyObject o) {
436: return py().__rdivmod__(o);
437: }
438:
439: public PyObject __pow__(PyObject o) {
440: return py().__pow__(o);
441: }
442:
443: public PyObject __rpow__(PyObject o) {
444: return py().__rpow__(o);
445: }
446:
447: public PyObject __ipow__(PyObject o) {
448: return py().__ipow__(o);
449: }
450:
451: public PyObject __lshift__(PyObject o) {
452: return py().__lshift__(o);
453: }
454:
455: public PyObject __rlshift__(PyObject o) {
456: return py().__rlshift__(o);
457: }
458:
459: public PyObject __ilshift__(PyObject o) {
460: return py().__ilshift__(o);
461: }
462:
463: public PyObject __rshift__(PyObject o) {
464: return py().__rshift__(o);
465: }
466:
467: public PyObject __rrshift__(PyObject o) {
468: return py().__rrshift__(o);
469: }
470:
471: public PyObject __irshift__(PyObject o) {
472: return py().__irshift__(o);
473: }
474:
475: public PyObject __and__(PyObject o) {
476: return py().__and__(o);
477: }
478:
479: public PyObject __rand__(PyObject o) {
480: return py().__rand__(o);
481: }
482:
483: public PyObject __iand__(PyObject o) {
484: return py().__iand__(o);
485: }
486:
487: public PyObject __or__(PyObject o) {
488: return py().__or__(o);
489: }
490:
491: public PyObject __ror__(PyObject o) {
492: return py().__ror__(o);
493: }
494:
495: public PyObject __ior__(PyObject o) {
496: return py().__ior__(o);
497: }
498:
499: public PyObject __xor__(PyObject o) {
500: return py().__xor__(o);
501: }
502:
503: public PyObject __rxor__(PyObject o) {
504: return py().__rxor__(o);
505: }
506:
507: public PyObject __ixor__(PyObject o) {
508: return py().__ixor__(o);
509: }
510:
511: public String toString() {
512: String ret = "<weakref " + Py.idstr(this );
513: PyObject obj = (PyObject) gref.get();
514: if (obj == null)
515: obj = Py.None;
516: ret += " to " + obj.safeRepr() + " " + Py.idstr(obj) + ">";
517: return ret;
518: }
519: }
520:
521: public static class CallableProxyType extends ProxyType {
522: CallableProxyType(GlobalRef ref, PyObject callback) {
523: super (ref, callback);
524: }
525:
526: public PyObject __call__(PyObject[] args, String[] kws) {
527: return py().__call__(args, kws);
528: }
529: }
530:
531: }
|