barbieri pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=3cb15c17e01bd86220891b3ad4ea755f934e19d6
commit 3cb15c17e01bd86220891b3ad4ea755f934e19d6 Author: Gustavo Sverzut Barbieri <barbi...@profusion.mobi> Date: Fri Oct 21 09:53:17 2016 -0200 efl_net_dialer_udp_example: be more 'correct' using events to read/write. instead of blindly reading and writing, which can lead to hangs due no server, let's use can_read and can_write to do the operations, this won't let us believe we can read when we can't. it's also the recommended approach, so let's show that in the examples so users don't copy&paste incorrect stuff :-) --- src/examples/ecore/efl_net_dialer_udp_example.c | 115 ++++++++++++++++++------ 1 file changed, 86 insertions(+), 29 deletions(-) diff --git a/src/examples/ecore/efl_net_dialer_udp_example.c b/src/examples/ecore/efl_net_dialer_udp_example.c index 4193cc1..6e113a9 100644 --- a/src/examples/ecore/efl_net_dialer_udp_example.c +++ b/src/examples/ecore/efl_net_dialer_udp_example.c @@ -7,61 +7,112 @@ #include <ctype.h> static int retval = EXIT_SUCCESS; -static Eina_Bool do_read = EINA_FALSE; +static int needed_reads = 0; static void _connected(void *data EINA_UNUSED, const Efl_Event *event) { + fprintf(stderr, "INFO: connected %s\n", + efl_net_dialer_address_dial_get(event->object)); +} + +static void +_can_read(void *data EINA_UNUSED, const Efl_Event *event) +{ char buf[1024]; Eina_Rw_Slice rw_slice = {.mem = buf, .len = sizeof(buf)}; - Eina_Slice slice = EINA_SLICE_STR_LITERAL("Hello World"); Eina_Error err; + Eina_Bool can_read = efl_io_reader_can_read_get(event->object); - fprintf(stderr, "INFO: connected %s\n", - efl_net_dialer_address_dial_get(event->object)); + /* NOTE: this message may appear with can read=0 BEFORE + * "read '...'" because efl_io_readr_read() will change the status + * of can_read to FALSE prior to return so we can print it! + */ + fprintf(stderr, "INFO: can read=%d (needed reads=%d)\n", can_read, needed_reads); + if (!can_read) return; - err = efl_io_writer_write(event->object, &slice, NULL); + if (!needed_reads) return; + + err = efl_io_reader_read(event->object, &rw_slice); if (err) { - fprintf(stderr, "ERROR: could not write: %s\n", eina_error_msg_get(err)); + fprintf(stderr, "ERROR: could not read: %s\n", eina_error_msg_get(err)); retval = EXIT_FAILURE; ecore_main_loop_quit(); return; } - fprintf(stderr, "INFO: wrote " EINA_SLICE_STR_FMT "\n", EINA_SLICE_STR_PRINT(slice)); + fprintf(stderr, "INFO: read '" EINA_SLICE_STR_FMT "'\n", EINA_SLICE_STR_PRINT(rw_slice)); - slice = (Eina_Slice)EINA_SLICE_STR_LITERAL("Second Write"); - err = efl_io_writer_write(event->object, &slice, NULL); - if (err) + needed_reads--; + if (!needed_reads) { - fprintf(stderr, "ERROR: could not write: %s\n", eina_error_msg_get(err)); - retval = EXIT_FAILURE; + retval = EXIT_SUCCESS; ecore_main_loop_quit(); - return; } +} - fprintf(stderr, "INFO: wrote " EINA_SLICE_STR_FMT "\n", EINA_SLICE_STR_PRINT(slice)); - - /* if CORK was used, then say we're done to generate the single final datagram */ - efl_net_socket_udp_cork_set(event->object, EINA_FALSE); +static void +_can_write(void *data EINA_UNUSED, const Efl_Event *event) +{ + static int needed_writes = 2; + Eina_Slice slice; + Eina_Error err; + Eina_Bool can_write = efl_io_writer_can_write_get(event->object); - if (!do_read) goto end; + /* NOTE: this message may appear with can write=0 BEFORE + * "wrote '...'" because efl_io_writer_write() will change the status + * of can_write to FALSE prior to return so we can print it! + */ + fprintf(stderr, "INFO: can write=%d (needed writes=%d)\n", can_write, needed_writes); + if (!can_write) return; - err = efl_io_reader_read(event->object, &rw_slice); - if (err) + if (needed_writes == 2) { - fprintf(stderr, "ERROR: could not read: %s\n", eina_error_msg_get(err)); - retval = EXIT_FAILURE; - ecore_main_loop_quit(); + slice = (Eina_Slice)EINA_SLICE_STR_LITERAL("Hello World"); + + err = efl_io_writer_write(event->object, &slice, NULL); + if (err) + { + fprintf(stderr, "ERROR: could not write: %s\n", eina_error_msg_get(err)); + retval = EXIT_FAILURE; + ecore_main_loop_quit(); + return; + } + + fprintf(stderr, "INFO: wrote '" EINA_SLICE_STR_FMT "'\n", EINA_SLICE_STR_PRINT(slice)); + } + else if (needed_writes == 1) + { + slice = (Eina_Slice)EINA_SLICE_STR_LITERAL("Second Write"); + err = efl_io_writer_write(event->object, &slice, NULL); + if (err) + { + fprintf(stderr, "ERROR: could not write: %s\n", eina_error_msg_get(err)); + retval = EXIT_FAILURE; + ecore_main_loop_quit(); + return; + } + + fprintf(stderr, "INFO: wrote '" EINA_SLICE_STR_FMT "'\n", EINA_SLICE_STR_PRINT(slice)); + + /* if CORK was used, then say we're done to generate the single final datagram */ + efl_net_socket_udp_cork_set(event->object, EINA_FALSE); + } + else if (needed_writes == 0) + { + if (needed_reads) + fprintf(stderr, "INFO: done writing, now wait for %d reads\n", needed_reads); + else + { + fprintf(stderr, "INFO: we're done\n"); + retval = EXIT_SUCCESS; + ecore_main_loop_quit(); + } return; } - fprintf(stderr, "INFO: read " EINA_SLICE_STR_FMT "\n", EINA_SLICE_STR_PRINT(rw_slice)); - - end: - retval = EXIT_SUCCESS; - ecore_main_loop_quit(); + needed_writes--; } static void @@ -83,7 +134,10 @@ _error(void *data EINA_UNUSED, const Efl_Event *event) EFL_CALLBACKS_ARRAY_DEFINE(dialer_cbs, { EFL_NET_DIALER_EVENT_CONNECTED, _connected }, { EFL_NET_DIALER_EVENT_RESOLVED, _resolved }, - { EFL_NET_DIALER_EVENT_ERROR, _error }); + { EFL_NET_DIALER_EVENT_ERROR, _error }, + { EFL_IO_READER_EVENT_CAN_READ_CHANGED, _can_read }, + { EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED, _can_write } + ); static const Ecore_Getopt options = { "efl_net_dialer_udp_example", /* program name */ @@ -113,6 +167,7 @@ main(int argc, char **argv) { char *address = NULL; Eina_Bool cork = EINA_FALSE; + Eina_Bool do_read = EINA_FALSE; Eina_Bool quit_option = EINA_FALSE; double timeout_dial = 30.0; Ecore_Getopt_Value values[] = { @@ -182,6 +237,8 @@ main(int argc, char **argv) efl_net_socket_udp_cork_get(dialer), efl_net_dialer_timeout_dial_get(dialer)); + if (do_read) needed_reads = cork ? 1 : 2; + ecore_main_loop_begin(); fprintf(stderr, "INFO: main loop finished.\n"); --