Addons updated to new doc format
[io.git] / addons / AsyncRequest / source / IoAsyncRequest.c
blobafdf83e51bae79abfbcf365dd6ec15550387e643
1 //metadoc AsyncRequest copyright Steve Dekorte, 2004
2 //metadoc AsyncRequest license BSD revised
3 //metadoc AsyncRequest category Filesystem
4 /*metadoc AsyncRequest description
5 Used for doing asynchronous file i/o.
6 Example use;
7 <code>
9 </code>
12 #include "IoAsyncRequest.h"
13 #include "IoState.h"
14 #include "IoNumber.h"
15 #include "IoSeq.h"
17 #define IOCB(self) ((struct aiocb *)(IoObject_dataPointer(self)))
18 #define IOCB_BUFFER(self) ((void *)(IOCB(self)->aio_buf))
20 IoTag *IoAsyncRequest_newTag(void *state)
22 IoTag *tag = IoTag_newWithName_("AsyncRequest");
23 IoTag_state_(tag, state);
24 IoTag_cloneFunc_(tag, (IoTagCloneFunc *)IoAsyncRequest_rawClone);
25 IoTag_freeFunc_(tag, (IoTagFreeFunc *)IoAsyncRequest_free);
26 return tag;
29 IoAsyncRequest *IoAsyncRequest_proto(void *state)
31 IoAsyncRequest *self = IoObject_new(state);
32 IoObject_tag_(self, IoAsyncRequest_newTag(state));
34 IoObject_setDataPointer_(self, calloc(1, sizeof(struct aiocb)));
36 IoState_registerProtoWithFunc_(state, self, IoAsyncRequest_proto);
39 IoMethodTable methodTable[] = {
40 {"setDescriptor", IoAsyncRequest_setDescriptor},
41 {"descriptor", IoAsyncRequest_descriptor},
42 {"numberOfBytes", IoAsyncRequest_numberOfBytes},
43 {"read", IoAsyncRequest_read},
44 {"write", IoAsyncRequest_write},
45 {"isDone", IoAsyncRequest_isDone},
46 {"error", IoAsyncRequest_error},
47 {"cancel", IoAsyncRequest_cancel},
48 {"sync", IoAsyncRequest_sync},
49 {"copyBufferTo", IoAsyncRequest_copyBufferTo},
50 {NULL, NULL},
52 IoObject_addMethodTable_(self, methodTable);
55 return self;
58 IoAsyncRequest *IoAsyncRequest_rawClone(IoAsyncRequest *proto)
60 IoObject *self = IoObject_rawClonePrimitive(proto);
61 IoObject_setDataPointer_(self, calloc(1, sizeof(struct aiocb)));
62 return self;
65 IoAsyncRequest *IoAsyncRequest_new(void *state)
67 IoObject *proto = IoState_protoWithInitFunction_(state, IoAsyncRequest_proto);
68 return IOCLONE(proto);
71 void IoAsyncRequest_free(IoAsyncRequest *self)
73 int fd = IOCB(self)->aio_fildes;
75 if (fd)
77 aio_cancel(fd, IOCB(self));
80 if (IOCB_BUFFER(self))
82 free(IOCB_BUFFER(self));
85 free(IOCB(self));
88 // -----------------------------------------------------------
90 IoObject *IoAsyncRequest_setDescriptor(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
92 IOCB(self)->aio_fildes = IoMessage_locals_intArgAt_(m, locals, 0);
93 return self;
96 IoObject *IoAsyncRequest_descriptor(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
98 return IONUMBER(IOCB(self)->aio_fildes);
101 IoObject *IoAsyncRequest_numberOfBytes(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
103 return IONUMBER(IOCB(self)->aio_nbytes);
106 IoObject *IoAsyncRequest_position(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
108 return IONUMBER(IOCB(self)->aio_offset);
111 IoObject *IoAsyncRequest_read(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
113 int r;
115 IOCB(self)->aio_offset = (size_t)CNUMBER(IoMessage_locals_numberArgAt_(m, locals, 0));
116 IOCB(self)->aio_nbytes = IoMessage_locals_intArgAt_(m, locals, 1);
118 if (!IOCB_BUFFER(self))
120 IOCB(self)->aio_buf = calloc(1, IOCB(self)->aio_nbytes);
122 else
124 IOCB(self)->aio_buf = realloc(IOCB_BUFFER(self), IOCB(self)->aio_nbytes);
127 r = aio_read(IOCB(self));
129 return r == 0 ? self : IONIL(self);
132 IoObject *IoAsyncRequest_write(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
134 int r;
135 IoSeq *data;
136 UArray *ba;
137 int bufferOffset;
138 int bytesToWrite;
140 IOCB(self)->aio_offset = (size_t)CNUMBER(IoMessage_locals_numberArgAt_(m, locals, 0));
142 data = IoMessage_locals_seqArgAt_(m, locals, 1);
143 ba = IoSeq_rawUArray(data);
145 bufferOffset = IoMessage_locals_intArgAt_(m, locals, 2);
146 bytesToWrite = IoMessage_locals_intArgAt_(m, locals, 3);
148 if (bytesToWrite > UArray_size(ba) - bufferOffset)
150 bytesToWrite = UArray_size(ba) - bufferOffset;
153 IOCB(self)->aio_nbytes = bytesToWrite;
154 IOCB(self)->aio_buf = realloc(IOCB_BUFFER(self), bytesToWrite);
155 memcpy(IOCB_BUFFER(self), UArray_bytes(ba), bytesToWrite);
157 r = aio_write(IOCB(self));
159 return r == 0 ? self : IONIL(self);
162 IoObject *IoAsyncRequest_isDone(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
164 int r = aio_error(IOCB(self));
165 return (r == 0 || r != EINPROGRESS) ? IOTRUE(self) : IOFALSE(self);
168 #include <errno.h>
170 IoObject *IoAsyncRequest_error(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
172 int r;
174 errno = 0;
176 r = aio_error(IOCB(self));
178 if (r == -1)
180 char *s = strerror(errno);
182 if (errno == 22)
184 s = "The iocb argument does not reference an outstanding asynchronous I/O request.";
185 printf("AsyncRequest error: %s\n", s);
186 //return IOSYMBOL("The iocb argument does not reference an outstanding asynchronous I/O request.");
187 return IONIL(self);
190 printf("AsyncRequest errno %i : %s' EINVAL = %i\n", errno, s, EINVAL);
191 return IOSYMBOL(s);
194 if (r != 0 && r != EINPROGRESS)
196 char *s = strerror(r);
197 printf("AsyncRequest error %i\n", r);
198 return IOSYMBOL(s);
201 return IONIL(self);
204 IoObject *IoAsyncRequest_cancel(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
206 int r = aio_cancel(IOCB(self)->aio_fildes, IOCB(self));
207 return r == 0 ? self : IONIL(self);
210 IoObject *IoAsyncRequest_sync(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
212 int r = aio_fsync(O_SYNC, IOCB(self));
213 return r == 0 ? self : IONIL(self);
216 IoObject *IoAsyncRequest_copyBufferTo(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
218 if (IOCB_BUFFER(self))
220 IoSeq *data = IoMessage_locals_mutableSeqArgAt_(m, locals, 0);
221 UArray *ba = IoSeq_rawUArray(data);
222 UArray_setData_type_size_copy_(ba, IOCB_BUFFER(self), CTYPE_uint8_t, IOCB(self)->aio_nbytes, 1);
223 return self;
226 return IONIL(self);