forked from enlightenment/efl
ecore: fix ecore main loop on Windows when number of objects is greater that MAXIMUM_WAIT_OBJECTS
@fix Signed-off-by: Cedric BAIL <c.bail@partner.samsung.com>
This commit is contained in:
parent
113d794973
commit
ed2987eb69
|
@ -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,7 +2322,7 @@ _ecore_main_win32_select(int nfds EINA_UNUSED,
|
|||
}
|
||||
else if (result == WAIT_TIMEOUT)
|
||||
{
|
||||
/* ERR("time out\n"); */
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue