Removed all code that uses OpenGL from Image.
[io/quag.git] / addons / AsyncRequest / source / IoAsyncRequest.c
blob63baf8b0ff98b4e41f6e74f8ca1c6a900e82f746
1 /*#io
2 AsyncRequest ioDoc(
3 docCopyright("Steve Dekorte", 2004)
4 docLicense("BSD revised")
5 docCategory("Filesystem")
6 docDescription("""Used for doing asynchronous file i/o.
7 Example use;
8 <pre>
10 </pre>
11 """)
14 #include "IoAsyncRequest.h"
15 #include "IoState.h"
16 #include "IoNumber.h"
17 #include "IoSeq.h"
19 #define IOCB(self) ((struct aiocb *)(IoObject_dataPointer(self)))
20 #define IOCB_BUFFER(self) ((void *)(IOCB(self)->aio_buf))
22 IoTag *IoAsyncRequest_newTag(void *state)
24 IoTag *tag = IoTag_newWithName_("AsyncRequest");
25 IoTag_state_(tag, state);
26 IoTag_cloneFunc_(tag, (IoTagCloneFunc *)IoAsyncRequest_rawClone);
27 IoTag_freeFunc_(tag, (IoTagFreeFunc *)IoAsyncRequest_free);
28 return tag;
31 IoAsyncRequest *IoAsyncRequest_proto(void *state)
33 IoAsyncRequest *self = IoObject_new(state);
34 IoObject_tag_(self, IoAsyncRequest_newTag(state));
36 IoObject_setDataPointer_(self, calloc(1, sizeof(struct aiocb)));
38 IoState_registerProtoWithFunc_(state, self, IoAsyncRequest_proto);
41 IoMethodTable methodTable[] = {
42 {"setDescriptor", IoAsyncRequest_setDescriptor},
43 {"descriptor", IoAsyncRequest_descriptor},
44 {"numberOfBytes", IoAsyncRequest_numberOfBytes},
45 {"read", IoAsyncRequest_read},
46 {"write", IoAsyncRequest_write},
47 {"isDone", IoAsyncRequest_isDone},
48 {"error", IoAsyncRequest_error},
49 {"cancel", IoAsyncRequest_cancel},
50 {"sync", IoAsyncRequest_sync},
51 {"copyBufferTo", IoAsyncRequest_copyBufferTo},
52 {NULL, NULL},
54 IoObject_addMethodTable_(self, methodTable);
57 return self;
60 IoAsyncRequest *IoAsyncRequest_rawClone(IoAsyncRequest *proto)
62 IoObject *self = IoObject_rawClonePrimitive(proto);
63 IoObject_setDataPointer_(self, calloc(1, sizeof(struct aiocb)));
64 return self;
67 IoAsyncRequest *IoAsyncRequest_new(void *state)
69 IoObject *proto = IoState_protoWithInitFunction_(state, IoAsyncRequest_proto);
70 return IOCLONE(proto);
73 void IoAsyncRequest_free(IoAsyncRequest *self)
75 int fd = IOCB(self)->aio_fildes;
77 if (fd)
79 aio_cancel(fd, IOCB(self));
82 if (IOCB_BUFFER(self))
84 free(IOCB_BUFFER(self));
87 free(IOCB(self));
90 // -----------------------------------------------------------
92 IoObject *IoAsyncRequest_setDescriptor(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
94 IOCB(self)->aio_fildes = IoMessage_locals_intArgAt_(m, locals, 0);
95 return self;
98 IoObject *IoAsyncRequest_descriptor(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
100 return IONUMBER(IOCB(self)->aio_fildes);
103 IoObject *IoAsyncRequest_numberOfBytes(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
105 return IONUMBER(IOCB(self)->aio_nbytes);
108 IoObject *IoAsyncRequest_position(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
110 return IONUMBER(IOCB(self)->aio_offset);
113 IoObject *IoAsyncRequest_read(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
115 int r;
117 IOCB(self)->aio_offset = (size_t)CNUMBER(IoMessage_locals_numberArgAt_(m, locals, 0));
118 IOCB(self)->aio_nbytes = IoMessage_locals_intArgAt_(m, locals, 1);
120 if (!IOCB_BUFFER(self))
122 IOCB(self)->aio_buf = calloc(1, IOCB(self)->aio_nbytes);
124 else
126 IOCB(self)->aio_buf = realloc(IOCB_BUFFER(self), IOCB(self)->aio_nbytes);
129 r = aio_read(IOCB(self));
131 return r == 0 ? self : IONIL(self);
134 IoObject *IoAsyncRequest_write(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
136 int r;
137 IoSeq *data;
138 UArray *ba;
139 int bufferOffset;
140 int bytesToWrite;
142 IOCB(self)->aio_offset = (size_t)CNUMBER(IoMessage_locals_numberArgAt_(m, locals, 0));
144 data = IoMessage_locals_seqArgAt_(m, locals, 1);
145 ba = IoSeq_rawUArray(data);
147 bufferOffset = IoMessage_locals_intArgAt_(m, locals, 2);
148 bytesToWrite = IoMessage_locals_intArgAt_(m, locals, 3);
150 if (bytesToWrite > UArray_size(ba) - bufferOffset)
152 bytesToWrite = UArray_size(ba) - bufferOffset;
155 IOCB(self)->aio_nbytes = bytesToWrite;
156 IOCB(self)->aio_buf = realloc(IOCB_BUFFER(self), bytesToWrite);
157 memcpy(IOCB_BUFFER(self), UArray_bytes(ba), bytesToWrite);
159 r = aio_write(IOCB(self));
161 return r == 0 ? self : IONIL(self);
164 IoObject *IoAsyncRequest_isDone(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
166 int r = aio_error(IOCB(self));
167 return (r == 0 || r != EINPROGRESS) ? IOTRUE(self) : IOFALSE(self);
170 #include <errno.h>
172 IoObject *IoAsyncRequest_error(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
174 int r;
176 errno = 0;
178 r = aio_error(IOCB(self));
180 if (r == -1)
182 char *s = strerror(errno);
184 if (errno == 22)
186 s = "The iocb argument does not reference an outstanding asynchronous I/O request.";
187 printf("AsyncRequest error: %s\n", s);
188 //return IOSYMBOL("The iocb argument does not reference an outstanding asynchronous I/O request.");
189 return IONIL(self);
192 printf("AsyncRequest errno %i : %s' EINVAL = %i\n", errno, s, EINVAL);
193 return IOSYMBOL(s);
196 if (r != 0 && r != EINPROGRESS)
198 char *s = strerror(r);
199 printf("AsyncRequest error %i\n", r);
200 return IOSYMBOL(s);
203 return IONIL(self);
206 IoObject *IoAsyncRequest_cancel(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
208 int r = aio_cancel(IOCB(self)->aio_fildes, IOCB(self));
209 return r == 0 ? self : IONIL(self);
212 IoObject *IoAsyncRequest_sync(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
214 int r = aio_fsync(O_SYNC, IOCB(self));
215 return r == 0 ? self : IONIL(self);
218 IoObject *IoAsyncRequest_copyBufferTo(IoAsyncRequest *self, IoObject *locals, IoMessage *m)
220 if (IOCB_BUFFER(self))
222 IoSeq *data = IoMessage_locals_mutableSeqArgAt_(m, locals, 0);
223 UArray *ba = IoSeq_rawUArray(data);
224 UArray_setData_type_size_copy_(ba, IOCB_BUFFER(self), CTYPE_uint8_t, IOCB(self)->aio_nbytes, 1);
225 return self;
228 return IONIL(self);