move around - flatter.
[profile/ivi/evas.git] / src / lib / canvas / evas_async_events.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3
4 #ifdef BUILD_ASYNC_EVENTS
5
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <pthread.h>
9 #include <errno.h>
10
11 static int _fd_write = -1;
12 static int _fd_read = -1;
13
14 static int _init_evas_event = 0;
15 static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
16
17 typedef struct _Evas_Event_Async        Evas_Event_Async;
18 struct _Evas_Event_Async
19 {
20    void                 (*func)(void *target, Evas_Callback_Type type, void *event_info);
21    void                  *target;
22    Evas_Callback_Type     type;
23    void                  *event_info;
24 };
25
26 #endif
27
28 int
29 evas_async_events_init(void)
30 {
31 #ifdef BUILD_ASYNC_EVENTS
32    int filedes[2];
33
34    _init_evas_event++;
35    if (_init_evas_event > 1) return _init_evas_event;
36
37    if (pipe(filedes) == -1)
38      {
39         _init_evas_event = 0;
40         return 0;
41      }
42
43    _fd_read = filedes[0];
44    _fd_write = filedes[1];
45
46    fcntl(_fd_read, F_SETFL, O_NONBLOCK);
47
48    return _init_evas_event;
49 #else
50    return 0;
51 #endif
52 }
53
54 int
55 evas_async_events_shutdown(void)
56 {
57 #ifdef BUILD_ASYNC_EVENTS
58    _init_evas_event--;
59    if (_init_evas_event > 0) return _init_evas_event;
60
61    close(_fd_read);
62    close(_fd_write);
63    _fd_read = -1;
64    _fd_write = -1;
65
66    return _init_evas_event;
67 #else
68    return 0;
69 #endif
70 }
71
72 EAPI int
73 evas_async_events_fd_get(void)
74 {
75 #ifdef BUILD_ASYNC_EVENTS
76    return _fd_read;
77 #else
78    return -1;
79 #endif
80 }
81
82 EAPI int
83 evas_async_events_process(void)
84 {
85 #ifdef BUILD_ASYNC_EVENTS
86    static Evas_Event_Async current;
87    static int size = 0;
88    int check;
89    int count = 0;
90
91    if (_fd_read == -1) return 0;
92
93    do
94      {
95         check = read(_fd_read, ((char*) &current) + size, sizeof(current) - size);
96
97         if (check > 0)
98           {
99              size += check;
100              if (size == sizeof(current))
101                {
102                   if (current.func) current.func(current.target, current.type, current.event_info);
103                   size = 0;
104                   count++;
105                }
106           }
107      }
108    while (check > 0);
109
110    if (check < 0)
111      switch (errno)
112        {
113         case EBADF:
114         case EINVAL:
115         case EIO:
116         case EISDIR:
117            _fd_read = -1;
118        }
119
120    return count;
121 #else
122    return 0;
123 #endif
124 }
125
126 EAPI Evas_Bool
127 evas_async_events_put(void *target, Evas_Callback_Type type, void *event_info, void (*func)(void *target, Evas_Callback_Type type, void *event_info))
128 {
129 #ifdef BUILD_ASYNC_EVENTS
130    Evas_Event_Async new;
131    ssize_t check;
132    int  offset = 0;
133    Evas_Bool result = 0;
134
135    if (!func) return 0;
136    if (_fd_write == -1) return 0;
137
138    new.func = func;
139    new.target = target;
140    new.type = type;
141    new.event_info = event_info;
142
143    pthread_mutex_lock(&_mutex);
144
145    do {
146       check = write(_fd_write, ((char*)&new) + offset, sizeof(new) - offset);
147       offset += check;
148    } while (offset != sizeof(new) && (errno == EINTR || errno == EAGAIN));
149
150    if (offset == sizeof(new))
151      result = 1;
152    else
153      switch (errno)
154        {
155         case EBADF:
156         case EINVAL:
157         case EIO:
158         case EPIPE:
159            _fd_write = -1;
160        }
161
162    pthread_mutex_unlock(&_mutex);
163
164    return result;
165 #else
166    return 0;
167 #endif
168 }
169