3 docCopyright("Steve Dekorte", 2004)
4 docLicense("BSD revised")
5 docCategory("Filesystem")
6 docDescription("""Used for doing asynchronous file i/o.
14 #include "IoAsyncRequest.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
);
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
},
54 IoObject_addMethodTable_(self
, methodTable
);
60 IoAsyncRequest
*IoAsyncRequest_rawClone(IoAsyncRequest
*proto
)
62 IoObject
*self
= IoObject_rawClonePrimitive(proto
);
63 IoObject_setDataPointer_(self
, calloc(1, sizeof(struct aiocb
)));
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
;
79 aio_cancel(fd
, IOCB(self
));
82 if (IOCB_BUFFER(self
))
84 free(IOCB_BUFFER(self
));
90 // -----------------------------------------------------------
92 IoObject
*IoAsyncRequest_setDescriptor(IoAsyncRequest
*self
, IoObject
*locals
, IoMessage
*m
)
94 IOCB(self
)->aio_fildes
= IoMessage_locals_intArgAt_(m
, locals
, 0);
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
)
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
);
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
)
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
);
172 IoObject
*IoAsyncRequest_error(IoAsyncRequest
*self
, IoObject
*locals
, IoMessage
*m
)
178 r
= aio_error(IOCB(self
));
182 char *s
= strerror(errno
);
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.");
192 printf("AsyncRequest errno %i : %s' EINVAL = %i\n", errno
, s
, EINVAL
);
196 if (r
!= 0 && r
!= EINPROGRESS
)
198 char *s
= strerror(r
);
199 printf("AsyncRequest error %i\n", r
);
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);