odyssey/src/mm_write.c

113 lines
2.2 KiB
C
Raw Normal View History

2017-03-21 12:47:05 +00:00
/*
* machinarium.
*
* cooperative multitasking engine.
*/
#include <machinarium.h>
#include <machinarium_private.h>
2017-03-21 12:47:05 +00:00
static void
2017-04-12 12:19:30 +00:00
mm_write_cb(mm_fd_t *handle)
2017-03-21 12:47:05 +00:00
{
2017-04-12 12:19:30 +00:00
mm_io_t *io = handle->on_write_arg;
mm_call_t *call = &io->call;
assert(mm_call_is(call, MM_CALL_WRITE));
if (mm_call_is_aborted(call))
return;
2017-04-12 12:19:30 +00:00
int left = io->write_size - io->write_pos;
int rc;
while (left > 0)
{
rc = mm_socket_write(io->fd, io->write_buf + io->write_pos, left);
if (rc == -1) {
if (errno == EAGAIN ||
errno == EWOULDBLOCK)
return;
2017-04-12 12:19:30 +00:00
if (errno == EINTR)
continue;
call->status = errno;
goto wakeup;
2017-04-12 12:19:30 +00:00
}
io->write_pos += rc;
left = io->write_size - io->write_pos;
assert(left >= 0);
return;
2017-04-12 12:19:30 +00:00
}
call->status = 0;
wakeup:
if (call->coroutine)
mm_scheduler_wakeup(&mm_self->scheduler, call->coroutine);
2017-03-21 12:47:05 +00:00
}
int mm_write(mm_io_t *io, char *buf, int size, uint32_t time_ms)
2017-03-21 12:47:05 +00:00
{
mm_machine_t *machine = mm_self;
2017-05-30 14:00:16 +00:00
mm_errno_set(0);
2017-04-12 12:19:30 +00:00
if (mm_call_is_active(&io->call)) {
2017-05-30 14:00:16 +00:00
mm_errno_set(EINPROGRESS);
2017-03-29 11:58:27 +00:00
return -1;
}
2017-04-12 12:19:30 +00:00
if (! io->connected) {
2017-05-30 14:00:16 +00:00
mm_errno_set(ENOTCONN);
2017-04-12 12:19:30 +00:00
return -1;
}
if (! io->attached) {
2017-05-30 14:00:16 +00:00
mm_errno_set(ENOTCONN);
return -1;
}
2017-04-12 12:19:30 +00:00
io->write_buf = buf;
io->write_size = size;
io->write_pos = 0;
2017-03-21 12:47:05 +00:00
io->handle.on_write = mm_write_cb;
io->handle.on_write_arg = io;
mm_call_fast(&io->call, MM_CALL_WRITE,
(void(*)(void*))mm_write_cb,
2017-04-20 12:08:56 +00:00
&io->handle);
if (io->call.status != 0) {
mm_errno_set(io->call.status);
return -1;
}
if (io->write_pos == io->write_size)
return 0;
2017-04-12 12:19:30 +00:00
/* subscribe for write event */
2017-03-21 12:47:05 +00:00
int rc;
rc = mm_loop_write(&machine->loop, &io->handle, mm_write_cb, io);
2017-04-12 12:19:30 +00:00
if (rc == -1) {
2017-05-30 14:00:16 +00:00
mm_errno_set(errno);
2017-03-29 11:58:27 +00:00
return -1;
2017-03-21 12:47:05 +00:00
}
2017-04-12 12:19:30 +00:00
/* wait for completion */
mm_call(&io->call, MM_CALL_WRITE, time_ms);
2017-04-12 12:19:30 +00:00
rc = mm_loop_write_stop(&machine->loop, &io->handle);
2017-04-12 12:19:30 +00:00
if (rc == -1) {
2017-05-30 14:00:16 +00:00
mm_errno_set(errno);
2017-04-12 12:19:30 +00:00
return -1;
}
rc = io->call.status;
2017-04-12 12:19:30 +00:00
if (rc != 0) {
2017-05-30 14:00:16 +00:00
mm_errno_set(rc);
2017-03-29 11:58:27 +00:00
return -1;
}
2017-03-21 12:47:05 +00:00
return 0;
}
MACHINE_API int
machine_write(machine_io_t obj, char *buf, int size, uint32_t time_ms)
{
mm_io_t *io = obj;
if (mm_tls_is_active(&io->tls))
return mm_tlsio_write(&io->tls, buf, size);
return mm_write(io, buf, size, time_ms);
}