3 docCopyright("Steve Dekorte", 2002)
4 docLicense("BSD revised")
6 docDescription("""A WeakLink is a primitive that can hold a reference to an object without preventing the garbage collector from collecting it. The link reference is set with the setLink() method. After the garbage collector collects an object, it informs any (uncollected) WeakLink objects whose link value pointed to that object by calling their "collectedLink" method.
10 #include "IoWeakLink.h"
16 #define DATA(self) ((IoWeakLinkData *)IoObject_dataPointer(self))
18 IoTag
*IoWeakLink_newTag(void *state
)
20 IoTag
*tag
= IoTag_newWithName_("WeakLink");
21 IoTag_state_(tag
, state
);
22 IoTag_cloneFunc_(tag
, (IoTagCloneFunc
*)IoWeakLink_rawClone
);
23 IoTag_freeFunc_(tag
, (IoTagFreeFunc
*)IoWeakLink_free
);
24 IoTag_notificationFunc_(tag
, (IoTagNotificationFunc
*)IoWeakLink_notification
);
25 IoTag_writeToStreamFunc_(tag
, (IoTagWriteToStreamFunc
*)IoWeakLink_writeToStream_
);
26 IoTag_readFromStreamFunc_(tag
, (IoTagReadFromStreamFunc
*)IoWeakLink_readFromStream_
);
30 void IoWeakLink_writeToStream_(IoWeakLink
*self
, BStream
*stream
)
34 BStream_writeTaggedInt32_(stream
, IoObject_pid(DATA(self
)->link
));
38 BStream_writeTaggedInt32_(stream
, 0);
42 void IoWeakLink_readFromStream_(IoWeakLink
*self
, BStream
*stream
)
44 PID_TYPE linkid
= BStream_readTaggedInt32(stream
);
48 IoObject
*link
= IoState_objectWithPid_(IOSTATE
, linkid
);
49 IoWeakLink_rawSetLink(self
, link
);
53 IoObject
*IoWeakLink_proto(void *state
)
55 IoMethodTable methodTable
[] = {
56 {"setLink", IoWeakLink_setLink
},
57 {"link", IoWeakLink_link
},
61 IoObject
*self
= IoObject_new(state
);
63 IoObject_setDataPointer_(self
, io_calloc(1, sizeof(IoWeakLinkData
)));
64 IoObject_tag_(self
, IoWeakLink_newTag(state
));
65 DATA(self
)->link
= NULL
;
66 IoState_registerProtoWithFunc_((IoState
*)state
, self
, IoWeakLink_proto
);
68 IoObject_addMethodTable_(self
, methodTable
);
72 IoObject
*IoWeakLink_rawClone(IoWeakLink
*proto
)
74 IoObject
*self
= IoObject_rawClonePrimitive(proto
);
75 IoObject_setDataPointer_(self
, io_calloc(1, sizeof(IoWeakLinkData
)));
76 DATA(self
)->link
= NULL
;
80 IoObject
*IoWeakLink_new(void *state
)
82 IoObject
*proto
= IoState_protoWithInitFunction_((IoState
*)state
, IoWeakLink_proto
);
83 return IOCLONE(proto
);
86 void IoWeakLink_rawStopListening(IoWeakLink
*self
)
88 if (DATA(self
)->link
) IoObject_removeListener_(DATA(self
)->link
, self
);
91 void IoWeakLink_free(IoWeakLink
*self
)
93 IoWeakLink_rawStopListening(self
);
94 io_free(IoObject_dataPointer(self
));
97 IoObject
*IoWeakLink_newWithValue_(void *state
, IoObject
*v
)
99 IoObject
*self
= IoWeakLink_new(state
);
100 DATA(self
)->link
= v
;
104 void IoWeakLink_notification(IoWeakLink
*self
, void *notification
) // called when link is freed
106 DATA(self
)->link
= NULL
;
107 //IoMessage_locals_performOn_(IOSTATE->collectedLinkMessage, self, self);
110 // -----------------------------------------------------------
112 IoObject
*IoWeakLink_setLink(IoWeakLink
*self
, IoObject
*locals
, IoMessage
*m
)
115 docSlot("setLink(aValue)", "Sets the link pointer. Returns self.")
118 IoWeakLink_rawSetLink(self
, IoMessage_locals_valueArgAt_(m
, locals
, 0));
122 void IoWeakLink_rawSetLink(IoWeakLink
*self
, IoObject
*v
)
124 IoWeakLink_rawStopListening(self
);
128 DATA(self
)->link
= NULL
;
132 DATA(self
)->link
= v
; // no IOREF needed since this is a weak link
133 IoObject_addListener_(v
, self
);
137 IoObject
*IoWeakLink_link(IoWeakLink
*self
, IoObject
*locals
, IoMessage
*m
)
140 docSlot("link", "Returns the link pointer or Nil if none is set.")
143 IoObject
*v
= DATA(self
)->link
;
144 return v
? v
: IONIL(self
);