summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-11-25 16:48:45 -0200
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-11-25 17:25:18 -0200
commit16be61c7e15d89ba9ba4529e0d280dcb5fb81da7 (patch)
tree8c8b4952f4cd019ce9bcaf3d34f6ae22d7ae407b /src/lib
parentd9dafab78531f676217e0e81d78c0533edd0cc30 (diff)
efl_io_copier_flush: add may_block and ignore_line_delimiter parameters.
The may_block parameter is useful to force a flush without blocking on read/write, sometimes particularly useful if ignore_line_delimiter is true, then you get the data events without blocking -- as if a server sending some content misses a trailing line delimiter, you do not want to block on recv() but still want to flush data to user. The ignore_line_delimiter parameter is useful if we're going to close the copier and want to flush pending data which may exist due missing trailing terminator. The close method will also force that if destination can take more data.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ecore/efl_io_copier.c58
-rw-r--r--src/lib/ecore/efl_io_copier.eo4
-rw-r--r--src/lib/ecore_ipc/ecore_ipc.c4
3 files changed, 60 insertions, 6 deletions
diff --git a/src/lib/ecore/efl_io_copier.c b/src/lib/ecore/efl_io_copier.c
index 3eee61ff59..c92a8efca0 100644
--- a/src/lib/ecore/efl_io_copier.c
+++ b/src/lib/ecore/efl_io_copier.c
@@ -27,6 +27,7 @@ typedef struct _Efl_Io_Copier_Data
27 double inactivity_timeout; 27 double inactivity_timeout;
28 Eina_Bool closed; 28 Eina_Bool closed;
29 Eina_Bool done; 29 Eina_Bool done;
30 Eina_Bool force_dispatch;
30 Eina_Bool close_on_exec; 31 Eina_Bool close_on_exec;
31 Eina_Bool close_on_destructor; 32 Eina_Bool close_on_destructor;
32} Efl_Io_Copier_Data; 33} Efl_Io_Copier_Data;
@@ -281,7 +282,7 @@ _efl_io_copier_write(Eo *o, Efl_Io_Copier_Data *pd)
281 return; 282 return;
282 } 283 }
283 284
284 if ((pd->line_delimiter.len > 0) && 285 if ((pd->line_delimiter.len > 0) && (!pd->force_dispatch) &&
285 (pd->source && !efl_io_reader_eos_get(pd->source))) 286 (pd->source && !efl_io_reader_eos_get(pd->source)))
286 { 287 {
287 const uint8_t *p = eina_slice_find(ro_slice, pd->line_delimiter); 288 const uint8_t *p = eina_slice_find(ro_slice, pd->line_delimiter);
@@ -469,6 +470,8 @@ _efl_io_copier_destination_closed(void *data, const Efl_Event *event EINA_UNUSED
469 { 470 {
470 Eina_Error err = EBADF; 471 Eina_Error err = EBADF;
471 if (pd->inactivity_timer) efl_future_cancel(pd->inactivity_timer); 472 if (pd->inactivity_timer) efl_future_cancel(pd->inactivity_timer);
473 WRN("copier %p destination %p closed with %zd bytes pending...",
474 o, pd->destination, eina_binbuf_length_get(pd->buf));
472 efl_event_callback_call(o, EFL_IO_COPIER_EVENT_ERROR, &err); 475 efl_event_callback_call(o, EFL_IO_COPIER_EVENT_ERROR, &err);
473 } 476 }
474} 477}
@@ -604,6 +607,34 @@ _efl_io_copier_efl_io_closer_close(Eo *o, Efl_Io_Copier_Data *pd)
604 607
605 _COPIER_DBG(o, pd); 608 _COPIER_DBG(o, pd);
606 609
610 while (pd->buf)
611 {
612 size_t pending = eina_binbuf_length_get(pd->buf);
613 if (pending == 0) break;
614 else if (pd->destination && efl_io_writer_can_write_get(pd->destination))
615 {
616 DBG("copier %p destination %p closed with %zd bytes pending, do final write...",
617 o, pd->destination, pending);
618 pd->force_dispatch = EINA_TRUE;
619 _efl_io_copier_write(o, pd);
620 pd->force_dispatch = EINA_FALSE;
621 }
622 else if (!pd->destination)
623 {
624 Eina_Slice binbuf_slice = eina_binbuf_slice_get(pd->buf);
625 DBG("copier %p destination %p closed with %zd bytes pending, dispatch events...",
626 o, pd->destination, pending);
627 _efl_io_copier_dispatch_data_events(o, pd, binbuf_slice);
628 break;
629 }
630 else
631 {
632 DBG("copier %p destination %p closed with %zd bytes pending...",
633 o, pd->destination, pending);
634 break;
635 }
636 }
637
607 if (pd->job) 638 if (pd->job)
608 efl_future_cancel(pd->job); 639 efl_future_cancel(pd->job);
609 640
@@ -699,7 +730,7 @@ _efl_io_copier_inactivity_timeout_get(Eo *o EINA_UNUSED, Efl_Io_Copier_Data *pd)
699} 730}
700 731
701EOLIAN static Eina_Bool 732EOLIAN static Eina_Bool
702_efl_io_copier_flush(Eo *o, Efl_Io_Copier_Data *pd) 733_efl_io_copier_flush(Eo *o, Efl_Io_Copier_Data *pd, Eina_Bool may_block, Eina_Bool ignore_line_delimiter)
703{ 734{
704 uint64_t old_read = pd->progress.read; 735 uint64_t old_read = pd->progress.read;
705 uint64_t old_written = pd->progress.written; 736 uint64_t old_written = pd->progress.written;
@@ -708,10 +739,29 @@ _efl_io_copier_flush(Eo *o, Efl_Io_Copier_Data *pd)
708 _COPIER_DBG(o, pd); 739 _COPIER_DBG(o, pd);
709 740
710 if (pd->source && !efl_io_reader_eos_get(pd->source)) 741 if (pd->source && !efl_io_reader_eos_get(pd->source))
711 _efl_io_copier_read(o, pd); 742 {
743 if (may_block || efl_io_reader_can_read_get(pd->source))
744 _efl_io_copier_read(o, pd);
745 }
712 746
713 if (pd->destination) 747 if (pd->destination)
714 _efl_io_copier_write(o, pd); 748 {
749 if (may_block || efl_io_writer_can_write_get(pd->source))
750 {
751 pd->force_dispatch = ignore_line_delimiter;
752 _efl_io_copier_write(o, pd);
753 pd->force_dispatch = EINA_FALSE;
754 }
755 }
756 else if (ignore_line_delimiter && pd->buf)
757 {
758 size_t pending = eina_binbuf_length_get(pd->buf);
759 if (pending)
760 {
761 Eina_Slice binbuf_slice = eina_binbuf_slice_get(pd->buf);
762 _efl_io_copier_dispatch_data_events(o, pd, binbuf_slice);
763 }
764 }
715 765
716 if ((old_read != pd->progress.read) || 766 if ((old_read != pd->progress.read) ||
717 (old_written != pd->progress.written) || 767 (old_written != pd->progress.written) ||
diff --git a/src/lib/ecore/efl_io_copier.eo b/src/lib/ecore/efl_io_copier.eo
index 1c0bd5fd93..36ad624843 100644
--- a/src/lib/ecore/efl_io_copier.eo
+++ b/src/lib/ecore/efl_io_copier.eo
@@ -335,6 +335,10 @@ class Efl.Io.Copier (Efl.Loop_User, Efl.Io.Closer) {
335 approach is to operate asynchronously and wait for 335 approach is to operate asynchronously and wait for
336 "done" event. 336 "done" event.
337 ]] 337 ]]
338 params {
339 may_block: bool; [[If $true, then @Efl.Io.Reader.can_read and @Efl.Io.Writer.can_write are not checked and the call may block.]]
340 ignore_line_delimiter: bool; [[Force flush ignoring line delimiters]]
341 }
338 return: bool(true); [[$true on success, $false otherwise]] 342 return: bool(true); [[$true on success, $false otherwise]]
339 } 343 }
340 } 344 }
diff --git a/src/lib/ecore_ipc/ecore_ipc.c b/src/lib/ecore_ipc/ecore_ipc.c
index e227251467..e4287aa4fa 100644
--- a/src/lib/ecore_ipc/ecore_ipc.c
+++ b/src/lib/ecore_ipc/ecore_ipc.c
@@ -1210,7 +1210,7 @@ ecore_ipc_server_flush(Ecore_Ipc_Server *svr)
1210 if (svr->dialer.input) 1210 if (svr->dialer.input)
1211 { 1211 {
1212 while (efl_io_queue_usage_get(svr->dialer.input) > 0) 1212 while (efl_io_queue_usage_get(svr->dialer.input) > 0)
1213 efl_io_copier_flush(svr->dialer.send_copier); 1213 efl_io_copier_flush(svr->dialer.send_copier, EINA_TRUE, EINA_TRUE);
1214 return; 1214 return;
1215 } 1215 }
1216 else if (svr->server) 1216 else if (svr->server)
@@ -1627,7 +1627,7 @@ ecore_ipc_client_flush(Ecore_Ipc_Client *cl)
1627 if (cl->socket.input) 1627 if (cl->socket.input)
1628 { 1628 {
1629 while (efl_io_queue_usage_get(cl->socket.input) > 0) 1629 while (efl_io_queue_usage_get(cl->socket.input) > 0)
1630 efl_io_copier_flush(cl->socket.send_copier); 1630 efl_io_copier_flush(cl->socket.send_copier, EINA_TRUE, EINA_TRUE);
1631 return; 1631 return;
1632 } 1632 }
1633#ifndef EFL_NET_SERVER_UNIX_CLASS 1633#ifndef EFL_NET_SERVER_UNIX_CLASS