summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2016-07-12 22:26:23 +0800
committerruki <[email protected]>2016-07-12 22:26:23 +0800
commit0f7173fe7610408d1f947517e48447a4b0fd4461 (patch)
tree836124606b169f00b04343f407d5486a42208f8a
parent2df6235f8b2b3c88c94676720c2e4076b2d0d9d9 (diff)
add process.waitlist interfaces
-rwxr-xr-xcore/pkg/tbox.pkg/inc/mac/x64/tbox.config.h4
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/platform/process.h75
-rwxr-xr-xcore/pkg/tbox.pkg/inc/tbox/platform/windows/interface/kernel32.h6
-rw-r--r--core/pkg/tbox.pkg/inc/tbox/tbox.config.h115
-rwxr-xr-xcore/src/xmake/machine.c2
-rwxr-xr-xcore/src/xmake/makefile1
-rwxr-xr-xcore/src/xmake/process/wait.c7
-rwxr-xr-xcore/src/xmake/process/waitlist.c143
8 files changed, 351 insertions, 2 deletions
diff --git a/core/pkg/tbox.pkg/inc/mac/x64/tbox.config.h b/core/pkg/tbox.pkg/inc/mac/x64/tbox.config.h
index ea46a2e3c..a330a7f95 100755
--- a/core/pkg/tbox.pkg/inc/mac/x64/tbox.config.h
+++ b/core/pkg/tbox.pkg/inc/mac/x64/tbox.config.h
@@ -6,10 +6,12 @@
#define TB_CONFIG_VERSION_MAJOR 1
#define TB_CONFIG_VERSION_MINOR 5
#define TB_CONFIG_VERSION_ALTER 3
-#define TB_CONFIG_VERSION_BUILD 201607031524
+#define TB_CONFIG_VERSION_BUILD 201607122000
// defines
#define TB_CONFIG_OS_MACOSX 1
+#define _GNU_SOURCE 1
+#define _REENTRANT 1
#define TB_CONFIG_SMALL 1
#define TB_CONFIG_TYPE_HAVE_FLOAT 1
#define TB_CONFIG_POSIX_HAVE_POSIX_SPAWNP 1
diff --git a/core/pkg/tbox.pkg/inc/tbox/platform/process.h b/core/pkg/tbox.pkg/inc/tbox/platform/process.h
index dab5ac300..1c36d1355 100755
--- a/core/pkg/tbox.pkg/inc/tbox/platform/process.h
+++ b/core/pkg/tbox.pkg/inc/tbox/platform/process.h
@@ -102,6 +102,20 @@ typedef struct __tb_process_attr_t
/// the process ref type
typedef struct{}* tb_process_ref_t;
+/// the process wait info type
+typedef struct __tb_process_waitinfo_t
+{
+ // the index of the processes
+ tb_size_t index;
+
+ // the process
+ tb_process_ref_t process;
+
+ // the status
+ tb_long_t status;
+
+}tb_process_waitinfo_t, *tb_process_waitinfo_ref_t;
+
/* //////////////////////////////////////////////////////////////////////////////////////
* interfaces
*/
@@ -250,6 +264,67 @@ tb_void_t tb_process_suspend(tb_process_ref_t process);
*/
tb_long_t tb_process_wait(tb_process_ref_t process, tb_long_t* pstatus, tb_long_t timeout);
+/*! wait the process list
+ *
+ * @code
+
+ // init processes
+ tb_size_t count1 = 0;
+ tb_process_ref_t processes1[5] = {0};
+ tb_process_ref_t processes2[5] = {0};
+ for (; count1 < 4; count1++)
+ {
+ processes1[count1] = tb_process_init(argv[1], (tb_char_t const**)(argv + 1), tb_null);
+ tb_assert_and_check_break(processes1[count1]);
+ }
+
+ // ok?
+ while (count1)
+ {
+ // trace
+ tb_trace_i("waiting: %ld", count1);
+
+ // wait processes
+ tb_long_t infosize = -1;
+ tb_process_waitinfo_t infolist[4] = {{0}};
+ if ((infosize = tb_process_waitlist(processes1, infolist, tb_arrayn(infolist), -1)) > 0)
+ {
+ tb_size_t i = 0;
+ for (i = 0; i < infosize; i++)
+ {
+ // trace
+ tb_trace_i("process(%ld:%p) exited: %ld", infolist[i].index, infolist[i].process, infolist[i].status);
+
+ // exit process
+ if (infolist[i].process) tb_process_exit(infolist[i].process);
+
+ // remove this process
+ processes1[infolist[i].index] = tb_null;
+ }
+
+ // update processes
+ tb_size_t count2 = 0;
+ for (i = 0; i < count1; i++)
+ {
+ if (processes1[i]) processes2[count2++] = processes1[i];
+ }
+ tb_memcpy(processes1, processes2, count2 * sizeof(tb_process_ref_t));
+ processes1[count2] = tb_null;
+ count1 = count2;
+ }
+ }
+
+ * @endcode
+ *
+ * @param processes the null-terminated process list
+ * @param infolist the info list
+ * @param infomaxn the info maxn
+ * @param timeout the timeout (ms), infinity: -1
+ *
+ * @return > 0: the info list size, 0: timeout, -1: failed
+ */
+tb_long_t tb_process_waitlist(tb_process_ref_t const* processes, tb_process_waitinfo_ref_t infolist, tb_size_t infomaxn, tb_long_t timeout);
+
/* //////////////////////////////////////////////////////////////////////////////////////
* extern
*/
diff --git a/core/pkg/tbox.pkg/inc/tbox/platform/windows/interface/kernel32.h b/core/pkg/tbox.pkg/inc/tbox/platform/windows/interface/kernel32.h
index b9f3f3773..a8d32d976 100755
--- a/core/pkg/tbox.pkg/inc/tbox/platform/windows/interface/kernel32.h
+++ b/core/pkg/tbox.pkg/inc/tbox/platform/windows/interface/kernel32.h
@@ -77,6 +77,9 @@ typedef BOOL (WINAPI* tb_kernel32_CloseHandle_t)(HANDLE hObject);
// the WaitForSingleObject func type
typedef DWORD (WINAPI* tb_kernel32_WaitForSingleObject_t)(HANDLE hHandle, DWORD dwMilliseconds);
+// the WaitForMultipleObjects func type
+typedef DWORD (WINAPI* tb_kernel32_WaitForMultipleObjects_t)(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds);
+
// the GetExitCodeProcess func type
typedef BOOL (WINAPI* tb_kernel32_GetExitCodeProcess_t)(HANDLE hProcess, LPDWORD lpExitCode);
@@ -131,6 +134,9 @@ typedef struct __tb_kernel32_t
// WaitForSingleObject
tb_kernel32_WaitForSingleObject_t WaitForSingleObject;
+ // WaitForMultipleObjects
+ tb_kernel32_WaitForMultipleObjects_t WaitForMultipleObjects;
+
// GetExitCodeProcess
tb_kernel32_GetExitCodeProcess_t GetExitCodeProcess;
diff --git a/core/pkg/tbox.pkg/inc/tbox/tbox.config.h b/core/pkg/tbox.pkg/inc/tbox/tbox.config.h
new file mode 100644
index 000000000..a330a7f95
--- /dev/null
+++ b/core/pkg/tbox.pkg/inc/tbox/tbox.config.h
@@ -0,0 +1,115 @@
+#ifndef TB_CONFIG_H
+#define TB_CONFIG_H
+
+// version
+#define TB_CONFIG_VERSION "1.5.3"
+#define TB_CONFIG_VERSION_MAJOR 1
+#define TB_CONFIG_VERSION_MINOR 5
+#define TB_CONFIG_VERSION_ALTER 3
+#define TB_CONFIG_VERSION_BUILD 201607122000
+
+// defines
+#define TB_CONFIG_OS_MACOSX 1
+#define _GNU_SOURCE 1
+#define _REENTRANT 1
+#define TB_CONFIG_SMALL 1
+#define TB_CONFIG_TYPE_HAVE_FLOAT 1
+#define TB_CONFIG_POSIX_HAVE_POSIX_SPAWNP 1
+#define TB_CONFIG_LIBC_HAVE_MKTIME 1
+#define TB_CONFIG_LIBM_HAVE_ACOS 1
+#define TB_CONFIG_POSIX_HAVE_SOCKET 1
+#define TB_CONFIG_LIBC_HAVE_SETLOCALE 1
+#define TB_CONFIG_POSIX_HAVE_POLL 1
+#define TB_CONFIG_LIBC_HAVE_KILL 1
+#define TB_CONFIG_LIBM_HAVE_ATAN2 1
+#define TB_CONFIG_POSIX_HAVE_SCHED_YIELD 1
+#define TB_CONFIG_LIBC_HAVE_WCSLEN 1
+#define TB_CONFIG_LIBC_HAVE_WCSCMP 1
+#define TB_CONFIG_LIBC_HAVE_WCSNCAT 1
+#define TB_CONFIG_POSIX_HAVE_EXECVP 1
+#define TB_CONFIG_POSIX_HAVE_FORK 1
+#define TB_CONFIG_POSIX_HAVE_GETIFADDRS 1
+#define TB_CONFIG_POSIX_HAVE_DLOPEN 1
+#define TB_CONFIG_POSIX_HAVE_REGEXEC 1
+#define TB_CONFIG_POSIX_HAVE_VFORK 1
+#define TB_CONFIG_LIBC_HAVE_STRCAT 1
+#define TB_CONFIG_LIBC_HAVE_WCSSTR 1
+#define TB_CONFIG_LIBC_HAVE_WCSCAT 1
+#define TB_CONFIG_LIBM_HAVE_POW 1
+#define TB_CONFIG_LIBC_HAVE_MEMCPY 1
+#define TB_CONFIG_LIBM_HAVE_SQRTF 1
+#define TB_CONFIG_LIBC_HAVE_WCSNLEN 1
+#define TB_CONFIG_LIBM_HAVE_ACOSF 1
+#define TB_CONFIG_POSIX_HAVE_OPEN 1
+#define TB_CONFIG_LIBC_HAVE_STRNLEN 1
+#define TB_CONFIG_LIBM_HAVE_ATANF 1
+#define TB_CONFIG_LIBC_HAVE_STRNCAT 1
+#define TB_CONFIG_LIBC_HAVE_WCSNCPY 1
+#define TB_CONFIG_LIBC_HAVE_GMTIME 1
+#define TB_CONFIG_LIBM_HAVE_TAN 1
+#define TB_CONFIG_LIBM_HAVE_POWF 1
+#define TB_CONFIG_LIBM_HAVE_SINF 1
+#define TB_CONFIG_LIBM_HAVE_ATAN 1
+#define TB_CONFIG_LIBC_HAVE_STRNCMP 1
+#define TB_CONFIG_LIBC_HAVE_MEMMOVE 1
+#define TB_CONFIG_LIBC_HAVE_STRNCASECMP 1
+#define TB_CONFIG_LIBC_HAVE_STRLCPY 1
+#define TB_CONFIG_LIBC_HAVE_WCSCPY 1
+#define TB_CONFIG_LIBM_HAVE_SQRT 1
+#define TB_CONFIG_LIBC_HAVE_STRCMP 1
+#define TB_CONFIG_LIBC_HAVE_STRCASECMP 1
+#define TB_CONFIG_LIBC_HAVE_MEMSET 1
+#define TB_CONFIG_LIBC_HAVE_FPUTS 1
+#define TB_CONFIG_LIBM_HAVE_TANF 1
+#define TB_CONFIG_LIBC_HAVE_STRNCPY 1
+#define TB_CONFIG_LIBC_HAVE_LOCALTIME 1
+#define TB_CONFIG_LIBC_HAVE_WCSNCASECMP 1
+#define TB_CONFIG_LIBC_HAVE_STRCPY 1
+#define TB_CONFIG_LIBC_HAVE_WCSLCPY 1
+#define TB_CONFIG_SYSTEMV_HAVE_SEMGET 1
+#define TB_CONFIG_POSIX_HAVE_WAITPID 1
+#define TB_CONFIG_LIBC_HAVE_GETTIMEOFDAY 1
+#define TB_CONFIG_LIBC_HAVE_SIGNAL 1
+#define TB_CONFIG_LIBC_HAVE_STRSTR 1
+#define TB_CONFIG_POSIX_HAVE_WRITEV 1
+#define TB_CONFIG_LIBC_HAVE_WCSNCMP 1
+#define TB_CONFIG_POSIX_HAVE_READV 1
+#define TB_CONFIG_LIBM_HAVE_LOG2 1
+#define TB_CONFIG_LIBM_HAVE_COS 1
+#define TB_CONFIG_POSIX_HAVE_REGCOMP 1
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_MUTEX_INIT 1
+#define TB_CONFIG_LIBM_HAVE_FMODF 1
+#define TB_CONFIG_POSIX_HAVE_SYSCONF 1
+#define TB_CONFIG_LIBC_HAVE_WCSTOMBS 1
+#define TB_CONFIG_LIBM_HAVE_FMOD 1
+#define TB_CONFIG_LIBC_HAVE_MEMCMP 1
+#define TB_CONFIG_POSIX_HAVE_GETPAGESIZE 1
+#define TB_CONFIG_POSIX_HAVE_SEM_INIT 1
+#define TB_CONFIG_POSIX_HAVE_GETHOSTNAME 1
+#define TB_CONFIG_POSIX_HAVE_OPENDIR 1
+#define TB_CONFIG_LIBM_HAVE_COSF 1
+#define TB_CONFIG_LIBM_HAVE_ATAN2F 1
+#define TB_CONFIG_LIBM_HAVE_EXP 1
+#define TB_CONFIG_LIBM_HAVE_SIN 1
+#define TB_CONFIG_POSIX_HAVE_PTHREAD_CREATE 1
+#define TB_CONFIG_LIBM_HAVE_ASIN 1
+#define TB_CONFIG_LIBM_HAVE_EXPF 1
+#define TB_CONFIG_LIBC_HAVE_STRLEN 1
+#define TB_CONFIG_MODULE_HAVE_THREAD 1
+#define TB_CONFIG_MODULE_HAVE_NETWORK 1
+#define TB_CONFIG_LIBC_HAVE_MEMMEM 1
+#define TB_CONFIG_LIBC_HAVE_WCSCASECMP 1
+#define TB_CONFIG_LIBC_HAVE_MBSTOWCS 1
+#define TB_CONFIG_LIBC_HAVE_SIGSETJMP 1
+#define TB_CONFIG_LIBM_HAVE_LOG2F 1
+#define TB_CONFIG_LIBM_HAVE_ASINF 1
+#define TB_CONFIG_LIBC_HAVE_SETJMP 1
+#define TB_CONFIG_LIBC_HAVE_STRCASESTR 1
+#define TB_CONFIG_LIBC_HAVE_BACKTRACE 1
+
+// undefines
+#undef TB_CONFIG_TRACE_INFO_ONLY
+#undef TB_CONFIG_EXCEPTION_ENABLE
+#undef TB_CONFIG_MEMORY_UNALIGNED_ACCESS_ENABLE
+
+#endif
diff --git a/core/src/xmake/machine.c b/core/src/xmake/machine.c
index e7a032aa0..835060fdb 100755
--- a/core/src/xmake/machine.c
+++ b/core/src/xmake/machine.c
@@ -88,6 +88,7 @@ tb_int_t xm_string_startswith(lua_State* lua);
tb_int_t xm_process_open(lua_State* lua);
tb_int_t xm_process_openv(lua_State* lua);
tb_int_t xm_process_wait(lua_State* lua);
+tb_int_t xm_process_waitlist(lua_State* lua);
tb_int_t xm_process_close(lua_State* lua);
/* //////////////////////////////////////////////////////////////////////////////////////
@@ -144,6 +145,7 @@ static luaL_Reg const g_process_functions[] =
{ "open", xm_process_open }
, { "openv", xm_process_openv }
, { "wait", xm_process_wait }
+, { "waitlist", xm_process_waitlist }
, { "close", xm_process_close }
, { tb_null, tb_null }
};
diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile
index 32c3d903f..4b692eda3 100755
--- a/core/src/xmake/makefile
+++ b/core/src/xmake/makefile
@@ -43,6 +43,7 @@ xmake_C_FILES += \
process/open \
process/openv \
process/wait \
+ process/waitlist \
process/close
diff --git a/core/src/xmake/process/wait.c b/core/src/xmake/process/wait.c
index fe5d4db59..e7ff0cbaf 100755
--- a/core/src/xmake/process/wait.c
+++ b/core/src/xmake/process/wait.c
@@ -36,7 +36,7 @@
* implementation
*/
-// ok, status = process.wait(p, timeout)
+// ok, status = process.wait(proc, timeout)
tb_int_t xm_process_wait(lua_State* lua)
{
// check
@@ -44,7 +44,12 @@ tb_int_t xm_process_wait(lua_State* lua)
// is user data?
if (!lua_isuserdata(lua, 1))
+ {
+ // error
+ lua_pushfstring(lua, "invalid argument type(%s) for process.wait", luaL_typename(lua, 1));
+ lua_error(lua);
return 0;
+ }
// get the process
tb_process_ref_t process = (tb_process_ref_t)lua_touserdata(lua, 1);
diff --git a/core/src/xmake/process/waitlist.c b/core/src/xmake/process/waitlist.c
new file mode 100755
index 000000000..15e065628
--- /dev/null
+++ b/core/src/xmake/process/waitlist.c
@@ -0,0 +1,143 @@
+/*!The Automatic Cross-platform Build Tool
+ *
+ * XMake is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * XMake is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with XMake;
+ * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
+ *
+ * Copyright (C) 2015 - 2016, ruki All rights reserved.
+ *
+ * @author ruki
+ * @file waitlist.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "process.waitlist"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * implementation
+ */
+
+/* count, list = process.waitlist(proclist, timeout)
+ *
+ * count:
+ *
+ * the finished count: > 0
+ * timeout: 0
+ * failed: -1
+ *
+ * for _, procinfo in ipairs(list) do
+ * print("index: ", procinfo[1])
+ * print("status: ", procinfo[2])
+ * print("process: ", procinfo[3])
+ * end
+ */
+tb_int_t xm_process_waitlist(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ // is table?
+ if (!lua_istable(lua, 1))
+ {
+ // error
+ lua_pushfstring(lua, "invalid argument type(%s) for process.waitlist", luaL_typename(lua, 1));
+ lua_error(lua);
+ return 0;
+ }
+
+ // get the processes count
+ tb_long_t count = lua_objlen(lua, 1);
+ if (count <= 0 || count > 64)
+ {
+ // error
+ lua_pushfstring(lua, "invalid process count(%ld) for process.waitlist", count);
+ lua_error(lua);
+ return 0;
+ }
+
+ // get the processes
+ tb_size_t i = 0;
+ tb_process_ref_t processes[64 + 1];
+ for (i = 0; i < count; i++)
+ {
+ // get proclist[i]
+ lua_pushinteger(lua, i + 1);
+ lua_gettable(lua, 1);
+
+ // is userdata?
+ if (lua_isuserdata(lua, -1))
+ {
+ // save this process
+ processes[i] = lua_touserdata(lua, -1);
+ if (!processes[i])
+ {
+ // error
+ lua_pushfstring(lua, "process[%ld] is null for process.waitlist", i);
+ lua_error(lua);
+ }
+ }
+ else
+ {
+ // error
+ lua_pushfstring(lua, "invalid process[%ld] type(%s) for process.waitlist", i, luaL_typename(lua, -1));
+ lua_error(lua);
+ }
+
+ // pop it
+ lua_pop(lua, 1);
+ }
+
+ // end
+ processes[count] = tb_null;
+
+ // get the timeout
+ tb_long_t timeout = (tb_long_t)luaL_checkinteger(lua, 2);
+
+ // wait it
+ tb_process_waitinfo_t infolist[64];
+ tb_long_t infosize = tb_process_waitlist(processes, infolist, tb_arrayn(infolist), timeout);
+
+ // save process info count
+ lua_pushinteger(lua, infosize);
+ if (infosize > 0)
+ {
+ // save process info list
+ lua_newtable(lua);
+ for (i = 0; i < infosize; i++)
+ {
+ // save one process info
+ lua_newtable(lua);
+ lua_pushinteger(lua, infolist[i].index + 1);
+ lua_rawseti(lua, -2, 1);
+ lua_pushinteger(lua, infolist[i].status);
+ lua_rawseti(lua, -2, 2);
+ lua_pushlightuserdata(lua, infolist[i].process);
+ lua_rawseti(lua, -2, 3);
+
+ lua_rawseti(lua, -2, i + 1);
+ }
+ }
+ else lua_pushnil(lua);
+
+ // ok
+ return 2;
+}