Fixed a lazySlot bug where lazy slots in different objects end up pointing to the...
[io/quag.git] / libs / iovm / source / IoWeakLink.c
blob197ed5f06d77ebdd04c62a85e074347d1cd26651
1 /*#io
2 WeakLink ioDoc(
3 docCopyright("Steve Dekorte", 2002)
4 docLicense("BSD revised")
5 docCategory("Core")
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.
7 """)
8 */
10 #include "IoWeakLink.h"
11 #include "IoSeq.h"
12 #include "IoState.h"
13 #include "IoObject.h"
14 #include "IoNumber.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_);
27 return tag;
30 void IoWeakLink_writeToStream_(IoWeakLink *self, BStream *stream)
32 if (DATA(self)->link)
34 BStream_writeTaggedInt32_(stream, IoObject_pid(DATA(self)->link));
36 else
38 BStream_writeTaggedInt32_(stream, 0);
42 void IoWeakLink_readFromStream_(IoWeakLink *self, BStream *stream)
44 PID_TYPE linkid = BStream_readTaggedInt32(stream);
46 if (linkid != 0)
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},
58 {NULL, NULL},
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);
69 return self;
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;
77 return self;
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;
101 return self;
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)
114 /*#io
115 docSlot("setLink(aValue)", "Sets the link pointer. Returns self.")
118 IoWeakLink_rawSetLink(self, IoMessage_locals_valueArgAt_(m, locals, 0));
119 return self;
122 void IoWeakLink_rawSetLink(IoWeakLink *self, IoObject *v)
124 IoWeakLink_rawStopListening(self);
126 if (ISNIL(v))
128 DATA(self)->link = NULL;
130 else
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)
139 /*#io
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);