

This is a very simple example where we will start monitoring the stdin of the program and, whenever there\textquotesingle{}s something to be read, we call our callback that will read it.

Check the full code for this example \mbox{\hyperlink{ecore_fd_handler_example_8c-example}{here}}.

This seems to be stupid, since a similar result could be achieved by the following code\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{\textcolor{keywordflow}{while} (nbytes = read(STDIN\_FILENO, buf, \textcolor{keyword}{sizeof}(buf)))}
\DoxyCodeLine{  \{}
\DoxyCodeLine{     buf[nbytes -\/ 1] = \textcolor{charliteral}{'\(\backslash\)0'};}
\DoxyCodeLine{     printf(\textcolor{stringliteral}{"Read \%zd bytes from input: \(\backslash\)"\%s\(\backslash\)"\(\backslash\)n"}, nbytes -\/ 1, buf);}
\DoxyCodeLine{  \}}
\end{DoxyCode}


However, the above code is blocking, and won\textquotesingle{}t allow you to do anything else other than reading the input. Of course there are other methods to do a non-\/blocking reading, like setting the file descriptor to non-\/blocking and keep looping always checking if there\textquotesingle{}s something to be read, and do other things otherwise. Or use a {\ttfamily select} call to watch for more than one file descriptor at the same time.

The advantage of using an \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ga225121ed2123da4b52b76aa08d78c220}{Ecore\+\_\+\+Fd\+\_\+\+Handler}} is that you can monitor a file descriptor, while still iterating on the Ecore main loop. It will allow you to have timers working and expiring, events still being processed when received, idlers doing its work when there\textquotesingle{}s nothing happening, and whenever there\textquotesingle{}s something to be read from the file descriptor, your callback will be called. And it\textquotesingle{}s everything monitored in the same main loop, no threads are needed, thus reducing the complexity of the program and any overhead caused by the use of threads.

Now let\textquotesingle{}s start our program. First we just declare a context structure that will be passed to our callback, with pointers to our handler and to a timer that will be used later\+:


\begin{DoxyCodeInclude}{0}
\DoxyCodeLine{\textcolor{comment}{/*}}
\DoxyCodeLine{\textcolor{comment}{ * gcc -\/o ecore\_fd\_handler\_example ecore\_fd\_handler\_example.c `pkg-\/config -\/-\/cflags -\/-\/libs ecore`}}
\DoxyCodeLine{\textcolor{comment}{ */}}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{preprocessor}{\#include <Ecore.h>}}
\DoxyCodeLine{\textcolor{preprocessor}{\#include <unistd.h>}}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keyword}{struct }context}
\DoxyCodeLine{\{}
\DoxyCodeLine{   \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ga225121ed2123da4b52b76aa08d78c220}{Ecore\_Fd\_Handler}} *handler;}
\DoxyCodeLine{   \mbox{\hyperlink{group__Ecore__Timer__Group_gaf96ffb609956658ec038e54bd39f46f0}{Ecore\_Timer}}      *timer;}
\DoxyCodeLine{\};}

\end{DoxyCodeInclude}


Then we will declare a prepare\+\_\+callback that is called before any fd\+\_\+handler set in the program, and before the main loop select function is called. Just use one if you really know that you need it. We are just putting it here to exemplify its usage\+:


\begin{DoxyCodeInclude}{0}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keyword}{static} \textcolor{keywordtype}{void}}
\DoxyCodeLine{\_fd\_prepare\_cb(\textcolor{keywordtype}{void} *data \mbox{\hyperlink{group__Eina__Types__Group_ga82d751be730f849719ca292f9558be87}{EINA\_UNUSED}}, \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ga225121ed2123da4b52b76aa08d78c220}{Ecore\_Fd\_Handler}} *handler \mbox{\hyperlink{group__Eina__Types__Group_ga82d751be730f849719ca292f9558be87}{EINA\_UNUSED}})}
\DoxyCodeLine{\{}
\DoxyCodeLine{   printf(\textcolor{stringliteral}{"prepare\_cb called.\(\backslash\)n"});}
\DoxyCodeLine{\}}

\end{DoxyCodeInclude}


Now, our fd handler. In its arguments, the {\ttfamily data} pointer will have any data passed to it when it was registered, and the {\ttfamily handler} pointer will contain the fd handler returned by the \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ga832e68eb7f15912abeadef816bb5d2f5}{ecore\+\_\+main\+\_\+fd\+\_\+handler\+\_\+add()}} call. It can be used, for example, to retrieve which file descriptor triggered this callback, since it could be added to more than one file descriptor, or to check what type of activity there\textquotesingle{}s in the file descriptor.

The code is very simple\+: we first check if the type of activity was an error. It probably won\textquotesingle{}t happen with the default input, but could be the case of a network socket detecting a disconnection. Next, we get the file descriptor from this handler (as said before, the callback could be added to more than one file descriptor), and read it since we know that it shouldn\textquotesingle{}t block, because our fd handler told us that there\textquotesingle{}s some activity on it. If the result of the read was 0 bytes, we know that it\textquotesingle{}s an end of file (E\+OF), so we can finish reading the input. Otherwise we just print the content read from it\+:


\begin{DoxyCodeInclude}{0}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keyword}{static} \mbox{\hyperlink{group__Eina__Types__Group_ga3fe0caf72e93b1bab1ca8ee3ccf3f226}{Eina\_Bool}}}
\DoxyCodeLine{\_fd\_handler\_cb(\textcolor{keywordtype}{void} *data, \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ga225121ed2123da4b52b76aa08d78c220}{Ecore\_Fd\_Handler}} *handler)}
\DoxyCodeLine{\{}
\DoxyCodeLine{   \textcolor{keyword}{struct }context *ctxt = data;}
\DoxyCodeLine{   \textcolor{keywordtype}{char} buf[1024];}
\DoxyCodeLine{   \textcolor{keywordtype}{size\_t} nbytes;}
\DoxyCodeLine{   \textcolor{keywordtype}{int} fd;}
\DoxyCodeLine{}
\DoxyCodeLine{   \textcolor{keywordflow}{if} (\mbox{\hyperlink{group__Ecore__FD__Handler__Group_gabd3040bd39c95723e42a8c48484b87de}{ecore\_main\_fd\_handler\_active\_get}}(handler, \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ggab5644f471dfa3bd182619601d9b60608a829d91235e3ca5eba61330c96a8074de}{ECORE\_FD\_ERROR}}))}
\DoxyCodeLine{     \{}
\DoxyCodeLine{        printf(\textcolor{stringliteral}{"An error has occurred. Stop watching this fd and quit.\(\backslash\)n"});}
\DoxyCodeLine{        \mbox{\hyperlink{group__Ecore__Main__Loop__Group_ga95cf8e97dff0716433c2c5474d606a98}{ecore\_main\_loop\_quit}}();}
\DoxyCodeLine{        ctxt-\/>handler = NULL;}
\DoxyCodeLine{        \textcolor{keywordflow}{return} \mbox{\hyperlink{group__Ecore__Main__Loop__Group_gae0c653baad8836232c0dc27f91f875d6}{ECORE\_CALLBACK\_CANCEL}};}
\DoxyCodeLine{     \}}

\end{DoxyCodeInclude}


Also notice that this callback returns \mbox{\hyperlink{group__Ecore__Main__Loop__Group_ga1ee9db07f9a46a8b20fb83e1c6dbed09}{E\+C\+O\+R\+E\+\_\+\+C\+A\+L\+L\+B\+A\+C\+K\+\_\+\+R\+E\+N\+EW}} to keep being called, as almost all other Ecore callbacks, otherwise if it returns \mbox{\hyperlink{group__Ecore__Main__Loop__Group_gae0c653baad8836232c0dc27f91f875d6}{E\+C\+O\+R\+E\+\_\+\+C\+A\+L\+L\+B\+A\+C\+K\+\_\+\+C\+A\+N\+C\+EL}} then the file handler would be deleted.

Just to demonstrate that our program isn\textquotesingle{}t blocking in the input read but still can process other Ecore events, we are going to setup an \mbox{\hyperlink{group__Ecore__Timer__Group_gaf96ffb609956658ec038e54bd39f46f0}{Ecore\+\_\+\+Timer}}. This is its callback\+:


\begin{DoxyCodeInclude}{0}
\DoxyCodeLine{}
\DoxyCodeLine{   fd = \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ga70d418717552a5258c7dfc1153250e7d}{ecore\_main\_fd\_handler\_fd\_get}}(handler);}
\DoxyCodeLine{   nbytes = read(fd, buf, \textcolor{keyword}{sizeof}(buf));}
\DoxyCodeLine{   \textcolor{keywordflow}{if} (nbytes == 0)}
\DoxyCodeLine{     \{}
\DoxyCodeLine{        printf(\textcolor{stringliteral}{"Nothing to read, exiting...\(\backslash\)n"});}
\DoxyCodeLine{        \mbox{\hyperlink{group__Ecore__Main__Loop__Group_ga95cf8e97dff0716433c2c5474d606a98}{ecore\_main\_loop\_quit}}();}
\DoxyCodeLine{        ctxt-\/>handler = NULL;}
\DoxyCodeLine{        \textcolor{keywordflow}{return} \mbox{\hyperlink{group__Ecore__Main__Loop__Group_gae0c653baad8836232c0dc27f91f875d6}{ECORE\_CALLBACK\_CANCEL}};}
\DoxyCodeLine{     \}}

\end{DoxyCodeInclude}


Now in the main code we are going to initialize the library, and setup callbacks for the file descriptor, the prepare callback, and the timer\+:


\begin{DoxyCodeInclude}{0}
\DoxyCodeLine{   buf[nbytes -\/ 1] = \textcolor{charliteral}{'\(\backslash\)0'};}
\DoxyCodeLine{}
\DoxyCodeLine{   printf(\textcolor{stringliteral}{"Read \%zd bytes from input: \(\backslash\)"\%s\(\backslash\)"\(\backslash\)n"}, nbytes -\/ 1, buf);}
\DoxyCodeLine{}
\DoxyCodeLine{   \textcolor{keywordflow}{return} \mbox{\hyperlink{group__Ecore__Main__Loop__Group_ga1ee9db07f9a46a8b20fb83e1c6dbed09}{ECORE\_CALLBACK\_RENEW}};}
\DoxyCodeLine{\}}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keyword}{static} \mbox{\hyperlink{group__Eina__Types__Group_ga3fe0caf72e93b1bab1ca8ee3ccf3f226}{Eina\_Bool}}}
\DoxyCodeLine{\_timer\_cb(\textcolor{keywordtype}{void} *data \mbox{\hyperlink{group__Eina__Types__Group_ga82d751be730f849719ca292f9558be87}{EINA\_UNUSED}})}
\DoxyCodeLine{\{}
\DoxyCodeLine{   printf(\textcolor{stringliteral}{"Timer expired after 5 seconds...\(\backslash\)n"});}
\DoxyCodeLine{}
\DoxyCodeLine{   \textcolor{keywordflow}{return} \mbox{\hyperlink{group__Ecore__Main__Loop__Group_ga1ee9db07f9a46a8b20fb83e1c6dbed09}{ECORE\_CALLBACK\_RENEW}};}
\DoxyCodeLine{\}}
\DoxyCodeLine{}
\DoxyCodeLine{\textcolor{keywordtype}{int}}
\DoxyCodeLine{main(\textcolor{keywordtype}{void})}
\DoxyCodeLine{\{}
\DoxyCodeLine{   \textcolor{keyword}{struct }context ctxt = \{0\};}
\DoxyCodeLine{}
\DoxyCodeLine{   \textcolor{keywordflow}{if} (!\mbox{\hyperlink{group__Ecore__Init__Group_ga77757609684a2c922dc5ec398274751b}{ecore\_init}}())}
\DoxyCodeLine{     \{}
\DoxyCodeLine{        printf(\textcolor{stringliteral}{"ERROR: Cannot init Ecore!\(\backslash\)n"});}
\DoxyCodeLine{        \textcolor{keywordflow}{return} -\/1;}
\DoxyCodeLine{     \}}
\DoxyCodeLine{}
\DoxyCodeLine{   ctxt.handler = \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ga832e68eb7f15912abeadef816bb5d2f5}{ecore\_main\_fd\_handler\_add}}(STDIN\_FILENO,}
\DoxyCodeLine{                                            \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ggab5644f471dfa3bd182619601d9b60608a1699f804eccf88e7e169a4a20f1d44e7}{ECORE\_FD\_READ}} | \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ggab5644f471dfa3bd182619601d9b60608a829d91235e3ca5eba61330c96a8074de}{ECORE\_FD\_ERROR}},}
\DoxyCodeLine{                                            \_fd\_handler\_cb,}
\DoxyCodeLine{                                            \&ctxt, NULL, NULL);}
\DoxyCodeLine{   \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ga072d1719e94e56639abcd385f7cbc692}{ecore\_main\_fd\_handler\_prepare\_callback\_set}}(ctxt.handler, \_fd\_prepare\_cb, \&ctxt);}
\DoxyCodeLine{   ctxt.timer = \mbox{\hyperlink{group__Ecore__Timer__Group_ga7b9cb9d24ecebfdbb957436e2e669402}{ecore\_timer\_add}}(5, \_timer\_cb, \&ctxt);}

\end{DoxyCodeInclude}


Notice that the use of \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ga832e68eb7f15912abeadef816bb5d2f5}{ecore\+\_\+main\+\_\+fd\+\_\+handler\+\_\+add()}} specifies what kind of activity we are monitoring. In this case, we want to monitor for read (since it\textquotesingle{}s the standard input) and for errors. This is done by the flags \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ggab5644f471dfa3bd182619601d9b60608a1699f804eccf88e7e169a4a20f1d44e7}{E\+C\+O\+R\+E\+\_\+\+F\+D\+\_\+\+R\+E\+AD}} and \mbox{\hyperlink{group__Ecore__FD__Handler__Group_ggab5644f471dfa3bd182619601d9b60608a829d91235e3ca5eba61330c96a8074de}{E\+C\+O\+R\+E\+\_\+\+F\+D\+\_\+\+E\+R\+R\+OR}}. For the three callbacks we are also giving a pointer to our context structure, which has pointers to the handlers added.

Then we can start the main loop and see everything happening\+:


\begin{DoxyCodeInclude}{0}
\DoxyCodeLine{}
\DoxyCodeLine{   printf(\textcolor{stringliteral}{"Starting the main loop. Type anything and hit <enter> to "}}
\DoxyCodeLine{          \textcolor{stringliteral}{"activate the fd\_handler callback, or CTRL+d to shutdown.\(\backslash\)n"});}
\DoxyCodeLine{}
\DoxyCodeLine{   \mbox{\hyperlink{group__Ecore__Main__Loop__Group_gaf103b9f668bb3e4fed12e52c6180132d}{ecore\_main\_loop\_begin}}();}
\DoxyCodeLine{}
\DoxyCodeLine{   \textcolor{keywordflow}{if} (ctxt.handler)}
\DoxyCodeLine{     \mbox{\hyperlink{group__Ecore__FD__Handler__Group_gaf92ef3a4a006a02e67b9806276f7312c}{ecore\_main\_fd\_handler\_del}}(ctxt.handler);}
\DoxyCodeLine{}
\DoxyCodeLine{   \textcolor{keywordflow}{if} (ctxt.timer)}
\DoxyCodeLine{     \mbox{\hyperlink{group__Ecore__Timer__Group_gaba2b599c7aabe3ab664dc3d47f62a33a}{ecore\_timer\_del}}(ctxt.timer);}
\DoxyCodeLine{}
\DoxyCodeLine{   \mbox{\hyperlink{group__Ecore__Init__Group_ga768298b932f18d7e7593a447493e5cde}{ecore\_shutdown}}();}
\DoxyCodeLine{}
\DoxyCodeLine{   \textcolor{keywordflow}{return} 0;}
\DoxyCodeLine{\}}

\end{DoxyCodeInclude}


In the end we are just deleting the fd handler and the timer to demonstrate the A\+PI usage, since Ecore would already do it for us on its shutdown. 