cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=ed2987eb69f7668c7e5e17cada47470ef40314b1

commit ed2987eb69f7668c7e5e17cada47470ef40314b1
Author: Vincent Torri <vincent.to...@gmail.com>
Date:   Sun Jun 22 17:33:34 2014 +0200

    ecore: fix ecore main loop on Windows when number of objects is greater 
that MAXIMUM_WAIT_OBJECTS
    
    @fix
    
    Signed-off-by: Cedric BAIL <c.b...@partner.samsung.com>
---
 src/lib/ecore/ecore_main.c | 194 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 185 insertions(+), 9 deletions(-)

diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c
index 46a07c6..5278116 100644
--- a/src/lib/ecore/ecore_main.c
+++ b/src/lib/ecore/ecore_main.c
@@ -2048,6 +2048,163 @@ done: 
/*******************************************************************/
 #endif
 
 #ifdef _WIN32
+typedef struct
+{
+   DWORD objects_nbr;
+   HANDLE *objects;
+   DWORD timeout;
+} Ecore_Main_Win32_Thread_Data;
+
+static unsigned int __stdcall
+_ecore_main_win32_objects_wait_thread(void *data)
+{
+   Ecore_Main_Win32_Thread_Data *td;
+   DWORD result;
+
+   td = (Ecore_Main_Win32_Thread_Data *)data;
+   result = MsgWaitForMultipleObjects(td->objects_nbr,
+                                      (const HANDLE *)td->objects,
+                                      FALSE,
+                                      td->timeout,
+                                      QS_ALLINPUT);
+   return result;
+}
+
+static DWORD
+_ecore_main_win32_objects_wait(DWORD objects_nbr,
+                               const HANDLE *objects,
+                               DWORD timeout)
+{
+   Ecore_Main_Win32_Thread_Data *threads_data;
+   HANDLE *threads_handles;
+   DWORD threads_nbr;
+   DWORD threads_remain;
+   DWORD objects_idx;
+   DWORD result;
+   DWORD i;
+
+   if (objects_nbr < MAXIMUM_WAIT_OBJECTS)
+     return MsgWaitForMultipleObjects(objects_nbr,
+                                      objects,
+                                      EINA_FALSE,
+                                      timeout, QS_ALLINPUT);
+   /*
+    * too much objects, so we launch a bunch of threads to
+    * wait for, each one calls MsgWaitForMultipleObjects
+    */
+
+   threads_nbr = objects_nbr / (MAXIMUM_WAIT_OBJECTS - 1);
+   threads_remain = objects_nbr % (MAXIMUM_WAIT_OBJECTS - 1);
+   if (threads_remain > 0)
+     threads_nbr++;
+
+   if (threads_nbr > MAXIMUM_WAIT_OBJECTS)
+     {
+        CRI("Too much objects to wait for (%lu).", objects_nbr);
+        return WAIT_FAILED;
+     }
+
+   threads_handles = (HANDLE *)malloc(threads_nbr * sizeof(HANDLE));
+   if (!threads_handles)
+     {
+        ERR("Can not allocate memory for the waiting thread.");
+        return WAIT_FAILED;
+     }
+
+   threads_data = (Ecore_Main_Win32_Thread_Data *)malloc(threads_nbr * 
sizeof(Ecore_Main_Win32_Thread_Data));
+   if (!threads_data)
+     {
+        ERR("Can not allocate memory for the waiting thread.");
+        goto free_threads_handles;
+     }
+
+   objects_idx = 0;
+   for (i = 0; i < threads_nbr; i++)
+     {
+        threads_data[i].timeout = timeout;
+        threads_data[i].objects = (HANDLE *)objects + objects_idx;
+
+        if ((i == (threads_nbr - 1)) && (threads_remain != 0))
+          {
+             threads_data[i].objects_nbr = threads_remain;
+             objects_idx += threads_remain;
+          }
+        else
+          {
+             threads_data[i].objects_nbr = (MAXIMUM_WAIT_OBJECTS - 1);
+             objects_idx += (MAXIMUM_WAIT_OBJECTS - 1);
+          }
+
+        threads_handles[i] = (HANDLE)_beginthreadex(NULL,
+                                                    0,
+                                                    
_ecore_main_win32_objects_wait_thread,
+                                                    &threads_data[i],
+                                                    0,
+                                                    NULL);
+        if (!threads_handles[i])
+          {
+             DWORD j;
+
+             ERR("Can not create the waiting threads.");
+             WaitForMultipleObjects(i, threads_handles, TRUE, INFINITE);
+             for (j = 0; j < i; j++)
+               CloseHandle(threads_handles[i]);
+
+             goto free_threads_data;
+          }
+     }
+
+   result = WaitForMultipleObjects(threads_nbr,
+                                   threads_handles,
+                                   FALSE, /* we wait until one thread is 
signaled */
+                                   INFINITE);
+
+   if (result < (WAIT_OBJECT_0 + threads_nbr))
+     {
+        DWORD wait_res;
+
+        /*
+         * One of the thread callback has exited so we retrieve
+         * its exit status, that is the returned value of
+         * MsgWaitForMultipleObjects()
+         */
+        if (GetExitCodeThread(threads_handles[result - WAIT_OBJECT_0],
+                              &wait_res))
+          {
+             WaitForMultipleObjects(threads_nbr, threads_handles, TRUE, 
INFINITE);
+             for (i = 0; i < threads_nbr; i++)
+               CloseHandle(threads_handles[i]);
+             free(threads_data);
+             free(threads_handles);
+             return wait_res;
+          }
+     }
+   else
+     {
+        ERR("Error when waiting threads.");
+        if (result == WAIT_FAILED)
+          {
+             char *str;
+
+             str = evil_last_error_get();
+             ERR("%s", str);
+             free(str);
+          }
+        goto close_thread;
+     }
+
+ close_thread:
+   WaitForMultipleObjects(threads_nbr, threads_handles, TRUE, INFINITE);
+   for (i = 0; i < threads_nbr; i++)
+     CloseHandle(threads_handles[i]);
+ free_threads_data:
+   free(threads_data);
+ free_threads_handles:
+   free(threads_handles);
+
+   return WAIT_FAILED;
+}
+
 static int
 _ecore_main_win32_select(int             nfds EINA_UNUSED,
                          fd_set         *readfds,
@@ -2055,12 +2212,12 @@ _ecore_main_win32_select(int             nfds 
EINA_UNUSED,
                          fd_set         *exceptfds,
                          struct timeval *tv)
 {
-   HANDLE objects[MAXIMUM_WAIT_OBJECTS];
-   int sockets[MAXIMUM_WAIT_OBJECTS];
+   HANDLE *objects;
+   int *sockets;
    Ecore_Fd_Handler *fdh;
    Ecore_Win32_Handler *wh;
+   unsigned int fds_nbr = 0;
    unsigned int objects_nbr = 0;
-   unsigned int handles_nbr = 0;
    unsigned int events_nbr = 0;
    DWORD result;
    DWORD timeout;
@@ -2068,6 +2225,18 @@ _ecore_main_win32_select(int             nfds 
EINA_UNUSED,
    unsigned int i;
    int res;
 
+   fds_nbr = eina_inlist_count(EINA_INLIST_GET(fd_handlers));
+   sockets = (int *)malloc(fds_nbr * sizeof(int));
+   if (!sockets)
+     return -1;
+
+   objects = (HANDLE)malloc((fds_nbr + 
eina_inlist_count(EINA_INLIST_GET(win32_handlers))) * sizeof(HANDLE));
+   if (!objects)
+     {
+        free(sockets);
+        return -1;
+     }
+
    /* Create an event object per socket */
    EINA_INLIST_FOREACH(fd_handlers, fdh)
      {
@@ -2106,7 +2275,6 @@ _ecore_main_win32_select(int             nfds EINA_UNUSED,
    EINA_INLIST_FOREACH(win32_handlers, wh)
      {
         objects[objects_nbr] = wh->h;
-        handles_nbr++;
         objects_nbr++;
      }
 
@@ -2124,10 +2292,16 @@ _ecore_main_win32_select(int             nfds 
EINA_UNUSED,
    else
      timeout = (DWORD)((tv->tv_sec * 1000.0) + (tv->tv_usec / 1000.0));
 
-   if (timeout == 0) return 0;
+   if (timeout == 0)
+     {
+        free(objects);
+        free(sockets);
+        return 0;
+     }
 
-   result = MsgWaitForMultipleObjects(objects_nbr, (const HANDLE *)objects, 
EINA_FALSE,
-                                      timeout, QS_ALLINPUT);
+   result = _ecore_main_win32_objects_wait(objects_nbr,
+                                           (const HANDLE *)objects,
+                                           timeout);
 
    if (readfds)
      FD_ZERO(readfds);
@@ -2148,8 +2322,8 @@ _ecore_main_win32_select(int             nfds EINA_UNUSED,
      }
    else if (result == WAIT_TIMEOUT)
      {
-        /* ERR("time out\n"); */
-         res = 0;
+        INF("time-out interval elapsed.");
+        res = 0;
      }
    else if (result == (WAIT_OBJECT_0 + objects_nbr))
      {
@@ -2221,6 +2395,8 @@ _ecore_main_win32_select(int             nfds EINA_UNUSED,
    /* Remove event objects again */
    for (i = 0; i < events_nbr; i++) WSACloseEvent(objects[i]);
 
+   free(objects);
+   free(sockets);
    return res;
 }
 

-- 


Reply via email to