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.
12 #include "IoAsyncRequest.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
);
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
},
52 IoObject_addMethodTable_(self
, methodTable
);
58 IoAsyncRequest
*IoAsyncRequest_rawClone(IoAsyncRequest
*proto
)
60 IoObject
*self
= IoObject_rawClonePrimitive(proto
);
61 IoObject_setDataPointer_(self
, calloc(1, sizeof(struct aiocb
)));
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
;
77 aio_cancel(fd
, IOCB(self
));
80 if (IOCB_BUFFER(self
))
82 free(IOCB_BUFFER(self
));
88 // -----------------------------------------------------------
90 IoObject
*IoAsyncRequest_setDescriptor(IoAsyncRequest
*self
, IoObject
*locals
, IoMessage
*m
)
92 IOCB(self
)->aio_fildes
= IoMessage_locals_intArgAt_(m
, locals
, 0);
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
)
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
);
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
)
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
);
170 IoObject
*IoAsyncRequest_error(IoAsyncRequest
*self
, IoObject
*locals
, IoMessage
*m
)
176 r
= aio_error(IOCB(self
));
180 char *s
= strerror(errno
);
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.");
190 printf("AsyncRequest errno %i : %s' EINVAL = %i\n", errno
, s
, EINVAL
);
194 if (r
!= 0 && r
!= EINPROGRESS
)
196 char *s
= strerror(r
);
197 printf("AsyncRequest error %i\n", r
);
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);