|
1 | 1 | use super::objtype::PyClassRef;
|
2 | 2 | use crate::function::{OptionalArg, PyFuncArgs};
|
3 | 3 | use crate::pyobject::{
|
4 |
| - PyClassImpl, PyContext, PyObject, PyObjectPayload, PyObjectRef, PyRef, PyResult, PyValue, |
| 4 | + IdProtocol, PyClassImpl, PyContext, PyObject, PyObjectPayload, PyObjectRef, PyRef, PyResult, |
| 5 | + PyValue, TypeProtocol, |
5 | 6 | };
|
6 | 7 | use crate::slots::SlotCall;
|
7 | 8 | use crate::vm::VirtualMachine;
|
8 | 9 |
|
| 10 | +use crate::pyhash::PyHash; |
| 11 | +use crossbeam_utils::atomic::AtomicCell; |
9 | 12 | use std::sync::{Arc, Weak};
|
10 | 13 |
|
11 | 14 | #[pyclass]
|
12 | 15 | #[derive(Debug)]
|
13 | 16 | pub struct PyWeak {
|
14 | 17 | referent: Weak<PyObject<dyn PyObjectPayload>>,
|
| 18 | + hash: AtomicCell<Option<PyHash>>, |
15 | 19 | }
|
16 | 20 |
|
17 | 21 | impl PyWeak {
|
18 | 22 | pub fn downgrade(obj: &PyObjectRef) -> PyWeak {
|
19 | 23 | PyWeak {
|
20 | 24 | referent: Arc::downgrade(obj),
|
| 25 | + hash: AtomicCell::new(None), |
21 | 26 | }
|
22 | 27 | }
|
23 | 28 |
|
@@ -53,6 +58,48 @@ impl PyWeak {
|
53 | 58 | ) -> PyResult<PyRef<Self>> {
|
54 | 59 | PyWeak::downgrade(&referent).into_ref_with_type(vm, cls)
|
55 | 60 | }
|
| 61 | + |
| 62 | + #[pymethod(magic)] |
| 63 | + fn hash(&self, vm: &VirtualMachine) -> PyResult<PyHash> { |
| 64 | + match self.hash.load() { |
| 65 | + Some(hash) => Ok(hash), |
| 66 | + None => { |
| 67 | + let obj = self |
| 68 | + .upgrade() |
| 69 | + .ok_or_else(|| vm.new_type_error("weak object has gone away".to_owned()))?; |
| 70 | + let hash = vm._hash(&obj)?; |
| 71 | + self.hash.store(Some(hash)); |
| 72 | + Ok(hash) |
| 73 | + } |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + #[pymethod(magic)] |
| 78 | + fn eq(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { |
| 79 | + if let Some(other) = other.payload_if_subclass::<Self>(vm) { |
| 80 | + self.upgrade() |
| 81 | + .and_then(|s| other.upgrade().map(|o| (s, o))) |
| 82 | + .map_or(Ok(false), |(a, b)| vm.bool_eq(a, b)) |
| 83 | + .map(|b| vm.new_bool(b)) |
| 84 | + } else { |
| 85 | + Ok(vm.ctx.not_implemented()) |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + #[pymethod(magic)] |
| 90 | + fn repr(zelf: PyRef<Self>) -> String { |
| 91 | + let id = zelf.get_id(); |
| 92 | + if let Some(o) = zelf.upgrade() { |
| 93 | + format!( |
| 94 | + "<weakref at {}; to '{}' at {}>", |
| 95 | + id, |
| 96 | + o.class().name, |
| 97 | + o.get_id(), |
| 98 | + ) |
| 99 | + } else { |
| 100 | + format!("<weakref at {}; dead>", id) |
| 101 | + } |
| 102 | + } |
56 | 103 | }
|
57 | 104 |
|
58 | 105 | pub fn init(context: &PyContext) {
|
|
0 commit comments