diff options
| author | ruki <[email protected]> | 2016-12-09 09:56:05 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2016-12-09 09:56:05 +0800 |
| commit | 432c1692189911296fecd8779d623cea96141617 (patch) | |
| tree | c093f2c726a6c4384d608493c50bb4ff3a13d63b | |
| parent | 2933d72e11d4af052dd3bc804926a53b85a9b4a6 (diff) | |
update tbox for linux x86_64
16 files changed, 979 insertions, 24 deletions
diff --git a/core/pkg/tbox.pkg/inc/linux/tbox.config.h b/core/pkg/tbox.pkg/inc/linux/tbox.config.h index c635166f7..5c05019b9 100755 --- a/core/pkg/tbox.pkg/inc/linux/tbox.config.h +++ b/core/pkg/tbox.pkg/inc/linux/tbox.config.h @@ -2,11 +2,11 @@ #define TB_CONFIG_H // version -#define TB_CONFIG_VERSION "1.6.1" +#define TB_CONFIG_VERSION "1.6.2" #define TB_CONFIG_VERSION_MAJOR 1 #define TB_CONFIG_VERSION_MINOR 6 -#define TB_CONFIG_VERSION_ALTER 1 -#define TB_CONFIG_VERSION_BUILD 201612012304 +#define TB_CONFIG_VERSION_ALTER 2 +#define TB_CONFIG_VERSION_BUILD 201612090948 // defines #define TB_CONFIG_OS_LINUX 1 @@ -81,6 +81,7 @@ #define TB_CONFIG_LIBM_HAVE_EXP 1 #define TB_CONFIG_LIBM_HAVE_EXPF 1 #define TB_CONFIG_POSIX_HAVE_POLL 1 +#define TB_CONFIG_POSIX_HAVE_SELECT 1 #define TB_CONFIG_POSIX_HAVE_PTHREAD_MUTEX_INIT 1 #define TB_CONFIG_POSIX_HAVE_PTHREAD_CREATE 1 #define TB_CONFIG_POSIX_HAVE_PTHREAD_SETSPECIFIC 1 diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/coroutine.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/coroutine.h index 390640f71..15a4ddb64 100755 --- a/core/pkg/tbox.pkg/inc/tbox/coroutine/coroutine.h +++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/coroutine.h @@ -31,6 +31,7 @@ #include "channel.h" #include "semaphore.h" #include "scheduler.h" +#include "stackless/stackless.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern @@ -101,7 +102,7 @@ tb_pointer_t tb_coroutine_sleep(tb_long_t interval); * * @return > 0: the events, 0: timeout, -1: failed */ -tb_long_t tb_coroutine_wait(tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout); +tb_long_t tb_coroutine_waitio(tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout); /*! get the current coroutine * diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/core.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/core.h new file mode 100755 index 000000000..298beab04 --- /dev/null +++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/core.h @@ -0,0 +1,169 @@ +/*!The Treasure Box Library + * + * TBox 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. + * + * TBox 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 TBox; + * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> + * + * Copyright (C) 2009 - 2017, ruki All rights reserved. + * + * @author ruki + * @file core.h + * @ingroup coroutine + * + */ +#ifndef TB_COROUTINE_STACKLESS_CORE_H +#define TB_COROUTINE_STACKLESS_CORE_H + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * macros + */ + +/* + * Copyright (c) 2004-2005, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +// get core from coroutine +#define tb_lo_core(co) ((tb_lo_core_ref_t)(co)) + +// get core state +#define tb_lo_core_state(co) (tb_lo_core(co)->state) + +// set core state +#define tb_lo_core_state_set(co, val) tb_lo_core(co)->state = (val) + +#ifdef TB_COMPILER_IS_GCC +/* + * Implementation of local continuations based on the "Labels as + * values" feature of gcc + * + * @author Adam Dunkels <[email protected]> + * + * This implementation of local continuations is based on a special + * feature of the GCC C compiler called "labels as values". This + * feature allows assigning pointers with the address of the code + * corresponding to a particular C label. + * + * For more information, see the GCC documentation: + * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html + */ +# define tb_lo_core_init(co) tb_lo_core(co)->branch = tb_null; tb_lo_core(co)->state = TB_STATE_READY +# define tb_lo_core_resume(co) \ + if (tb_lo_core(co)->branch) \ + { \ + goto *(tb_lo_core(co)->branch); \ + } \ + else + +# define tb_lo_core_record(co) \ + do \ + { \ + __tb_mconcat_ex__(__tb_lo_core_label, __tb_line__): \ + tb_lo_core(co)->branch = &&__tb_mconcat_ex__(__tb_lo_core_label, __tb_line__); \ + \ + } while(0) + +# define tb_lo_core_exit(co) tb_lo_core(co)->branch = tb_null, tb_lo_core(co)->state = TB_STATE_END + +#else + +/* + * Implementation of local continuations based on switch() statment + * + * @author Adam Dunkels <[email protected]> + * + * This implementation of local continuations uses the C switch() + * statement to resume execution of a function somewhere inside the + * function's body. The implementation is based on the fact that + * switch() statements are able to jump directly into the bodies of + * control structures such as if() or while() statmenets. + * + * This implementation borrows heavily from Simon Tatham's coroutines + * implementation in C: + * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html + * + * + * + * WARNING! the implementation using switch() does not work if an + * core_set() is done within another switch() statement! + */ +# define tb_lo_core_init(co) tb_lo_core(co)->branch = 0; tb_lo_core(co)->state = TB_STATE_READY +# define tb_lo_core_resume(co) switch (tb_lo_core(co)->branch) case 0: +# define tb_lo_core_record_(co, label) tb_lo_core(co)->branch = (tb_uint16_t)label; case label: +# define tb_lo_core_exit(co) tb_lo_core(co)->branch = 0, tb_lo_core(co)->state = TB_STATE_END +# ifdef TB_COMPILER_IS_MSVC +# define tb_lo_core_record(co) tb_lo_core_record_(co, __COUNTER__ + 1) +# else +# define tb_lo_core_record(co) tb_lo_core_record_(co, __tb_line__) +# endif +#endif + +/* ////////////////////////////////////////////////////////////////////////////////////// + * types + */ + +// the core branch type +#ifdef TB_COMPILER_IS_GCC +typedef tb_pointer_t tb_lo_core_branch_t; +#else +typedef tb_uint16_t tb_lo_core_branch_t; +#endif + +// the stackless coroutine core type +typedef struct __tb_lo_core_t +{ + // the code branch + tb_lo_core_branch_t branch; + + /* the state + * + * TB_STATE_READY + * TB_STATE_SUSPEND + * TB_STATE_END + */ + tb_uint8_t state; + +}tb_lo_core_t, *tb_lo_core_ref_t; + + +#endif diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/coroutine.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/coroutine.h new file mode 100755 index 000000000..c24d3bda0 --- /dev/null +++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/coroutine.h @@ -0,0 +1,411 @@ +/*!The Treasure Box Library + * + * TBox 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. + * + * TBox 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 TBox; + * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> + * + * Copyright (C) 2009 - 2017, ruki All rights reserved. + * + * @author ruki + * @file coroutine.h + * @ingroup coroutine + * + */ +#ifndef TB_COROUTINE_STACKLESS_COROUTINE_H +#define TB_COROUTINE_STACKLESS_COROUTINE_H + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "core.h" +#include "scheduler.h" +#include "../../libc/libc.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * macros + */ + +/// the self coroutine +#define tb_lo_coroutine_self() (co__) + +/* enter coroutine + * + * @code + * + // before + tb_lo_coroutine_enter(co) + { + for (i = 0; i < 100; i++) + { + tb_lo_coroutine_yield(); + } + } + + // after expanding again (init: branch = 0, state = TB_STATE_READY) + tb_lo_coroutine_ref_t co__ = co; + tb_int_t lo_yield_flag__ = 1; + for (; lo_yield_flag__; tb_lo_core(co__)->branch = 0, tb_lo_core(co__)->state = TB_STATE_END, lo_yield_flag__ = 0) + switch (tb_lo_core(co__)->branch) + case 0: + { + for (i = 0; i < 100; i++) + { + lo_yield_flag__ = 0; + tb_lo_core(co__)->branch = __tb_line__; case __tb_line__:; + if (lo_yield_flag__ == 0) + return ; + } + } + + // or .. + + // after expanding again for gcc label (init: branch = tb_null, state = TB_STATE_READY) + tb_lo_coroutine_ref_t co__ = co; + tb_int_t lo_yield_flag__ = 1; + for (; lo_yield_flag__; tb_lo_core(co__)->branch = tb_null, tb_lo_core(co__)->state = TB_STATE_END, lo_yield_flag__ = 0) + if (tb_lo_core(co)->branch) + { + goto *(tb_lo_core(co)->branch); + } + else + { + for (i = 0; i < 100; i++) + { + lo_yield_flag__ = 0; + do + { + __tb_mconcat_ex__(__tb_lo_core_label, __tb_line__): + tb_lo_core(co)->branch = &&__tb_mconcat_ex__(__tb_lo_core_label, __tb_line__); + + } while(0) + + if (lo_yield_flag__ == 0) + return ; + } + } + + * @endcode + */ +#define tb_lo_coroutine_enter(co) \ + tb_lo_coroutine_ref_t co__ = (co); \ + tb_int_t lo_yield_flag__ = 1; \ + for ( ; lo_yield_flag__; tb_lo_core_exit(tb_lo_coroutine_self()), lo_yield_flag__ = 0) \ + tb_lo_core_resume(tb_lo_coroutine_self()) + +/// yield coroutine +#define tb_lo_coroutine_yield() \ +do \ +{ \ + lo_yield_flag__ = 0; \ + tb_lo_core_record(co__); \ + if (lo_yield_flag__ == 0) \ + return ; \ + \ +} while(0) + +/*! suspend current coroutine + * + * the scheduler will move this coroutine to the suspended coroutines after the function be returned + * + * @code + * + // before + tb_lo_coroutine_enter(co) + { + for (i = 0; i < 100; i++) + { + tb_lo_coroutine_yield(); + tb_lo_coroutine_suspend(); + } + } + + // after expanding again (init: branch = 0, state = TB_STATE_READY) + tb_lo_coroutine_ref_t co__ = co; + tb_int_t lo_yield_flag__ = 1; + for (; lo_yield_flag__; tb_lo_core(co__)->branch = 0, tb_lo_core(co__)->state = TB_STATE_END, lo_yield_flag__ = 0) + switch (tb_lo_core(co__)->branch) + case 0: + { + for (i = 0; i < 100; i++) + { + lo_yield_flag__ = 0; + tb_lo_core(co__)->branch = __tb_line__; case __tb_line__:; + if (lo_yield_flag__ == 0) + return ; + + // suspend coroutine + tb_lo_core(co__)->state = TB_STATE_SUSPEND; + tb_lo_core(co__)->branch = __tb_line__; case __tb_line__:; + if (tb_lo_core(co__)->state == TB_STATE_SUSPEND) + return ; + } + } + * @endcode + */ +#define tb_lo_coroutine_suspend() \ +do \ +{ \ + tb_used(&lo_yield_flag__); \ + tb_lo_core_state_set(tb_lo_coroutine_self(), TB_STATE_SUSPEND); \ + tb_lo_core_record(tb_lo_coroutine_self()); \ + if (tb_lo_core_state(tb_lo_coroutine_self()) == TB_STATE_SUSPEND) \ + return ; \ + \ +} while(0) + +/// sleep some time +#define tb_lo_coroutine_sleep(interval) \ +do \ +{ \ + if (interval) \ + { \ + tb_lo_coroutine_sleep_(tb_lo_coroutine_self(), interval); \ + tb_lo_coroutine_suspend(); \ + } \ + \ +} while(0) + +/// wait io socket events +#define tb_lo_coroutine_waitio(sock, events, interval) \ +do \ +{ \ + if (tb_lo_coroutine_waitio_(tb_lo_coroutine_self(), sock, events, interval)) \ + { \ + tb_lo_coroutine_suspend(); \ + } \ + \ +} while(0) + +/// wait until coroutine be true +#define tb_lo_coroutine_wait_until(cond) \ +do \ +{ \ + tb_used(&lo_yield_flag__); \ + tb_lo_core_record(tb_lo_coroutine_self()); \ + if (!(cond)) \ + return ; \ + \ +} while(0) + +/// wait while coroutine be true +#define tb_lo_coroutine_wait_while(pt, cond) tb_lo_coroutine_wait_until(!(cond)) + +/// get socket events after waiting +#define tb_lo_coroutine_events() tb_lo_coroutine_events_(tb_lo_coroutine_self()) + +/*! pass the user private data + * + * @code + + // start coroutine + tb_lo_coroutine_start(scheduler, coroutine_func, tb_lo_coroutine_pass(tb_xxxx_priv_t)); + + * @endcode + * + * => + * + * @code + + // start coroutine + tb_lo_coroutine_start(scheduler, coroutine_func, tb_malloc0_type(tb_xxxx_priv_t), tb_lo_coroutine_pass_free_); + + * @endcode + */ +#define tb_lo_coroutine_pass(type) tb_malloc0_type(type), tb_lo_coroutine_pass_free_ + +/*! pass the user private data and init one member + * + * @code + + typedef struct __tb_xxxx_priv_t + { + tb_size_t member; + tb_size_t others; + + }tb_xxxx_priv_t; + + // start coroutine + tb_lo_coroutine_start(scheduler, coroutine_func, tb_lo_coroutine_pass1(tb_xxxx_priv_t, member, value)); + + * @endcode + * + * => + * + * @code + + tb_xxxx_priv_t* priv = tb_malloc0_type(tb_xxxx_priv_t); + if (priv) + { + priv->member = value; + } + + // start coroutine + tb_lo_coroutine_start(scheduler, coroutine_func, priv, tb_lo_coroutine_pass_free_); + + * @endcode + */ +#define tb_lo_coroutine_pass1(type, member, value) tb_lo_coroutine_pass1_make_(sizeof(type), &(value), tb_offsetof(type, member), tb_memsizeof(type, member)), tb_lo_coroutine_pass_free_ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * extern + */ +__tb_extern_c_enter__ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * private interfaces + */ + +/* get the scheduler of coroutine + * + * @param coroutine the coroutine + * + * @return the scheduler + */ +tb_lo_scheduler_ref_t tb_lo_coroutine_scheduler_(tb_lo_coroutine_ref_t coroutine); + +/* sleep the current coroutine + * + * @param coroutine the coroutine + * @param interval the interval (ms), infinity: -1 + */ +tb_void_t tb_lo_coroutine_sleep_(tb_lo_coroutine_ref_t coroutine, tb_long_t interval); + +/* wait io events + * + * @param coroutine the coroutine + * @param sock the socket + * @param events the waited events + * @param timeout the timeout, infinity: -1 + * + * @return suspend coroutine if be tb_true + */ +tb_bool_t tb_lo_coroutine_waitio_(tb_lo_coroutine_ref_t coroutine, tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout); + +/* get the events after waiting socket + * + * @param coroutine the coroutine + * + * @return events: > 0, failed: -1, timeout: 0 + */ +tb_long_t tb_lo_coroutine_events_(tb_lo_coroutine_ref_t coroutine); + +/* free the user private data for pass() + * + * @note only be a wrapper of free() for tb_lo_coroutine_pass() + * + * @param priv the user private data + */ +tb_void_t tb_lo_coroutine_pass_free_(tb_cpointer_t priv); + +/* make the user private data for pass1() + * + * @param type_size the data type size + * @param value the value pointer + * @param offset the member offset + * @param size the value size + * + * @return the user private data + */ +tb_pointer_t tb_lo_coroutine_pass1_make_(tb_size_t type_size, tb_cpointer_t value, tb_size_t offset, tb_size_t size); + +/* make the user private data for pass2() + * + * @param type_size the data type size + * @param value1 the value1 pointer + * @param offset1 the member1 offset + * @param size1 the value1 size + * @param value2 the value2 pointer + * @param offset2 the member2 offset + * @param size2 the value2 size + * + * @return the user private data + */ +tb_pointer_t tb_lo_coroutine_pass2_make_(tb_size_t type_size, tb_cpointer_t value1, tb_size_t offset1, tb_size_t size1, tb_cpointer_t value2, tb_size_t offset2, tb_size_t size2); + +/* ////////////////////////////////////////////////////////////////////////////////////// + * interfaces + */ + +/*! start coroutine + * + * @code + static tb_void_t switchtask(tb_lo_coroutine_ref_t coroutine, tb_cpointer_t priv) + { + // get count pointer (@note only allow non-status local variables) + tb_size_t* count = (tb_size_t*)priv; + + // enter coroutine + tb_lo_coroutine_enter(coroutine); + + // @note can not define local variables here + // ... + + // loop + while ((*count)--) + { + // yield + tb_lo_coroutine_yield(); + } + + // leave coroutine + tb_lo_coroutine_leave(); + } + + tb_int_t main (tb_int_t argc, tb_char_t** argv) + { + // init tbox + if (!tb_init(tb_null, tb_null)) return -1; + + // init scheduler + tb_lo_scheduler_ref_t scheduler = tb_lo_scheduler_init(); + if (scheduler) + { + // start coroutine + tb_size_t counts[] = {100, 100}; + tb_lo_coroutine_start(scheduler, switchtask, &counts[0], tb_null); + tb_lo_coroutine_start(scheduler, switchtask, &counts[1], tb_null); + + // run scheduler + tb_lo_scheduler_loop(scheduler); + + // exit scheduler + tb_lo_scheduler_exit(scheduler); + } + + // exit tbox + tb_exit(); + } + + * @endcode + * + * @param scheduler the scheduler (can not be null, we can get scheduler of the current coroutine from tb_lo_scheduler_self()) + * @param func the coroutine function + * @param priv the passed user private data as the argument of function + * @param free the user private free function + * + * @return tb_true or tb_false + */ +tb_bool_t tb_lo_coroutine_start(tb_lo_scheduler_ref_t scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free); + +/*! resume the given coroutine + * + * @param coroutine the coroutine + */ +tb_void_t tb_lo_coroutine_resume(tb_lo_coroutine_ref_t coroutine); + +/* ////////////////////////////////////////////////////////////////////////////////////// + * extern + */ +__tb_extern_c_leave__ + +#endif diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/lock.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/lock.h new file mode 100755 index 000000000..ceae8e0b1 --- /dev/null +++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/lock.h @@ -0,0 +1,79 @@ +/*!The Treasure Box Library + * + * TBox 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. + * + * TBox 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 TBox; + * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> + * + * Copyright (C) 2009 - 2017, ruki All rights reserved. + * + * @author ruki + * @file lock.h + * @ingroup coroutine + * + */ +#ifndef TB_COROUTINE_STACKLESS_LOCK_H +#define TB_COROUTINE_STACKLESS_LOCK_H + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "semaphore.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * macros + */ + +/*! init lock + * + * @param lock the lock pointer + */ +#define tb_lo_lock_init(lock) tb_lo_semaphore_init(lock, 1) + +/*! exit lock + * + * @param lock the lock pointer + */ +#define tb_lo_lock_exit(lock) tb_lo_semaphore_exit(lock) + +/*! enter lock + * + * @param lock the lock pointer + */ +#define tb_lo_lock_enter(lock) tb_lo_semaphore_wait(lock) + +/*! try to enter lock + * + * @param lock the lock pointer + * + * @return tb_true or tb_false + */ +#define tb_lo_lock_enter_try(lock) tb_lo_semaphore_wait_try(lock) + +/*! leave lock + * + * @param lock the lock pointer + */ +#define tb_lo_lock_leave(lock) tb_lo_semaphore_post(lock, 1) + + +/* ////////////////////////////////////////////////////////////////////////////////////// + * types + */ + +/// the stackless lock type +typedef tb_lo_semaphore_t tb_lo_lock_t; + +/// the stackless lock ref type +typedef tb_lo_semaphore_ref_t tb_lo_lock_ref_t; + +#endif diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/prefix.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/prefix.h new file mode 100755 index 000000000..288f8ebd8 --- /dev/null +++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/prefix.h @@ -0,0 +1,55 @@ +/*!The Treasure Box Library + * + * TBox 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. + * + * TBox 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 TBox; + * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> + * + * Copyright (C) 2009 - 2017, ruki All rights reserved. + * + * @author ruki + * @file prefix.h + * + */ +#ifndef TB_COROUTINE_STACKLESS_PREFIX_H +#define TB_COROUTINE_STACKLESS_PREFIX_H + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "../prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * types + */ + +/// the stackless coroutine ref type +typedef __tb_typeref__(lo_coroutine); + +/// the stackless scheduler ref type +typedef __tb_typeref__(lo_scheduler); + +/*! the coroutine function type + * + * @param coroutine the coroutine self + * @param priv the user private data from start(.., priv) + */ +typedef tb_void_t (*tb_lo_coroutine_func_t)(tb_lo_coroutine_ref_t coroutine, tb_cpointer_t priv); + +/*! the user private data free function type + * + * @param priv the user private data from start(.., priv) + */ +typedef tb_void_t (*tb_lo_coroutine_free_t)(tb_cpointer_t priv); + + +#endif diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/scheduler.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/scheduler.h new file mode 100755 index 000000000..f1b607a49 --- /dev/null +++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/scheduler.h @@ -0,0 +1,79 @@ +/*!The Treasure Box Library + * + * TBox 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. + * + * TBox 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 TBox; + * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> + * + * Copyright (C) 2009 - 2017, ruki All rights reserved. + * + * @author ruki + * @file scheduler.h + * @ingroup coroutine + * + */ +#ifndef TB_COROUTINE_STACKLESS_SCHEDULER_H +#define TB_COROUTINE_STACKLESS_SCHEDULER_H + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * macros + */ + +/// the self scheduler +#define tb_lo_scheduler_self() tb_lo_coroutine_scheduler_(co__) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * extern + */ +__tb_extern_c_enter__ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * interfaces + */ + +/*! init scheduler + * + * @return the scheduler + */ +tb_lo_scheduler_ref_t tb_lo_scheduler_init(tb_noarg_t); + +/*! exit scheduler + * + * @param scheduler the scheduler + */ +tb_void_t tb_lo_scheduler_exit(tb_lo_scheduler_ref_t scheduler); + +/* kill the scheduler + * + * @param scheduler the scheduler + */ +tb_void_t tb_lo_scheduler_kill(tb_lo_scheduler_ref_t scheduler); + +/*! run the scheduler loop + * + * @param scheduler the scheduler + * @param exclusive enable exclusive mode, we need ensure only one loop() be called at the same time, + * but it will be faster using thr global scheduler instead of TLS storage + */ +tb_void_t tb_lo_scheduler_loop(tb_lo_scheduler_ref_t scheduler, tb_bool_t exclusive); + +/* ////////////////////////////////////////////////////////////////////////////////////// + * extern + */ +__tb_extern_c_leave__ + +#endif diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/semaphore.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/semaphore.h new file mode 100755 index 000000000..32d7c6518 --- /dev/null +++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/semaphore.h @@ -0,0 +1,102 @@ +/*!The Treasure Box Library + * + * TBox 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. + * + * TBox 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 TBox; + * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> + * + * Copyright (C) 2009 - 2017, ruki All rights reserved. + * + * @author ruki + * @file semaphore.h + * @ingroup coroutine + * + */ +#ifndef TB_COROUTINE_STACKLESS_SEMAPHORE_H +#define TB_COROUTINE_STACKLESS_SEMAPHORE_H + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "coroutine.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * macros + */ + +/*! init semaphore + * + * @param sem the semaphore pointer + * @param val the initial semaphore value + */ +#define tb_lo_semaphore_init(sem, val) (sem)->value = val + +/*! exit semaphore + * + * @param sem the semaphore pointer + */ +#define tb_lo_semaphore_exit(sem) (sem)->value = 0 + +/*! get semaphore value + * + * @param sem the semaphore pointer + * + * @return the semaphore value + */ +#define tb_lo_semaphore_value(sem) ((sem)->value) + +/*! post semaphore + * + * @param sem the semaphore pointer + * @param post the post semaphore value + */ +#define tb_lo_semaphore_post(sem, post) \ +do \ +{ \ + (sem)->value += (post); \ + tb_lo_coroutine_yield(); \ + \ +} while (0) + +/*! wait semaphore + * + * @param sem the semaphore pointer + */ +#define tb_lo_semaphore_wait(sem) \ +do \ +{ \ + tb_lo_coroutine_wait_until((sem)->value > 0); \ + (sem)->value--; \ + \ +} while(0) + +/*! try to wait semaphore + * + * @param sem the semaphore pointer + * + * @return tb_true or tb_false + */ +#define tb_lo_semaphore_wait_try(sem) (((sem)->value > 0)? (sem)->value-- : 0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * types + */ + +/// the stackless semaphore type +typedef struct __tb_lo_semaphore_t +{ + // the semaphore value + tb_long_t value; + +}tb_lo_semaphore_t, *tb_lo_semaphore_ref_t; + +#endif diff --git a/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/stackless.h b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/stackless.h new file mode 100755 index 000000000..c898c8ff6 --- /dev/null +++ b/core/pkg/tbox.pkg/inc/tbox/coroutine/stackless/stackless.h @@ -0,0 +1,36 @@ +/*!The Treasure Box Library + * + * TBox 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. + * + * TBox 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 TBox; + * If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a> + * + * Copyright (C) 2009 - 2017, ruki All rights reserved. + * + * @author ruki + * @file stackless.h + * @ingroup coroutine + * + */ +#ifndef TB_COROUTINE_STACKLESS_H +#define TB_COROUTINE_STACKLESS_H + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "coroutine.h" +#include "scheduler.h" +#include "semaphore.h" +#include "lock.h" + + +#endif diff --git a/core/pkg/tbox.pkg/inc/tbox/platform/poller.h b/core/pkg/tbox.pkg/inc/tbox/platform/poller.h index 76e1bd083..c746bff57 100755 --- a/core/pkg/tbox.pkg/inc/tbox/platform/poller.h +++ b/core/pkg/tbox.pkg/inc/tbox/platform/poller.h @@ -41,16 +41,23 @@ __tb_extern_c_enter__ /// the poller event enum, only for sock typedef enum __tb_poller_event_e { + // the waited events TB_POLLER_EVENT_NONE = TB_SOCKET_EVENT_NONE , TB_POLLER_EVENT_CONN = TB_SOCKET_EVENT_CONN , TB_POLLER_EVENT_ACPT = TB_SOCKET_EVENT_ACPT , TB_POLLER_EVENT_RECV = TB_SOCKET_EVENT_RECV , TB_POLLER_EVENT_SEND = TB_SOCKET_EVENT_SEND +, TB_POLLER_EVENT_EALL = TB_SOCKET_EVENT_EALL + // the event flags after waiting , TB_POLLER_EVENT_CLEAR = 0x0010 //!< edge trigger. after the event is retrieved by the user, its state is reset , TB_POLLER_EVENT_ONESHOT = 0x0020 //!< causes the event to return only the first occurrence of the filter being triggered -, TB_POLLER_EVENT_EALL = TB_SOCKET_EVENT_EALL + /*! the event flag will be marked if the connection be closed in the edge trigger (TB_POLLER_EVENT_CLEAR) + * + * be similar to epoll.EPOLLRDHUP and kqueue.EV_EOF + */ +, TB_POLLER_EVENT_EOF = 0x0100 }tb_poller_event_e; diff --git a/core/pkg/tbox.pkg/inc/tbox/platform/windows/interface/ws2_32.h b/core/pkg/tbox.pkg/inc/tbox/platform/windows/interface/ws2_32.h index 8ac1d5e92..7c3c48ba4 100755 --- a/core/pkg/tbox.pkg/inc/tbox/platform/windows/interface/ws2_32.h +++ b/core/pkg/tbox.pkg/inc/tbox/platform/windows/interface/ws2_32.h @@ -118,6 +118,9 @@ typedef tb_int_t (WSAAPI* tb_ws2_32___WSAFDIsSet_t)(SOCKET fd, fd_set* set); // the getaddrinfo func type typedef tb_int_t (WSAAPI* tb_ws2_32_getaddrinfo_t)(PCSTR pNodeName, PCSTR pServiceName, ADDRINFOA *pHints, PADDRINFOA *ppResult); +// the freeaddrinfo func type +typedef tb_void_t (WSAAPI* tb_ws2_32_freeaddrinfo_t)(struct addrinfo* ai); + // the getnameinfo func type typedef tb_int_t (WSAAPI* tb_ws2_32_getnameinfo_t)(const struct sockaddr FAR *sa, socklen_t salen, tb_char_t FAR *host, DWORD hostlen, tb_char_t FAR *serv, DWORD servlen, tb_int_t flags); @@ -207,6 +210,9 @@ typedef struct __tb_ws2_32_t // getaddrinfo tb_ws2_32_getaddrinfo_t getaddrinfo; + + // freeaddrinfo + tb_ws2_32_freeaddrinfo_t freeaddrinfo; // getnameinfo tb_ws2_32_getnameinfo_t getnameinfo; diff --git a/core/pkg/tbox.pkg/inc/tbox/prefix/compiler.h b/core/pkg/tbox.pkg/inc/tbox/prefix/compiler.h index cbda980cf..18b8c3fb6 100755 --- a/core/pkg/tbox.pkg/inc/tbox/prefix/compiler.h +++ b/core/pkg/tbox.pkg/inc/tbox/prefix/compiler.h @@ -286,6 +286,8 @@ # define TB_COMPILER_VERSION_STRING "visual c++ .net 2013 (12.0)" # elif (_MSC_VER == 1900) # define TB_COMPILER_VERSION_STRING "visual c++ .net 2015 (14.0)" +# elif (_MSC_VER == 2000) +# define TB_COMPILER_VERSION_STRING "visual c++ .net 2017 (15.0)" # else # error Unknown visual c++ Compiler Version # endif diff --git a/core/pkg/tbox.pkg/inc/tbox/utils/bits.h b/core/pkg/tbox.pkg/inc/tbox/utils/bits.h index d5f97adff..dc05316ac 100755 --- a/core/pkg/tbox.pkg/inc/tbox/utils/bits.h +++ b/core/pkg/tbox.pkg/inc/tbox/utils/bits.h @@ -29,8 +29,7 @@ */ #include "prefix.h" #include "../libm/libm.h" -#if defined(TB_COMPILER_IS_GCC) \ - && TB_COMPILER_VERSION_BE(4, 1) +#if defined(TB_COMPILER_IS_GCC) # include "impl/bits_gcc.h" #endif #if defined(TB_ARCH_x86) || defined(TB_ARCH_x64) @@ -658,22 +657,22 @@ static __tb_inline__ tb_void_t tb_bits_set_u64_be_inline(tb_byte_t* p, tb_uint64 */ // swap -static __tb_inline__ tb_uint16_t const tb_bits_swap_u16_inline(tb_uint16_t x) +static __tb_inline__ tb_uint16_t tb_bits_swap_u16_inline(tb_uint16_t x) { x = (x >> 8) | (x << 8); return x; } -static __tb_inline__ tb_uint32_t const tb_bits_swap_u24_inline(tb_uint32_t x) +static __tb_inline__ tb_uint32_t tb_bits_swap_u24_inline(tb_uint32_t x) { return (x >> 16) | (x & 0x0000ff00) | (x << 16); } -static __tb_inline__ tb_uint32_t const tb_bits_swap_u32_inline(tb_uint32_t x) +static __tb_inline__ tb_uint32_t tb_bits_swap_u32_inline(tb_uint32_t x) { x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); x = (x >> 16) | (x << 16); return x; } -static __tb_inline__ tb_hize_t const tb_bits_swap_u64_inline(tb_hize_t x) +static __tb_inline__ tb_hize_t tb_bits_swap_u64_inline(tb_hize_t x) { union { diff --git a/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_gcc.h b/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_gcc.h index df853e693..0d96249a1 100755 --- a/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_gcc.h +++ b/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_gcc.h @@ -32,22 +32,30 @@ * macros */ // swap -#define tb_bits_swap_u32(x) __builtin_bswap32(x) -#define tb_bits_swap_u64(x) __builtin_bswap64(x) +#if TB_COMPILER_VERSION_BE(4, 3) +# define tb_bits_swap_u32(x) __builtin_bswap32(x) +# define tb_bits_swap_u64(x) __builtin_bswap64(x) +#endif // cl0 -#define tb_bits_cl0_u32_be(x) ((x)? (tb_size_t)__builtin_clz((tb_uint32_t)(x)) : 32) -#define tb_bits_cl0_u32_le(x) ((x)? (tb_size_t)__builtin_ctz((tb_uint32_t)(x)) : 32) -#define tb_bits_cl0_u64_be(x) ((x)? (tb_size_t)__builtin_clzll((tb_uint64_t)(x)) : 64) -#define tb_bits_cl0_u64_le(x) ((x)? (tb_size_t)__builtin_ctzll((tb_uint64_t)(x)) : 64) +#if TB_COMPILER_VERSION_BE(4, 1) +# define tb_bits_cl0_u32_be(x) ((x)? (tb_size_t)__builtin_clz((tb_uint32_t)(x)) : 32) +# define tb_bits_cl0_u32_le(x) ((x)? (tb_size_t)__builtin_ctz((tb_uint32_t)(x)) : 32) +# define tb_bits_cl0_u64_be(x) ((x)? (tb_size_t)__builtin_clzll((tb_uint64_t)(x)) : 64) +# define tb_bits_cl0_u64_le(x) ((x)? (tb_size_t)__builtin_ctzll((tb_uint64_t)(x)) : 64) +#endif // cb1 -#define tb_bits_cb1_u32(x) ((x)? (tb_size_t)__builtin_popcount((tb_uint32_t)(x)) : 0) -#define tb_bits_cb1_u64(x) ((x)? (tb_size_t)__builtin_popcountll((tb_uint64_t)(x)) : 0) +#if TB_COMPILER_VERSION_BE(4, 1) +# define tb_bits_cb1_u32(x) ((x)? (tb_size_t)__builtin_popcount((tb_uint32_t)(x)) : 0) +# define tb_bits_cb1_u64(x) ((x)? (tb_size_t)__builtin_popcountll((tb_uint64_t)(x)) : 0) +#endif // fb1 -#define tb_bits_fb1_u32_le(x) ((x)? (tb_size_t)__builtin_ffs((tb_uint32_t)(x)) - 1 : 32) -#define tb_bits_fb1_u64_le(x) ((x)? (tb_size_t)__builtin_ffsll((tb_uint64_t)(x)) - 1 : 64) +#if TB_COMPILER_VERSION_BE(4, 1) +# define tb_bits_fb1_u32_le(x) ((x)? (tb_size_t)__builtin_ffs((tb_uint32_t)(x)) - 1 : 32) +# define tb_bits_fb1_u64_le(x) ((x)? (tb_size_t)__builtin_ffsll((tb_uint64_t)(x)) - 1 : 64) +#endif #endif diff --git a/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_x86.h b/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_x86.h index 76fc8010f..5c4fb7330 100755 --- a/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_x86.h +++ b/core/pkg/tbox.pkg/inc/tbox/utils/impl/bits_x86.h @@ -53,13 +53,13 @@ #ifdef TB_ASSEMBLER_IS_GAS // swap -static __tb_inline__ tb_uint16_t const tb_bits_swap_u16_asm(tb_uint16_t x) +static __tb_inline__ tb_uint16_t tb_bits_swap_u16_asm(tb_uint16_t x) { __tb_asm__ __tb_volatile__("rorw $8, %w0" : "+r"(x)); return x; } -static __tb_inline__ tb_uint32_t const tb_bits_swap_u32_asm(tb_uint32_t x) +static __tb_inline__ tb_uint32_t tb_bits_swap_u32_asm(tb_uint32_t x) { #if 1 __tb_asm__ __tb_volatile__("bswap %0" : "+r" (x)); @@ -76,7 +76,7 @@ static __tb_inline__ tb_uint32_t const tb_bits_swap_u32_asm(tb_uint32_t x) return x; } -static __tb_inline__ tb_hize_t const tb_bits_swap_u64_asm(tb_hize_t x) +static __tb_inline__ tb_hize_t tb_bits_swap_u64_asm(tb_hize_t x) { __tb_register__ tb_size_t esi, edi; __tb_asm__ __tb_volatile__ diff --git a/core/pkg/tbox.pkg/lib/release/linux/x86_64/libtbox.a b/core/pkg/tbox.pkg/lib/release/linux/x86_64/libtbox.a Binary files differindex ab777bf42..bd64b5a94 100755 --- a/core/pkg/tbox.pkg/lib/release/linux/x86_64/libtbox.a +++ b/core/pkg/tbox.pkg/lib/release/linux/x86_64/libtbox.a |
