New version. In this version ecore_read and ecore_write are symmetric. Now
we read the size of the data and then the data. The method block until we
get a first data of length equals to sizeof(unsigned int) and then until we
get a data of length equals to the first data read.
2009/9/14 Atton Jonathan <jonathan.at...@gmail.com>
> hey,
>
> The attached patch add the method ecore_pipe_read() to ecore.
>
> During the creation of the Ecore_Pipe the handler can be null. In this case
> the readable side of the pipe will block. I use it to pause a thread during
> an operation.
> The thread send a data to the main_loop with a pipe. Then the thread use
> ecore_pipe_read() and will block. When the main loop has terminate his
> operation, it write a data in the pipe and the thread is unblock.
> Consequently the main loop can works on a data used by the thread as the
> thread is in pause.
>
>
> Please review the patch, maybe you want to do this in an other way.
>
> --
> Regards.
>
--
Regards.
Index: ecore_pipe.c
===================================================================
--- ecore_pipe.c (revision 42487)
+++ ecore_pipe.c (working copy)
@@ -1,4 +1,47 @@
/*
+pe"
============================================================================
+" Netrw Directory Listing (netrw v125)
+" /home/Watchwolf/Projects/e/trunk/ecore/src/lib/ecore
+" Sorted by name
+" Sort sequence:
[\/]$,\.h$,\.c$,\.cpp$,*,\.o$,\.obj$,\.info$,\.swp$,\.bak$,\~$
+" Quick Help: <F1>:help -:go up dir D:delete R:rename s:sort-by x:exec
+" ============================================================================
+../
+.svn/
+Ecore.h
+Ecore_Data.h
+Ecore_Getopt.h
+Ecore_Str.h
+ecore_private.h
+ecore.c
+ecore_anim.c
+ecore_app.c
+ecore_events.c
+ecore_exe.c
+ecore_getopt.c
+ecore_hash.c
+ecore_idle_enterer.c
+ecore_idle_exiter.c
+ecore_idler.c
+ecore_list.c
+ecore_main.c
+ecore_path.c
+ecore_pipe.c
+ecore_plugin.c
+ecore_poll.c
+ecore_sheap.c
+ecore_signal.c
+ecore_str.c
+ecore_strbuf.c
+ecore_strings.c
+ecore_thread.c
+ecore_time.c
+ecore_timer.c
+ecore_tree.c
+ecore_value.c
+.cvsignore
+Makefile.am
+.Ecore.h.swp
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
@@ -273,7 +316,13 @@
* Create two file descriptors (sockets on Windows). Add
* a callback that will be called when the file descriptor that
* is listened receives data. An event is also put in the event
- * queue when data is received.
+ * queue when data is received. <br>
+ * If handler is null, no handler will be set and the function
+ * ecore_pipe_read() can be used to read the pipe. In this case
+ * the read operation is block until there is something to read.
+ * This configuration can be used to send information from the
+ * main loop to a thread. As the read operation block, the thread
+ * will be in pause until the main loop send a data.
*
* @param handler The handler called when data is received.
* @param data Data to pass to @p handler when it is called.
@@ -288,8 +337,6 @@
Ecore_Pipe *p;
int fds[2];
- if (!handler) return NULL;
-
p = (Ecore_Pipe *)calloc(1, sizeof(Ecore_Pipe));
if (!p) return NULL;
@@ -306,13 +353,15 @@
p->data = data;
#ifndef _WIN32
- fcntl(p->fd_read, F_SETFL, O_NONBLOCK);
+ if(handler)
+ fcntl(p->fd_read, F_SETFL, O_NONBLOCK);
#endif /* _WIN32 */
- p->fd_handler = ecore_main_fd_handler_add(p->fd_read,
- ECORE_FD_READ,
- _ecore_pipe_read,
- p,
- NULL, NULL);
+ if(handler)
+ p->fd_handler = ecore_main_fd_handler_add(p->fd_read,
+ ECORE_FD_READ,
+ _ecore_pipe_read,
+ p,
+ NULL, NULL);
return p;
}
@@ -445,7 +494,7 @@
ret = pipe_write(p->fd_write,
((unsigned char *)buffer) + already_written,
nbytes - already_written);
-
+
if (ret == (ssize_t)(nbytes - already_written))
return TRUE;
else if (ret >= 0)
@@ -474,9 +523,104 @@
return FALSE;
}
+/**
+ * Read the data from the file descriptor. The operation block
+ * until a data is received.
+ *
+ * @param p The Ecore_Pipe object.
+ * @param buffer The data read from the pipe.
+ * @param nbytes The size of the @p buffer in bytes.
+ * @return Returns the size of the data read
+ * @ingroup Ecore_Pipe_Group
+ */
+EAPI int
+ecore_pipe_read(Ecore_Pipe *p, void *buffer, unsigned int nbytes)
+{
+ ssize_t ret = 0, already_read = 0;
+ int retry = ECORE_PIPE_WRITE_RETRY;
+ unsigned int len = 0;
+
+ if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
+ {
+ ECORE_MAGIC_FAIL(p, ECORE_MAGIC_PIPE, "ecore_pipe_read");
+ return FALSE;
+ }
+
+ if (p->fd_read == PIPE_FD_INVALID) return FALSE;
+
+ do
+ {
+ /* read the len of the passed data */
+ ret = pipe_read(p->fd_read, ((char*)&len)+already_read,
sizeof(len)-already_read);
+
+ /* catch the non error case first */
+ if (ret > 0)
+ already_read += ret;
+ else if (ret == 0)
+ {
+ pipe_close(p->fd_read);
+ p->fd_read = PIPE_FD_INVALID;
+ return FALSE;
+ }
+ else if ((ret == PIPE_FD_ERROR) && ((errno == EINTR) || (errno ==
EAGAIN)))
+ ;
+ else
+ {
+ fprintf(stderr, "An unhandled error (ret: %d errno: %d)"
+ "occured while reading from the pipe the length\n",
+ ret, errno);
+ return FALSE;
+ }
+ } while (already_read < sizeof(len));
+
+ if(!retry)
+ return FALSE;
+
+ already_read = 0;
+ do
+ {
+ if(nbytes<len)
+ {
+ fprintf(stderr, "The data (%d) is longer than the buffer (%d)\n",
len, nbytes);
+ return FALSE;
+ }
+
+ /* and read the passed data */
+ ret = pipe_read(p->fd_read,
+ ((unsigned char *)buffer)+already_read,
+ len - already_read);
+
+ /* catch the non error case first */
+ if (ret == (ssize_t)(len - already_read))
+ {
+ return len;
+ }
+ else if (ret >= 0)
+ {
+ p->already_read += ret;
+ }
+ else if (ret == 0)
+ {
+ return FALSE;
+ }
+ else if (ret == PIPE_FD_ERROR && (errno == EINTR || errno == EAGAIN))
+ ;
+ else
+ {
+ fprintf(stderr, "An unhandled error (ret: %d errno: %d)"
+ "occured while reading from the pipe the data\n",
+ ret, errno);
+ return FALSE;
+ }
+ }
+ while(1);
+
+ return FALSE;
+}
+
/* Private function */
-static int
+ static int
_ecore_pipe_read(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
{
Ecore_Pipe *p;
@@ -532,7 +676,7 @@
ret = pipe_read(p->fd_read,
((unsigned char *)p->passed_data) + p->already_read,
p->len - p->already_read);
-
+
/* catch the non error case first */
if (ret == (ssize_t)(p->len - p->already_read))
{
@@ -567,6 +711,6 @@
}
}
while (ecore_time_get() - start_time < ecore_animator_frametime_get());
-
+
return ECORE_CALLBACK_RENEW;
}
Index: Ecore.h
===================================================================
--- Ecore.h (revision 42487)
+++ Ecore.h (working copy)
@@ -85,7 +85,7 @@
#define ECORE_EVENT_COUNT 6
#define ECORE_EXE_PRIORITY_INHERIT 9999
-
+
EAPI extern int ECORE_EXE_EVENT_ADD; /**< A child process has been added */
EAPI extern int ECORE_EXE_EVENT_DEL; /**< A child process has been deleted
(it exited, naming consistant with the rest of ecore). */
EAPI extern int ECORE_EXE_EVENT_DATA; /**< Data from a child process. */
@@ -299,6 +299,7 @@
EAPI Ecore_Pipe *ecore_pipe_add(void (*handler) (void *data, void *buffer,
unsigned int nbyte), const void *data);
EAPI void *ecore_pipe_del(Ecore_Pipe *p);
EAPI int ecore_pipe_write(Ecore_Pipe *p, const void *buffer,
unsigned int nbytes);
+ EAPI int ecore_pipe_read(Ecore_Pipe *p, void *buffer, unsigned int
nbytes);
EAPI void ecore_pipe_write_close(Ecore_Pipe *p);
EAPI void ecore_pipe_read_close(Ecore_Pipe *p);
------------------------------------------------------------------------------
Come build with us! The BlackBerry® Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9-12, 2009. Register now!
http://p.sf.net/sfu/devconf
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel