text: /*
    +----------------------------------------------------------------------+
    | Swoole                                                               |
    +----------------------------------------------------------------------+
    | This source file is subject to version 2.0 of the Apache license,    |
    | that is bundled with this package in the file LICENSE, and is        |
    | available through the world-wide-web at the following url:           |
    | http://www.apache.org/licenses/LICENSE-2.0.html                      |
    | If you did not receive a copy of the Apache2.0 license and are unable|
    | to obtain it through the world-wide-web, please send a note to       |
    | license@swoole.com so we can mail you a copy immediately.            |
    +----------------------------------------------------------------------+
    | Author: Tianfeng Han  <mikan.tenny@gmail.com>                        |
    +----------------------------------------------------------------------+
  */
  
  #ifndef SWOOLE_H_
  #define SWOOLE_H_
  
  #if defined(HAVE_CONFIG_H) && !defined(COMPILE_DL_SWOOLE)
  #include "config.h"
  #elif defined(PHP_ATOM_INC) || defined(ZEND_SIGNALS)
  #include "php_config.h"
  #endif
  
  #ifdef __cplusplus
  #define SW_EXTERN_C_BEGIN extern "C" {
  #define SW_EXTERN_C_END   }
  #else
  #define SW_EXTERN_C_BEGIN
  #define SW_EXTERN_C_END
  #endif
  
  SW_EXTERN_C_BEGIN
  
  #ifndef _GNU_SOURCE
  #define _GNU_SOURCE
  #endif
  
  /*--- C standard library ---*/
  #include <assert.h>
  #include <ctype.h>
  #include <errno.h>
  #include <inttypes.h>
  #include <limits.h>
  #include <math.h>
  #include <stddef.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <stdarg.h>
  #include <signal.h>
  #include <time.h>
  
  #include <fcntl.h>
  #include <unistd.h>
  #include <pthread.h>
  #include <poll.h>
  
  #include <arpa/inet.h>
  #include <netinet/in.h>
  #include <netinet/tcp.h>
  #include <netdb.h>
  #include <sys/socket.h>
  #include <sys/time.h>
  #include <sys/select.h>
  #include <sys/mman.h>
  #include <sys/ipc.h>
  #include <sys/wait.h>
  #include <sys/un.h>
  #include <sys/types.h>
  #include <sys/utsname.h>
  #include <sys/stat.h>
  
  #if defined(HAVE_CPU_AFFINITY)
  #ifdef __FreeBSD__
  #include <sys/types.h>
  #include <sys/cpuset.h>
  #include <pthread_np.h>
  typedef cpuset_t cpu_set_t;
  #else
  #include <sched.h>
  #endif
  #endif
  
  #ifdef __MACH__
  #include <mach/clock.h>
  #include <mach/mach_time.h>
  #include <sys/sysctl.h>
  
  #define ORWL_NANO (+1.0E-9)
  #define ORWL_GIGA UINT64_C(1000000000)
  
  static double orwl_timebase = 0.0;
  static uint64_t orwl_timestart = 0;
  #ifndef HAVE_CLOCK_GETTIME
  int clock_gettime(clock_id_t which_clock, struct timespec *t);
  #endif
  #endif
  
  #if __APPLE__
  #define  daemon(nochdir, noclose)    swoole_daemon(nochdir, noclose)
  #endif
  
  /*----------------------------------------------------------------------------*/
  
  #define SWOOLE_MAJOR_VERSION      4
  #define SWOOLE_MINOR_VERSION      4
  #define SWOOLE_RELEASE_VERSION    6
  #define SWOOLE_EXTRA_VERSION      "alpha"
  #define SWOOLE_VERSION            "4.4.6-alpha"
  #define SWOOLE_VERSION_ID         40406
  #define SWOOLE_BUG_REPORT \
      "A bug occurred in Swoole-v" SWOOLE_VERSION ", please report it.\n"\
      "The Swoole developers probably don't know about it,\n"\
      "and unless you report it, chances are it won't be fixed.\n"\
      "You can read How to report a bug doc before submitting any bug reports:\n"\
      ">> https://github.com/swoole/swoole-src/issues/2000\n"\
      "Please do not send bug reports in the mailing list or personal letters.\n"\
      "The issue page is also suitable to submit feature requests.\n"
  
  /*----------------------------------------------------------------------------*/
  
  #ifndef ulong
  #define ulong unsigned long
  #endif
  typedef unsigned long ulong_t;
  
  #ifndef PRIu64
  #define PRIu64 "llu"
  #endif
  
  #ifndef PRIx64
  #define PRIx64 "llx"
  #endif
  
  #if defined(__GNUC__)
  #if __GNUC__ >= 3
  #define sw_inline inline __attribute__((always_inline))
  #else
  #define sw_inline inline
  #endif
  #elif defined(_MSC_VER)
  #define sw_inline __forceinline
  #else
  #define sw_inline inline
  #endif
  
  #if defined(__GNUC__) && __GNUC__ >= 4
  #define SW_API __attribute__ ((visibility("default")))
  #else
  #define SW_API
  #endif
  
  #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
  #define MAP_ANONYMOUS MAP_ANON
  #endif
  
  #if defined(MAP_HUGETLB) || defined(MAP_ALIGNED_SUPER)
  #define MAP_HUGE_PAGE 1
  #endif
  
  #ifndef SOCK_NONBLOCK
  #define SOCK_NONBLOCK O_NONBLOCK
  #endif
  
  #ifndef CLOCK_REALTIME
  #define CLOCK_REALTIME 0
  #endif
  
  #if !defined(__GNUC__) || __GNUC__ < 3
  #define __builtin_expect(x, expected_value) (x)
  #endif
  
  #define sw_likely(x)        __builtin_expect(!!(x), 1)
  #define sw_unlikely(x)      __builtin_expect(!!(x), 0)
  
  #define SW_START_LINE  "-------------------------START----------------------------"
  #define SW_END_LINE    "--------------------------END-----------------------------"
  #define SW_ECHO_RED               "\e[31m%s\e[0m"
  #define SW_ECHO_GREEN             "\e[32m%s\e[0m"
  #define SW_ECHO_YELLOW            "\e[33m%s\e[0m"
  #define SW_ECHO_BLUE              "\e[34m%s\e[0m"
  #define SW_ECHO_MAGENTA           "\e[35m%s\e[0m"
  #define SW_ECHO_CYAN              "\e[36m%s\e[0m"
  #define SW_ECHO_WHITE             "\e[37m%s\e[0m"
  #define SW_COLOR_RED              1
  #define SW_COLOR_GREEN            2
  #define SW_COLOR_YELLOW           3
  #define SW_COLOR_BLUE             4
  #define SW_COLOR_MAGENTA          5
  #define SW_COLOR_CYAN             6
  #define SW_COLOR_WHITE            7
  
  #define SW_SPACE                  ' '
  #define SW_CRLF                   "\r\n"
  #define SW_CRLF_LEN               2
  #define SW_ASCII_CODE_0           64
  #define SW_ASCII_CODE_Z           106
  /*----------------------------------------------------------------------------*/
  
  #include "swoole_config.h"
  #include "atomic.h"
  #include "hashmap.h"
  #include "list.h"
  #include "heap.h"
  #include "ring_queue.h"
  #include "array.h"
  #include "error.h"
  
  #define SW_MAX(A, B)           ((A) > (B) ? (A) : (B))
  #define SW_MIN(A, B)           ((A) < (B) ? (A) : (B))
  
  #ifndef MAX
  #define MAX(A, B)              SW_MAX(A, B)
  #endif
  #ifndef MIN
  #define MIN(A, B)              SW_MIN(A, B)
  #endif
  
  #ifdef SW_DEBUG
  #define SW_ASSERT(e)           assert(e)
  #define SW_ASSERT_1BYTE(v)     do { \
      size_t i = 0, n = 0; \
      for (; i < sizeof(v); i++) { \
          n += ((v >> i) & 1) ? 1 : 0; \
      } \
      assert(n == 1); \
  } while (0)
  #else
  #define SW_ASSERT(e)
  #define SW_ASSERT_1BYTE(v)
  #endif
  #define SW_START_SLEEP         usleep(100000)  //sleep 1s,wait fork and pthread_create
  
  /*-----------------------------------Memory------------------------------------*/
  
  // Evaluates to the number of elements in 'array'
  #define SW_ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
  
  #define SW_DEFAULT_ALIGNMENT   sizeof(unsigned long)
  #define SW_MEM_ALIGNED_SIZE(size) \
          SW_MEM_ALIGNED_SIZE_EX(size, SW_DEFAULT_ALIGNMENT)
  #define SW_MEM_ALIGNED_SIZE_EX(size, alignment) \
          (((size) + ((alignment) - 1LL)) & ~((alignment) - 1LL))
  
  #ifdef SW_USE_EMALLOC
  #define sw_malloc              emalloc
  #define sw_free                efree
  #define sw_calloc              ecalloc
  #define sw_realloc             erealloc
  #else
  #ifdef SW_USE_JEMALLOC
  #include <jemalloc/jemalloc.h>
  #define sw_malloc              je_malloc
  #define sw_free                je_free
  #define sw_calloc              je_calloc
  #define sw_realloc             je_realloc
  #else
  #define sw_malloc              malloc
  #define sw_free                free
  #define sw_calloc              calloc
  #define sw_realloc             realloc
  #endif
  #endif
  
  static sw_inline int sw_mem_equal(const void *v1, size_t s1, const void *v2, size_t s2)
  {
      return s1 == s2 && memcmp(v1, v2, s2) == 0;
  }
  
  /*----------------------------------String-------------------------------------*/
  
  #define SW_STRS(s)             s, sizeof(s)
  #define SW_STRL(s)             s, sizeof(s)-1
  
  #if defined(SW_USE_JEMALLOC) || defined(SW_USE_TCMALLOC)
  #define sw_strdup              swoole_strdup
  #define sw_strndup             swoole_strndup
  #else
  #define sw_strdup              strdup
  #define sw_strndup             strndup
  #endif
  
  /** always return less than size, zero termination  */
  size_t sw_snprintf(char *buf, size_t size, const char *format, ...);
  size_t sw_vsnprintf(char *buf, size_t size, const char *format, va_list args);
  
  static sw_inline char* swoole_strdup(const char *s)
  {
      size_t l = strlen(s) + 1;
      char *p = (char *) sw_malloc(l);
      if (sw_likely(p))
      {
          memcpy(p, s, l);
      }
      return p;
  }
  
  static sw_inline char* swoole_strndup(const char *s, size_t n)
  {
      char *p = (char *) sw_malloc(n + 1);
      if (sw_likely(p))
      {
          strncpy(p, s, n)[n] = '\0';
      }
      return p;
  }
  
  /*--------------------------------Constants------------------------------------*/
  enum swResult_code
  {
      SW_OK = 0,
      SW_ERR = -1,
  };
  
  enum swReturn_code
  {
      SW_CONTINUE = 1,
      SW_WAIT     = 2,
      SW_CLOSE    = 3,
      SW_ERROR    = 4,
      SW_READY    = 5,
  };
  
  enum swFd_type
  {
      SW_FD_SESSION,       //server stream session
      SW_FD_STREAM_SERVER, //server stream port
      SW_FD_DGRAM_SERVER,  //server dgram port
      SW_FD_PIPE,
      SW_FD_STREAM,
      SW_FD_AIO,
      /**
       * Coroutine Socket
       */
      SW_FD_CORO_SOCKET,
      /**
       * socket poll fd [coroutine::socket_poll]
       */
      SW_FD_CORO_POLL,
      SW_FD_SIGNAL, //signalfd
      SW_FD_DNS_RESOLVER,//dns resolver
      /**
       * c-ares
       */
      SW_FD_ARES,
      /**
       * SW_FD_USER or SW_FD_USER+n: for custom event
       */
      SW_FD_USER = 16,
      SW_FD_STREAM_CLIENT,
      SW_FD_DGRAM_CLIENT,
  };
  
  enum swBool_type
  {
      SW_TRUE = 1,
      SW_FALSE = 0,
  };
  
  enum swEvent_type
  {
      SW_EVENT_NULL   = 0,
      SW_EVENT_DEAULT = 1u << 8,
      SW_EVENT_READ   = 1u << 9,
      SW_EVENT_WRITE  = 1u << 10,
      SW_EVENT_RDWR   = SW_EVENT_READ | SW_EVENT_WRITE,
      SW_EVENT_ERROR  = 1u << 11,
      SW_EVENT_ONCE   = 1u << 12,
  };
  
  enum swPipe_type
  {
      SW_PIPE_READ  = 0,
      SW_PIPE_WRITE = 1,
  };
  
  enum swGlobal_hook_type
  {
      SW_GLOBAL_HOOK_BEFORE_SERVER_START,
      SW_GLOBAL_HOOK_BEFORE_CLIENT_START,
      SW_GLOBAL_HOOK_BEFORE_WORKER_START,
      SW_GLOBAL_HOOK_ON_CORO_START,
      SW_GLOBAL_HOOK_ON_CORO_STOP,
      SW_GLOBAL_HOOK_ON_REACTOR_CREATE,
  };
  
  enum swFork_type
  {
      SW_FORK_SPAWN   = 0,
      SW_FORK_EXEC    = 1u << 2,
  };
  
  //-------------------------------------------------------------------------------
  enum swServer_mode
  {
      SW_MODE_BASE          =  1,
      SW_MODE_PROCESS       =  2,
  };
  //-------------------------------------------------------------------------------
  enum swSocket_type
  {
      SW_SOCK_TCP          =  1,
      SW_SOCK_UDP          =  2,
      SW_SOCK_TCP6         =  3,
      SW_SOCK_UDP6         =  4,
      SW_SOCK_UNIX_DGRAM   =  5,  //unix sock dgram
      SW_SOCK_UNIX_STREAM  =  6,  //unix sock stream
  };
  #define SW_SOCK_SSL            (1u << 9)
  //-------------------------------------------------------------------------------
  enum swLog_level
  {
      SW_LOG_DEBUG = 0,
      SW_LOG_TRACE,
      SW_LOG_INFO,
      SW_LOG_NOTICE,
      SW_LOG_WARNING,
      SW_LOG_ERROR,
      SW_LOG_NONE,
  };
  //-------------------------------------------------------------------------------
  enum swFactory_dispatch_mode
  {
      SW_DISPATCH_ROUND    = 1,
      SW_DISPATCH_FDMOD    = 2,
      SW_DISPATCH_QUEUE    = 3,
      SW_DISPATCH_IPMOD    = 4,
      SW_DISPATCH_UIDMOD   = 5,
      SW_DISPATCH_USERFUNC = 6,
      SW_DISPATCH_STREAM   = 7,
  };
  
  enum swFactory_dispatch_result
  {
      SW_DISPATCH_RESULT_DISCARD_PACKET    = -1,
      SW_DISPATCH_RESULT_CLOSE_CONNECTION  = -2,
      SW_DISPATCH_RESULT_USERFUNC_FALLBACK = -3,
  };
  
  enum swWorker_status
  {
      SW_WORKER_BUSY = 1,
      SW_WORKER_IDLE = 2,
      SW_WORKER_DEL  = 3,
  };
  //-------------------------------------------------------------------------------
  
  #define swInfo(str,...) \
      if (SW_LOG_INFO >= SwooleG.log_level) {\
          size_t _sw_error_len = sw_snprintf(sw_error,SW_ERROR_MSG_SIZE,str,##__VA_ARGS__);\
          SwooleG.write_log(SW_LOG_INFO, sw_error, _sw_error_len);\
      }
  
  #define swNotice(str,...) \
      if (SW_LOG_NOTICE >= SwooleG.log_level) {\
          size_t _sw_error_len = sw_snprintf(sw_error,SW_ERROR_MSG_SIZE,str,##__VA_ARGS__);\
          SwooleG.write_log(SW_LOG_NOTICE, sw_error, _sw_error_len);\
      }
  
  #define swSysNotice(str,...) \
      do{\
          SwooleG.error = errno;\
          if (SW_LOG_ERROR >= SwooleG.log_level) {\
              size_t _sw_error_len = sw_snprintf(sw_error,SW_ERROR_MSG_SIZE,"%s(:%d): " str ", Error: %s[%d]",__func__,__LINE__,##__VA_ARGS__,strerror(errno),errno);\
              SwooleG.write_log(SW_LOG_NOTICE, sw_error, _sw_error_len);\
          }\
      } while(0)
  
  #define swWarn(str,...) \
      do{\
          if (SW_LOG_WARNING >= SwooleG.log_level) {\
              size_t _sw_error_len = sw_snprintf(sw_error,SW_ERROR_MSG_SIZE,"%s: " str,__func__,##__VA_ARGS__);\
              SwooleG.write_log(SW_LOG_WARNING, sw_error, _sw_error_len);\
          }\
      } while(0)
  
  #define swSysWarn(str,...) \
      do{\
          SwooleG.error = errno;\
          if (SW_LOG_ERROR >= SwooleG.log_level) {\
              size_t _sw_error_len = sw_snprintf(sw_error,SW_ERROR_MSG_SIZE,"%s(:%d): " str ", Error: %s[%d]",__func__,__LINE__,##__VA_ARGS__,strerror(errno),errno);\
              SwooleG.write_log(SW_LOG_WARNING, sw_error, _sw_error_len);\
          }\
      } while(0)
  
  #define swError(str,...) \
      do{\
          size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, str, ##__VA_ARGS__);\
          SwooleG.write_log(SW_LOG_ERROR, sw_error, _sw_error_len);\
          exit(1);\
      } while(0)
  
  #define swSysError(str,...) \
      do{\
          size_t _sw_error_len = sw_snprintf(sw_error,SW_ERROR_MSG_SIZE,"%s(:%d): " str ", Error: %s[%d]",__func__,__LINE__,##__VA_ARGS__,strerror(errno),errno);\
          SwooleG.write_log(SW_LOG_ERROR, sw_error, _sw_error_len);\
          exit(1);\
      } while(0)
  
  #define swFatalError(code, str,...) \
          SwooleG.fatal_error(code, str, ##__VA_ARGS__)
  
  #define swoole_error_log(level, __errno, str, ...) \
      do{\
          SwooleG.error = __errno;\
          if (level >= SwooleG.log_level){\
              size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s (ERRNO %d): " str,__func__,__errno,##__VA_ARGS__);\
              SwooleG.write_log(level, sw_error, _sw_error_len);\
          }\
      } while(0)
  
  #ifdef SW_DEBUG
  #define swDebug(str,...) \
      if (SW_LOG_DEBUG >= SwooleG.log_level) {\
          size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(:%d): " str, __func__, __LINE__, ##__VA_ARGS__);\
          SwooleG.write_log(SW_LOG_DEBUG, sw_error, _sw_error_len);\
      }
  
  #define swHexDump(data, length) \
      do { \
          const char *__data = (data); \
          size_t __length = (length); \
          swDebug("+----------+------------+-----------+-----------+------------+------------------+"); \
          for (size_t of = 0; of < __length; of += 16) \
          { \
              char hex[16 * 3 + 1]; \
              char str[16 + 1]; \
              size_t i, hof = 0, sof = 0; \
              for (i = of; i < of + 16 && i < __length; i++) \
              { \
                  hof += sprintf(hex + hof, "%02x ", (__data)[i] & 0xff); \
                  sof += sprintf(str + sof, "%c", isprint((int) (__data)[i]) ? (__data)[i] : '.'); \
              } \
              swDebug("| %08x | %-48s| %-16s |", of, hex, str); \
          } \
          swDebug("+----------+------------+-----------+-----------+------------+------------------+"); \
      } while (0)
  #else
  #define swDebug(str,...)
  #define swHexDump(data, length)
  #endif
  
  enum swTrace_type
  {
      /**
       * Server
       */
      SW_TRACE_SERVER           = 1u << 1,
      SW_TRACE_CLIENT           = 1u << 2,
      SW_TRACE_BUFFER           = 1u << 3,
      SW_TRACE_CONN             = 1u << 4,
      SW_TRACE_EVENT            = 1u << 5,
      SW_TRACE_WORKER           = 1u << 6,
      SW_TRACE_MEMORY           = 1u << 7,
      SW_TRACE_REACTOR          = 1u << 8,
      SW_TRACE_PHP              = 1u << 9,
      SW_TRACE_HTTP             = 1u << 10,
      SW_TRACE_HTTP2            = 1u << 11,
      SW_TRACE_EOF_PROTOCOL     = 1u << 12,
      SW_TRACE_LENGTH_PROTOCOL  = 1u << 13,
      SW_TRACE_CLOSE            = 1u << 14,
      SW_TRACE_WEBSOCEKT        = 1u << 15,
      /**
       * Client
       */
      SW_TRACE_REDIS_CLIENT     = 1u << 16,
      SW_TRACE_MYSQL_CLIENT     = 1u << 17,
      SW_TRACE_HTTP_CLIENT      = 1u << 18,
      SW_TRACE_AIO              = 1u << 19,
      SW_TRACE_SSL              = 1u << 20,
      SW_TRACE_NORMAL           = 1u << 21,
      /**
       * Coroutine
       */
      SW_TRACE_CHANNEL          = 1u << 22,
      SW_TRACE_TIMER            = 1u << 23,
      SW_TRACE_SOCKET           = 1u << 24,
      SW_TRACE_COROUTINE        = 1u << 25,
      SW_TRACE_CONTEXT          = 1u << 26,
      SW_TRACE_CO_HTTP_SERVER   = 1u << 27,
  
      SW_TRACE_ALL              = 0xffffffff
  };
  
  #ifdef SW_LOG_TRACE_OPEN
  #define swTraceLog(what,str,...) \
      if (SW_LOG_TRACE >= SwooleG.log_level && (what & SwooleG.trace_flags)) {\
          size_t _sw_error_len = sw_snprintf(sw_error,SW_ERROR_MSG_SIZE,"%s(:%d): " str, __func__, __LINE__, ##__VA_ARGS__);\
          SwooleG.write_log(SW_LOG_TRACE, sw_error, _sw_error_len);\
      }
  #else
  #define swTraceLog(what,str,...)
  #endif
  
  #define swTrace(str,...)       swTraceLog(SW_TRACE_NORMAL, str, ##__VA_ARGS__)
  
  #define swYield()              sched_yield() //or usleep(1)
  #define SW_MAX_FDTYPE          32 //32 kinds of event
  
  //------------------------------Base--------------------------------
  #ifndef uchar
  typedef unsigned char uchar;
  #endif
  
  #ifdef SW_USE_OPENSSL
  #include <openssl/ssl.h>
  #endif
  
  typedef void (*swDestructor)(void *data);
  typedef void (*swCallback)(void *data);
  
  typedef struct
  {
      uint32_t id;
      uint32_t fd :24;
      uint32_t reactor_id :8;
  } swSession;
  
  typedef struct _swString
  {
      size_t length;
      size_t size;
      off_t offset;
      char *str;
  } swString;
  
  typedef struct _swLinkedList_node
  {
      struct _swLinkedList_node *prev;
      struct _swLinkedList_node *next;
      ulong_t priority;
      void *data;
  } swLinkedList_node;
  
  typedef struct
  {
      uint32_t num;
      uint8_t type;
      swLinkedList_node *head;
      swLinkedList_node *tail;
      swDestructor dtor;
  } swLinkedList;
  
  typedef struct
  {
      union
      {
          struct sockaddr_in inet_v4;
          struct sockaddr_in6 inet_v6;
          struct sockaddr_un un;
      } addr;
      socklen_t len;
  } swSocketAddress;
  
  typedef struct _swSocket
  {
      int fd;
      enum swFd_type fdtype;
      enum swSocket_type socket_type;
      int events;
  
      uint8_t removed :1;
      uint8_t nonblock :1;
      uint8_t direct_send :1;
      uint8_t ssl_send :1;
      uint8_t ssl_want_read :1;
      uint8_t ssl_want_write :1;
      uint8_t dontwait :1;
      uint8_t close_wait :1;
      uint8_t send_wait :1;
      uint8_t listen_wait :1;
      uint8_t tcp_nopush :1;
      uint8_t tcp_nodelay :1;
      uint8_t skip_recv :1;
      uint8_t recv_wait :1;
  
      /**
       * memory buffer size;
       */
      uint32_t buffer_size;
  
      void *object;
  
  #ifdef SW_USE_OPENSSL
      SSL *ssl;
      uint32_t ssl_state;
  #endif
  
      swSocketAddress info;
  
      struct _swBuffer *out_buffer;
      struct _swBuffer *in_buffer;
      swString *recv_buffer;
  
  #ifdef SW_DEBUG
      size_t total_recv_bytes;
      size_t total_send_bytes;
  #endif
  
  } swSocket;
  
  typedef struct _swConnection
  {
      /**
       * file descript
       */
      int fd;
      /**
       * session id
       */
      uint32_t session_id;
      /**
       * socket type, SW_SOCK_TCP or SW_SOCK_UDP
       */
      enum swSocket_type socket_type;
      //--------------------------------------------------------------
      /**
       * is active
       * system fd must be 0. en: signalfd, listen socket
       */
      uint8_t active;
      uint8_t connect_notify;
  #ifdef SW_USE_OPENSSL
      uint8_t ssl;
      uint8_t ssl_ready;
  #endif
      //--------------------------------------------------------------
      uint8_t overflow;
      uint8_t high_watermark;
      //--------------------------------------------------------------
      uint8_t http_upgrade;
  #ifdef SW_USE_HTTP2
      uint8_t http2_stream;
  #endif
      //--------------------------------------------------------------
      /**
       * server is actively close the connection
       */
      uint8_t close_actively;
      uint8_t closed;
      uint8_t close_queued;
      uint8_t closing;
      uint8_t close_reset;
      uint8_t peer_closed;
      /**
       * protected connection, cannot be closed by heartbeat thread.
       */
      uint8_t protect;
      //--------------------------------------------------------------
      uint8_t close_notify;
      uint8_t close_force;
      //--------------------------------------------------------------
      /**
       * ReactorThread id
       */
      uint16_t reactor_id;
      /**
       * close error code
       */
      uint16_t close_errno;
      /**
       * from which socket fd
       */
      sw_atomic_t server_fd;
      /**
       * socket address
       */
      swSocketAddress info;
      /**
       * link any thing, for kernel, do not use with application.
       */
      void *object;
      /**
       * socket info
       */
      swSocket *socket;
      /**
       * connect time(seconds)
       */
      time_t connect_time;
  
      /**
       * received time with last data
       */
      time_t last_time;
  
  #ifdef SW_BUFFER_RECV_TIME
      /**
       * received time(microseconds) with last data
       */
      double last_time_usec;
  #endif
      /**
       * bind uid
       */
      uint32_t uid;
      /**
       * upgarde websocket
       */
      uint8_t websocket_status;
      /**
       * unfinished data frame
       */
      swString *websocket_buffer;
  
  #ifdef SW_USE_OPENSSL
      swString *ssl_client_cert;
      uint16_t ssl_client_cert_pid;
  #endif
      sw_atomic_t lock;
  
  } swConnection;
  
  typedef struct _swProtocol
  {
      /* one package: eof check */
      uint8_t split_by_eof;
      uint8_t package_eof_len;
      char package_eof[SW_DATA_EOF_MAXLEN + 1];
  
      char package_length_type;
      uint8_t package_length_size;
      uint16_t package_length_offset;
      uint16_t package_body_offset;
      uint32_t package_max_length;
  
      void *private_data;
      void *private_data_2;
      uint16_t real_header_length;
  
      int (*onPackage)(struct _swProtocol *, swSocket *, char *, uint32_t);
      ssize_t (*get_package_length)(struct _swProtocol *, swSocket *, char *, uint32_t);
      uint8_t (*get_package_length_size)(swSocket *);
  } swProtocol;
  
  typedef ssize_t (*swProtocol_length_function)(struct _swProtocol *, swSocket *, char *, uint32_t);
  //------------------------------String--------------------------------
  #define swoole_tolower(c)      (uchar) ((c >= 'A' && c <= 'Z') ? (c | 0x20) : c)
  #define swoole_toupper(c)      (uchar) ((c >= 'a' && c <= 'z') ? (c & ~0x20) : c)
  
  uint32_t swoole_utf8_decode(uchar **p, size_t n);
  size_t swoole_utf8_length(uchar *p, size_t n);
  void swoole_random_string(char *buf, size_t size);
  
  static sw_inline char *swoole_strlchr(char *p, char *last, char c)
  {
      while (p < last)
      {
          if (*p == c)
          {
              return p;
          }
          p++;
      }
      return NULL;
  }
  
  static sw_inline size_t swoole_size_align(size_t size, int pagesize)
  {
      return size + (pagesize - (size % pagesize));
  }
  
  #define SW_STRINGL(s)      s->str, s->length
  #define SW_STRINGS(s)      s->str, s->size
  #define SW_STRINGCVL(s)    s->str + s->offset, s->length - s->offset
  
  swString *swString_new(size_t size);
  swString *swString_dup(const char *src_str, size_t length);
  swString *swString_dup2(swString *src);
  
  void swString_print(swString *str);
  int swString_append(swString *str, swString *append_str);
  int swString_append_ptr(swString *str, const char *append_str, size_t length);
  int swString_write(swString *str, off_t offset, swString *write_str);
  int swString_write_ptr(swString *str, off_t offset, char *write_str, size_t length);
  int swString_extend(swString *str, size_t new_size);
  char* swString_alloc(swString *str, size_t __size);
  
  static sw_inline void swString_clear(swString *str)
  {
      str->length = 0;
      str->offset = 0;
  }
  
  static sw_inline void swString_free(swString *str)
  {
      sw_free(str->str);
      sw_free(str);
  }
  
  static sw_inline int swString_extend_align(swString *str, size_t _new_size)
  {
      size_t align_size = SW_MEM_ALIGNED_SIZE(str->size * 2);
      while (align_size < _new_size)
      {
          align_size *= 2;
      }
      return swString_extend(str, align_size);
  }
  
  static sw_inline int swString_grow(swString *str, size_t incr_value)
  {
      str->length += incr_value;
      if (str->length == str->size && swString_extend(str, str->size * 2) < 0)
      {
          return SW_ERR;
      }
      else
      {
          return SW_OK;
      }
  }
  
  /**
   * migrate data to head, [offset, length - offset] -> [0, length - offset]
   */
  static sw_inline void swString_pop_front(swString *str, off_t offset)
  {
      assert(offset >= 0 && (size_t ) offset <= str->length);
      if (sw_unlikely(offset == 0)) return;
      str->length = str->length - offset;
      str->offset = 0;
      if (str->length == 0) return;
      memmove(str->str, str->str + offset, str->length);
  }
  
  static sw_inline void swString_sub(swString *str, off_t start, size_t length)
  {
      char *from = str->str + start + (start >= 0 ? 0 : str->length);
      str->length = length != 0 ? length : str->length - start;
      str->offset = 0;
      if (sw_likely(str->length > 0))
      {
          memmove(str->str, from, str->length);
      }
  }
  
  //------------------------------Base--------------------------------
  enum _swEventData_flag
  {
      SW_EVENT_DATA_NORMAL,
      SW_EVENT_DATA_PTR = 1u << 1,
      SW_EVENT_DATA_CHUNK = 1u << 2,
      SW_EVENT_DATA_END = 1u << 3,
      SW_EVENT_DATA_EXIT = 1u << 4,
  };
  
  typedef struct _swDataHead
  {
      int fd;
      uint32_t len;
      int16_t reactor_id;
      uint8_t type;
      uint8_t flags;
      uint16_t server_fd;
  #ifdef SW_BUFFER_RECV_TIME
      double time;
  #endif
  } swDataHead;
  
  typedef struct _swEvent
  {
      int fd;
      int16_t reactor_id;
      enum swFd_type type;
      swSocket *socket;
  } swEvent;
  
  typedef struct
  {
      swDataHead info;
      char data[SW_IPC_BUFFER_SIZE];
  } swEventData;
  
  typedef struct
  {
      swDataHead info;
      char data[0];
  } swPipeBuffer;
  
  typedef struct _swDgramPacket
  {
      swSocketAddress info;
      uint32_t length;
      char data[0];
  } swDgramPacket;
  
  typedef struct _swSendData
  {
      swDataHead info;
      char *data;
  } swSendData;
  
  typedef struct
  {
      off_t offset;
      size_t length;
      char filename[0];
  } swSendFile_request;
  
  typedef void (*swSignalHandler)(int);
  typedef struct _swReactor swReactor;
  
  typedef int (*swReactor_handler)(swReactor *reactor, swEvent *event);
  //------------------Pipe--------------------
  typedef struct _swPipe
  {
      void *object;
      int blocking;
      double timeout;
  
      int (*read)(struct _swPipe *, void *recv, int length);
      int (*write)(struct _swPipe *, void *send, int length);
      int (*getFd)(struct _swPipe *, int master);
      int (*close)(struct _swPipe *);
  } swPipe;
  
  enum swPipe_close_which
  {
      SW_PIPE_CLOSE_MASTER = 1,
      SW_PIPE_CLOSE_WORKER = 2,
      SW_PIPE_CLOSE_READ   = 3,
      SW_PIPE_CLOSE_WRITE  = 4,
      SW_PIPE_CLOSE_BOTH   = 0,
  };
  
  int swPipeBase_create(swPipe *p, int blocking);
  int swPipeEventfd_create(swPipe *p, int blocking, int semaphore, int timeout);
  int swPipeUnsock_create(swPipe *p, int blocking, int protocol);
  int swPipeUnsock_close_ext(swPipe *p, int which);
  
  static inline int swPipeNotify_auto(swPipe *p, int blocking, int semaphore)
  {
  #ifdef HAVE_EVENTFD
      return swPipeEventfd_create(p, blocking, semaphore, 0);
  #else
      return swPipeBase_create(p, blocking);
  #endif
  }
  
  //------------------Queue--------------------
  typedef struct _swQueue_Data
  {
      long mtype; /* type of received/sent message */
      char mdata[sizeof(swEventData)]; /* text of the message */
  } swQueue_data;
  
  typedef struct _swMsgQueue
  {
      int blocking;
      int msg_id;
      int flags;
      int perms;
  } swMsgQueue;
  
  int swMsgQueue_create(swMsgQueue *q, int blocking, key_t msg_key, int perms);
  void swMsgQueue_set_blocking(swMsgQueue *q, uint8_t blocking);
  int swMsgQueue_set_capacity(swMsgQueue *q, int queue_bytes);
  int swMsgQueue_push(swMsgQueue *q, swQueue_data *in, int data_length);
  int swMsgQueue_pop(swMsgQueue *q, swQueue_data *out, int buffer_length);
  int swMsgQueue_stat(swMsgQueue *q, int *queue_num, int *queue_bytes);
  int swMsgQueue_free(swMsgQueue *q);
  //------------------Lock--------------------------------------
  enum SW_LOCKS
  {
      SW_RWLOCK = 1,
      SW_FILELOCK = 2,
      SW_MUTEX = 3,
      SW_SEM = 4,
      SW_SPINLOCK = 5,
      SW_ATOMLOCK = 6,
  };
  
  enum swDNSLookup_cache_type
  {
      SW_DNS_LOOKUP_RANDOM  = (1u << 11),
  };
  
  typedef struct
  {
      const char *hostname;
      const char *service;
      int family;
      int socktype;
      int protocol;
      int error;
      void *result;
      int count;
  } swRequest_getaddrinfo;
  
  typedef struct _swMutex
  {
      pthread_mutex_t _lock;
      pthread_mutexattr_t attr;
  } swMutex;
  
  typedef struct _swFileLock
  {
      struct flock lock_t;
      int fd;
  } swFileLock;
  
  #ifdef HAVE_RWLOCK
  typedef struct _swRWLock
  {
      pthread_rwlock_t _lock;
      pthread_rwlockattr_t attr;
  
  } swRWLock;
  
  #ifdef HAVE_SPINLOCK
  typedef struct _swSpinLock
  {
      pthread_spinlock_t lock_t;
  } swSpinLock;
  #endif
  
  typedef struct _swAtomicLock
  {
      sw_atomic_t lock_t;
      uint32_t spin;
  } swAtomicLock;
  
  typedef struct _swSem
  {
      key_t key;
      int semid;
  } swSem;
  #endif
  
  typedef struct _swLock
  {
      int type;
      union
      {
          swMutex mutex;
  #ifdef HAVE_RWLOCK
          swRWLock rwlock;
  #endif
  #ifdef HAVE_SPINLOCK
          swSpinLock spinlock;
  #endif
          swFileLock filelock;
          swSem sem;
          swAtomicLock atomlock;
      } object;
  
      int (*lock_rd)(struct _swLock *);
      int (*lock)(struct _swLock *);
      int (*unlock)(struct _swLock *);
      int (*trylock_rd)(struct _swLock *);
      int (*trylock)(struct _swLock *);
      int (*free)(struct _swLock *);
  } swLock;
  
  
  //Thread Condition
  typedef struct _swCond
  {
      swLock _lock;
      pthread_cond_t _cond;
  
      int (*wait)(struct _swCond *object);
      int (*timewait)(struct _swCond *object, long, long);
      int (*notify)(struct _swCond *object);
      int (*broadcast)(struct _swCond *object);
      void (*free)(struct _swCond *object);
      int (*lock)(struct _swCond *object);
      int (*unlock)(struct _swCond *object);
  } swCond;
  
  #define SW_SHM_MMAP_FILE_LEN  64
  
  typedef struct _swShareMemory_mmap
  {
      size_t size;
      char mapfile[SW_SHM_MMAP_FILE_LEN];
      int tmpfd;
      int key;
      int shmid;
      void *mem;
  } swShareMemory;
  
  void *swShareMemory_mmap_create(swShareMemory *object, size_t size, char *mapfile);
  void *swShareMemory_sysv_create(swShareMemory *object, size_t size, int key);
  int swShareMemory_sysv_free(swShareMemory *object, int rm);
  int swShareMemory_mmap_free(swShareMemory *object);
  
  //-------------------memory manager-------------------------
  typedef struct _swMemoryPool
  {
      void *object;
      void* (*alloc)(struct _swMemoryPool *pool, uint32_t size);
      void (*free)(struct _swMemoryPool *pool, void *ptr);
      void (*destroy)(struct _swMemoryPool *pool);
  } swMemoryPool;
  
  typedef struct _swFixedPool_slice
  {
      uint8_t lock;
      struct _swFixedPool_slice *next;
      struct _swFixedPool_slice *pre;
      char data[0];
  
  } swFixedPool_slice;
  
  typedef struct _swFixedPool
  {
      void *memory;
      size_t size;
  
      swFixedPool_slice *head;
      swFixedPool_slice *tail;
  
      /**
       * total memory size
       */
      uint32_t slice_num;
  
      /**
       * memory usage
       */
      uint32_t slice_use;
  
      /**
       * Fixed slice size, not include the memory used by swFixedPool_slice
       */
      uint32_t slice_size;
  
      /**
       * use shared memory
       */
      uint8_t shared;
  
  } swFixedPool;
  /**
   * FixedPool, random alloc/free fixed size memory
   */
  swMemoryPool* swFixedPool_new(uint32_t slice_num, uint32_t slice_size, uint8_t shared);
  swMemoryPool* swFixedPool_new2(uint32_t slice_size, void *memory, size_t size);
  swMemoryPool* swMalloc_new();
  
  /**
   * RingBuffer, In order for malloc / free
   */
  swMemoryPool *swRingBuffer_new(uint32_t size, uint8_t shared);
  
  /**
   * Global memory, the program life cycle only malloc / free one time
   */
  swMemoryPool* swMemoryGlobal_new(uint32_t pagesize, uint8_t shared);
  
  void swFixedPool_debug(swMemoryPool *pool);
  
  /**
   * alloc shared memory
   */
  void* sw_shm_malloc(size_t size);
  void sw_shm_free(void *ptr);
  void* sw_shm_calloc(size_t num, size_t _size);
  int sw_shm_protect(void *addr, int flags);
  void* sw_shm_realloc(void *ptr, size_t new_size);
  
  #ifdef HAVE_RWLOCK
  int swRWLock_create(swLock *lock, int use_in_process);
  #endif
  #ifdef SEM_UNDO
  int swSem_create(swLock *lock, key_t key);
  #endif
  int swFileLock_create(swLock *lock, int fd);
  #ifdef HAVE_SPINLOCK
  int swSpinLock_create(swLock *object, int spin);
  #endif
  int swAtomicLock_create(swLock *object, int spin);
  
  int swMutex_create(swLock *lock, int use_in_process);
  int swMutex_lockwait(swLock *lock, int timeout_msec);
  int swCond_create(swCond *cond);
  
  typedef struct _swThreadParam
  {
      void *object;
      int pti;
  } swThreadParam;
  
  
  #ifdef __MACH__
  char* sw_error_();
  #define sw_error     sw_error_()
  #else
  extern __thread char sw_error[SW_ERROR_MSG_SIZE];
  #endif
  
  enum swProcess_type
  {
      SW_PROCESS_MASTER     = 1,
      SW_PROCESS_WORKER     = 2,
      SW_PROCESS_MANAGER    = 3,
      SW_PROCESS_TASKWORKER = 4,
      SW_PROCESS_USERWORKER = 5,
  };
  
  #define swIsMaster()          (SwooleG.process_type==SW_PROCESS_MASTER)
  #define swIsWorker()          (SwooleG.process_type==SW_PROCESS_WORKER)
  #define swIsTaskWorker()      (SwooleG.process_type==SW_PROCESS_TASKWORKER)
  #define swIsManager()         (SwooleG.process_type==SW_PROCESS_MANAGER)
  #define swIsUserWorker()      (SwooleG.process_type==SW_PROCESS_USERWORKER)
  
  //----------------------Logger---------------------
  int swLog_init(char *logfile);
  void swLog_put(int level, char *content, size_t length);
  void swLog_reopen(enum swBool_type redirect);
  void swLog_free(void);
  
  //----------------------Tool Function---------------------
  uint64_t swoole_hash_key(char *str, int str_len);
  uint32_t swoole_common_multiple(uint32_t u, uint32_t v);
  uint32_t swoole_common_divisor(uint32_t u, uint32_t v);
  
  extern void swoole_sha1(const char *str, int _len, unsigned char *digest);
  extern void swoole_sha256(const char *str, int _len, unsigned char *digest);
  
  static sw_inline uint16_t swoole_swap_endian16(uint16_t x)
  {
      return (((x & 0xff) << 8) | ((x & 0xff00) >> 8));
  }
  
  static sw_inline uint32_t swoole_swap_endian32(uint32_t x)
  {
      return (((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24));
  }
  
  static sw_inline int32_t swoole_unpack(char type, const void *data)
  {
      switch(type)
      {
      /*-------------------------16bit-----------------------------*/
      case 'c':
          return *((int8_t *) data);
      case 'C':
          return *((uint8_t *) data);
      /*-------------------------16bit-----------------------------*/
      /**
       * signed short (always 16 bit, machine byte order)
       */
      case 's':
          return *((int16_t *) data);
      /**
       * unsigned short (always 16 bit, machine byte order)
       */
      case 'S':
          return *((uint16_t *) data);
      /**
       * unsigned short (always 16 bit, big endian byte order)
       */
      case 'n':
          return ntohs(*((uint16_t *) data));
      /**
       * unsigned short (always 32 bit, little endian byte order)
       */
      case 'v':
          return swoole_swap_endian16(ntohs(*((uint16_t *) data)));
  
      /*-------------------------32bit-----------------------------*/
      /**
       * unsigned long (always 32 bit, machine byte order)
       */
      case 'L':
          return *((uint32_t *) data);
      /**
       * signed long (always 32 bit, machine byte order)
       */
      case 'l':
          return *((int *) data);
      /**
       * unsigned long (always 32 bit, big endian byte order)
       */
      case 'N':
          return ntohl(*((uint32_t *) data));
      /**
       * unsigned short (always 32 bit, little endian byte order)
       */
      case 'V':
          return swoole_swap_endian32(ntohl(*((uint32_t *) data)));
  
      default:
          return *((uint32_t *) data);
      }
  }
  
  static inline char* swoole_strnstr(const char *haystack, const char *needle, uint32_t length)
  {
      int i;
      uint32_t needle_length = strlen(needle);
      assert(needle_length > 0);
  
      for (i = 0; i < (int) (length - needle_length + 1); i++)
      {
          if ((haystack[0] == needle[0]) && (0 == memcmp(haystack, needle, needle_length)))
          {
              return (char *) haystack;
          }
          haystack++;
      }
  
      return NULL;
  }
  
  static inline int swoole_strnpos(const char *haystack, uint32_t haystack_length, const char *needle, uint32_t needle_length)
  {
      assert(needle_length > 0);
      uint32_t i;
  
      if (sw_likely(needle_length <= haystack_length))
      {
          for (i = 0; i < haystack_length - needle_length + 1; i++)
          {
              if ((haystack[0] == needle[0]) && (0 == memcmp(haystack, needle, needle_length)))
              {
                  return i;
              }
              haystack++;
          }
      }
  
      return -1;
  }
  
  static inline int swoole_strrnpos(const char *haystack, const char *needle, uint32_t length)
  {
      uint32_t needle_length = strlen(needle);
      assert(needle_length > 0);
      uint32_t i;
      haystack += (length - needle_length);
  
      for (i = length - needle_length; i > 0; i--)
      {
          if ((haystack[0] == needle[0]) && (0 == memcmp(haystack, needle, needle_length)))
          {
              return i;
          }
          haystack--;
      }
  
      return -1;
  }
  
  static inline void swoole_strtolower(char *str, int length)
  {
      char *c, *e;
  
      c = str;
      e = c + length;
  
      while (c < e)
      {
          *c = tolower(*c);
          c++;
      }
  }
  
  int swoole_itoa(char *buf, long value);
  void swoole_dump_ascii(const char *data, size_t size);
  void swoole_dump_bin(const char *data, char type, size_t size);
  void swoole_dump_hex(const char *data, size_t outlen);
  int swoole_type_size(char type);
  int swoole_mkdir_recursive(const char *dir);
  char* swoole_dirname(char *file);
  size_t swoole_sync_writefile(int fd, const void *data, size_t len);
  size_t swoole_sync_readfile(int fd, void *buf, size_t len);
  swString* swoole_sync_readfile_eof(int fd);
  int swoole_rand(int min, int max);
  int swoole_system_random(int min, int max);
  long swoole_file_get_size(FILE *fp);
  int swoole_tmpfile(char *filename);
  swString* swoole_file_get_contents(const char *filename);
  int swoole_file_put_contents(const char *filename, const char *content, size_t length);
  long swoole_file_size(const char *filename);
  char *swoole_dec2hex(int value, int base);
  int swoole_version_compare(const char *version1, const char *version2);
  #ifdef HAVE_EXECINFO
  void swoole_print_trace(void);
  #endif
  int swoole_ioctl_set_block(int sock, int nonblock);
  int swoole_fcntl_set_option(int sock, int nonblock, int cloexec);
  int swoole_gethostbyname(int type, const char *name, char *addr);
  int swoole_getaddrinfo(swRequest_getaddrinfo *req);
  char* swoole_string_format(size_t n, const char *format, ...);
  //----------------------core function---------------------
  int swSocket_set_timeout(int sock, double timeout);
  int swSocket_create_server(int type, const char *address, int port, int backlog);
  //----------------------------------------Socket---------------------------------------
  static sw_inline int swSocket_is_dgram(uint8_t type)
  {
      return (type == SW_SOCK_UDP || type == SW_SOCK_UDP6 || type == SW_SOCK_UNIX_DGRAM);
  }
  
  static sw_inline int swSocket_is_stream(uint8_t type)
  {
      return (type == SW_SOCK_TCP || type == SW_SOCK_TCP6 || type == SW_SOCK_UNIX_STREAM);
  }
  
  void swoole_init(void);
  void swoole_clean(void);
  pid_t swoole_fork(int flags);
  double swoole_microtime(void);
  void swoole_rtrim(char *str, int len);
  void swoole_redirect_stdout(int new_fd);
  int swoole_shell_exec(const char *command, pid_t *pid, uint8_t get_error_stream);
  int swoole_daemon(int nochdir, int noclose);
  
  SW_API int swoole_add_function(const char *name, void* func);
  SW_API void* swoole_get_function(const char *name, uint32_t length);
  SW_API int swoole_add_hook(enum swGlobal_hook_type type, swCallback func, int push_back);
  SW_API void swoole_call_hook(enum swGlobal_hook_type type, void *arg);
  
  static sw_inline uint64_t swoole_hton64(uint64_t host)
  {
      uint64_t ret = 0;
      uint32_t high, low;
  
      low = host & 0xFFFFFFFF;
      high = (host >> 32) & 0xFFFFFFFF;
      low = htonl(low);
      high = htonl(high);
  
      ret = low;
      ret <<= 32;
      ret |= high;
      return ret;
  }
  
  static sw_inline uint64_t swoole_ntoh64(uint64_t net)
  {
      uint64_t ret = 0;
      uint32_t high, low;
  
      low = net & 0xFFFFFFFF;
      high = (net >> 32) & 0xFFFFFFFF;
      low = ntohl(low);
      high = ntohl(high);
      ret = low;
      ret <<= 32;
      ret |= high;
      return ret;
  }
  
  int swSocket_create(int type);
  int swSocket_bind(int sock, int type, const char *host, int *port);
  int swSocket_accept(int fd, swSocketAddress *sa);
  int swSocket_wait(int fd, int timeout_ms, int events);
  int swSocket_wait_multi(int *list_of_fd, int n_fd, int timeout_ms, int events);
  void swSocket_clean(int fd);
  ssize_t swSocket_sendto_blocking(int fd, const void *buf, size_t n, int flag, struct sockaddr *addr, socklen_t addr_len);
  int swSocket_set_buffer_size(int fd, uint32_t buffer_size);
  ssize_t swSocket_udp_sendto(int server_sock, const char *dst_ip, int dst_port, const char *data, uint32_t len);
  ssize_t swSocket_udp_sendto6(int server_sock, const char *dst_ip, int dst_port, const char *data, uint32_t len);
  ssize_t swSocket_unix_sendto(int server_sock, const char *dst_path, const char *data, uint32_t len);
  int swSocket_sendfile_sync(int sock, const char *filename, off_t offset, size_t length, double timeout);
  int swSocket_write_blocking(int __fd, const void *__data, int __len);
  int swSocket_recv_blocking(int fd, void *__data, size_t __len, int flags);
  
  static sw_inline int swSocket_set_nonblock(int sock)
  {
      return swoole_fcntl_set_option(sock, 1, -1);
  }
  
  static sw_inline int swSocket_set_blocking(int sock)
  {
      return swoole_fcntl_set_option(sock, 0, -1);
  }
  
  static sw_inline int swoole_waitpid(pid_t __pid, int *__stat_loc, int __options)
  {
      int ret;
      do
      {
          ret = waitpid(__pid, __stat_loc, __options);
      } while (ret < 0 && errno == EINTR);
      return ret;
  }
  
  static sw_inline int swoole_kill(pid_t __pid, int __sig)
  {
      if (__pid <= 0)
      {
          return -1;
      }
      return kill(__pid, __sig);
  }
  
  #ifdef TCP_CORK
  #define HAVE_TCP_NOPUSH
  static sw_inline int swSocket_tcp_nopush(int sock, int nopush)
  {
      return setsockopt(sock, IPPROTO_TCP, TCP_CORK, (const void *) &nopush, sizeof(int));
  }
  #else
  #define swSocket_tcp_nopush(sock, nopush)
  #endif
  
  swSignalHandler swSignal_set(int sig, swSignalHandler func, int restart, int mask);
  void swSignal_add(int signo, swSignalHandler func);
  void swSignal_callback(int signo);
  swSignalHandler swSignal_get_handler(int signo);
  void swSignal_clear(void);
  void swSignal_none(void);
  char* swSignal_str(int sig);
  
  #ifdef HAVE_SIGNALFD
  void swSignalfd_init();
  int swSignalfd_setup(swReactor *reactor);
  #endif
  
  typedef struct _swDefer_callback
  {
      struct _swDefer_callback *next, *prev;
      swCallback callback;
      void *data;
  } swDefer_callback;
  
  struct _swReactor
  {
      void *object;
      void *ptr;  //reserve
  
      /**
       * last signal number
       */
      int singal_no;
  
      uint32_t event_num;
      uint32_t max_event_num;
      uint32_t signal_listener_num;
  
      uint32_t check_timer :1;
      uint32_t running :1;
      uint32_t start :1;
      uint32_t once :1;
      uint32_t wait_exit :1;
      /**
       * disable accept new connection
       */
      uint32_t disable_accept :1;
      /**
       * callback signal
       */
      uint32_t check_signalfd :1;
      /**
       * reactor->wait timeout (millisecond) or -1
       */
      int32_t timeout_msec;
  
      uint16_t id; //Reactor ID
      uint16_t flag; //flag
  
      uint32_t max_socket;
  
      swArray *socket_array;
  
  #ifdef SW_USE_MALLOC_TRIM
      time_t last_malloc_trim_time;
  #endif
  
      swReactor_handler read_handler[SW_MAX_FDTYPE];
      swReactor_handler write_handler[SW_MAX_FDTYPE];
      swReactor_handler error_handler[SW_MAX_FDTYPE];
  
      swReactor_handler default_write_handler;
      swReactor_handler default_error_handler;
  
      struct _swTimer *timer;
  
      int (*add)(swReactor *, int fd, int fdtype);
      int (*set)(swReactor *, int fd, int fdtype);
      int (*del)(swReactor *, int fd);
      int (*wait)(swReactor *, struct timeval *);
      void (*free)(swReactor *);
  
      void *defer_tasks;
      void *destroy_callbacks;
  
      swDefer_callback idle_task;
      swDefer_callback future_task;
  
      void (*onTimeout)(swReactor *);
      void (*onFinish)(swReactor *);
      void (*onBegin)(swReactor *);
  
      void (*enable_accept)(swReactor *);
      int (*is_empty)(swReactor *);
  
      int (*write)(swReactor *, int, const void *, int);
      int (*close)(swReactor *, int);
      void (*defer)(swReactor *, swCallback, void *);
  };
  
  typedef struct _swWorker swWorker;
  typedef struct _swThread swThread;
  typedef struct _swProcessPool swProcessPool;
  
  struct _swWorker
  {
      /**
       * worker process
       */
      pid_t pid;
  
      /**
       * worker thread
       */
      pthread_t tid;
  
      swProcessPool *pool;
  
      swMemoryPool *pool_output;
  
      swMsgQueue *queue;
  
      /**
       * redirect stdout to pipe_master
       */
      uint8_t redirect_stdout :1;
  
      /**
       * redirect stdin to pipe_worker
       */
      uint8_t redirect_stdin :1;
  
      /**
       * redirect stderr to pipe_worker
       */
      uint8_t redirect_stderr :1;
  
      /**
       * worker status, IDLE or BUSY
       */
      uint8_t status;
      uint8_t type;
      uint8_t ipc_mode;
      uint8_t child_process;
  
      uint8_t traced;
      void (*tracer)(struct _swWorker *);
  
      /**
       * tasking num
       */
      sw_atomic_t tasking_num;
  
      time_t start_time;
      time_t request_time;
  
      long dispatch_count;
      long request_count;
  
      /**
       * worker id
       */
      uint32_t id;
  
      swLock lock;
  
      swPipe *pipe_object;
  
      int pipe_master;
      int pipe_worker;
  
      int pipe;
      void *ptr;
      void *ptr2;
  };
  
  typedef struct
  {
      int socket;
      int last_connection;
      char *socket_file;
      swString *response_buffer;
  } swStreamInfo;
  
  struct _swProcessPool
  {
      /**
       * reloading
       */
      uint8_t reloading;
      uint8_t reload_init;
      uint8_t dispatch_mode;
      uint8_t ipc_mode;
      uint8_t started;
      uint32_t reload_worker_i;
      uint32_t max_wait_time;
      swWorker *reload_workers;
  
      /**
       * process type
       */
      uint8_t type;
  
      /**
       * worker->id = start_id + i
       */
      uint16_t start_id;
  
      /**
       * use message queue IPC
       */
      uint8_t use_msgqueue;
  
      /**
       * use stream socket IPC
       */
      uint8_t use_socket;
  
      char *packet_buffer;
      uint32_t max_packet_size;
  
      /**
       * message queue key
       */
      key_t msgqueue_key;
  
  
      uint32_t worker_num;
      uint32_t max_request;
      uint32_t max_request_grace;
  
      int (*onTask)(struct _swProcessPool *pool, swEventData *task);
  
      void (*onWorkerStart)(struct _swProcessPool *pool, int worker_id);
      void (*onMessage)(struct _swProcessPool *pool, char *data, uint32_t length);
      void (*onWorkerStop)(struct _swProcessPool *pool, int worker_id);
  
      int (*main_loop)(struct _swProcessPool *pool, swWorker *worker);
      int (*onWorkerNotFound)(struct _swProcessPool *pool, pid_t pid, int status);
  
      sw_atomic_t round_id;
  
      swWorker *workers;
      swPipe *pipes;
      swHashMap *map;
      swReactor *reactor;
      swMsgQueue *queue;
      swStreamInfo *stream;
  
      void *ptr;
      void *ptr2;
  };
  
  //----------------------------------------Reactor---------------------------------------
  static sw_inline int swReactor_error(swReactor *reactor)
  {
      switch (errno)
      {
      case EINTR:
          return SW_OK;
      }
      return SW_ERR;
  }
  
  static sw_inline int swReactor_event_read(int fdtype)
  {
      return (fdtype < SW_EVENT_DEAULT) || (fdtype & SW_EVENT_READ);
  }
  
  static sw_inline int swReactor_event_write(int fdtype)
  {
      return fdtype & SW_EVENT_WRITE;
  }
  
  static sw_inline int swReactor_event_error(int fdtype)
  {
      return fdtype & SW_EVENT_ERROR;
  }
  
  static sw_inline enum swFd_type swReactor_fdtype(int flags)
  {
      return (enum swFd_type) (flags & (~SW_EVENT_READ) & (~SW_EVENT_WRITE) & (~SW_EVENT_ERROR) & (~SW_EVENT_ONCE));
  }
  
  static sw_inline int swReactor_events(int flags)
  {
      int events = 0;
      if (swReactor_event_read(flags))
      {
          events |= SW_EVENT_READ;
      }
      if (swReactor_event_write(flags))
      {
          events |= SW_EVENT_WRITE;
      }
      if (swReactor_event_error(flags))
      {
          events |= SW_EVENT_ERROR;
      }
      if (flags & SW_EVENT_ONCE)
      {
          events |= SW_EVENT_ONCE;
      }
      return events;
  }
  
  int swReactor_create(swReactor *reactor, int max_event);
  void swReactor_destroy(swReactor *reactor);
  void swReactor_add_destroy_callback(swReactor *reactor, swCallback cb, void *data);
  
  static inline void swReactor_before_wait(swReactor *reactor)
  {
      reactor->running = 1;
      reactor->start = 1;
  }
  
  #define SW_REACTOR_CONTINUE   if (reactor->once) {break;} else {continue;}
  
  int swReactor_empty(swReactor *reactor);
  swSocket* swReactor_get(swReactor *reactor, int fd);
  
  static sw_inline int swReactor_isset_handler(swReactor *reactor, int fdtype)
  {
      return reactor->read_handler[fdtype] != NULL;
  }
  
  static sw_inline void swReactor_add(swReactor *reactor, int fd, int fdtype)
  {
      swSocket *_socket = swReactor_get(reactor, fd);
      _socket->fd = fd;
      _socket->fdtype = swReactor_fdtype(fdtype);
      _socket->events = swReactor_events(fdtype);
      _socket->removed = 0;
  }
  
  static sw_inline void swReactor_set(swReactor *reactor, int fd, int type)
  {
      swSocket *_socket = swReactor_get(reactor, fd);
      _socket->events = swReactor_events(type);
  }
  
  static sw_inline void swReactor_del(swReactor *reactor, int fd)
  {
      swSocket *_socket = swReactor_get(reactor, fd);
      _socket->events = 0;
      _socket->removed = 1;
  }
  
  static sw_inline int swReactor_exists(swReactor *reactor, int fd)
  {
      swSocket *_socket = swReactor_get(reactor, fd);
      return !_socket->removed && _socket->events;
  }
  
  static sw_inline int swReactor_get_timeout_msec(swReactor *reactor)
  {
      return reactor->defer_tasks ? 0 : reactor->timeout_msec;
  }
  
  int swReactor_onWrite(swReactor *reactor, swEvent *ev);
  int swReactor_close(swReactor *reactor, int fd);
  int swReactor_write(swReactor *reactor, int fd, const void *buf, int n);
  int swReactor_wait_write_buffer(swReactor *reactor, int fd);
  void swReactor_activate_future_task(swReactor *reactor);
  
  static sw_inline int swReactor_add_event(swReactor *reactor, int fd, enum swEvent_type event_type)
  {
      swSocket *_socket = swReactor_get(reactor, fd);
      if (!(_socket->events & event_type))
      {
          return reactor->set(reactor, fd, _socket->fdtype | _socket->events | event_type);
      }
      return SW_OK;
  }
  
  static sw_inline int swReactor_del_event(swReactor *reactor, int fd, enum swEvent_type event_type)
  {
      swSocket *_socket = swReactor_get(reactor, fd);
      if (_socket->events & event_type)
      {
          return reactor->set(reactor, fd, _socket->fdtype | (_socket->events & (~event_type)));
      }
      return SW_OK;
  }
  
  static sw_inline int swReactor_remove_read_event(swReactor *reactor, int fd)
  {
      swSocket *_socket = swReactor_get(reactor, fd);
      if (_socket->events & SW_EVENT_WRITE)
      {
          _socket->events &= (~SW_EVENT_READ);
          return reactor->set(reactor, fd, _socket->fdtype | _socket->events);
      }
      else
      {
          return reactor->del(reactor, fd);
      }
  }
  
  static sw_inline int swReactor_remove_write_event(swReactor *reactor, int fd)
  {
      swSocket *_socket = swReactor_get(reactor, fd);
      if (_socket->events & SW_EVENT_READ)
      {
          _socket->events &= (~SW_EVENT_WRITE);
          return reactor->set(reactor, fd, _socket->fdtype | _socket->events);
      }
      else
      {
          return reactor->del(reactor, fd);
      }
  }
  
  static sw_inline swReactor_handler swReactor_get_handler(swReactor *reactor, enum swEvent_type event_type, enum swFd_type fdtype)
  {
      switch(event_type)
      {
      case SW_EVENT_READ:
          return reactor->read_handler[fdtype];
      case SW_EVENT_WRITE:
          return (reactor->write_handler[fdtype] != NULL) ? reactor->write_handler[fdtype] : reactor->default_write_handler;
      case SW_EVENT_ERROR:
          return (reactor->error_handler[fdtype] != NULL) ? reactor->error_handler[fdtype] : reactor->default_error_handler;
      default:
          abort();
          break;
      }
      return NULL;
  }
  
  int swReactor_set_handler(swReactor *, int, swReactor_handler);
  
  static sw_inline int swReactor_trigger_close_event(swReactor *reactor, swEvent *event)
  {
      return reactor->default_error_handler(reactor, event);
  }
  
  int swReactorEpoll_create(swReactor *reactor, int max_event_num);
  int swReactorPoll_create(swReactor *reactor, int max_event_num);
  int swReactorKqueue_create(swReactor *reactor, int max_event_num);
  int swReactorSelect_create(swReactor *reactor);
  
  /*----------------------------Process Pool-------------------------------*/
  int swProcessPool_create(swProcessPool *pool, uint32_t worker_num, key_t msgqueue_key, int ipc_mode);
  int swProcessPool_create_unix_socket(swProcessPool *pool, char *socket_file, int blacklog);
  int swProcessPool_create_tcp_socket(swProcessPool *pool, char *host, int port, int blacklog);
  int swProcessPool_set_protocol(swProcessPool *pool, int task_protocol, uint32_t max_packet_size);
  void swProcessPool_set_max_request(swProcessPool *pool, uint32_t max_request, uint32_t max_request_grace);
  int swProcessPool_wait(swProcessPool *pool);
  int swProcessPool_start(swProcessPool *pool);
  void swProcessPool_shutdown(swProcessPool *pool);
  pid_t swProcessPool_spawn(swProcessPool *pool, swWorker *worker);
  int swProcessPool_dispatch(swProcessPool *pool, swEventData *data, int *worker_id);
  int swProcessPool_response(swProcessPool *pool, char *data, int length);
  int swProcessPool_dispatch_blocking(swProcessPool *pool, swEventData *data, int *dst_worker_id);
  int swProcessPool_add_worker(swProcessPool *pool, swWorker *worker);
  int swProcessPool_del_worker(swProcessPool *pool, swWorker *worker);
  int swProcessPool_get_max_request(swProcessPool *pool);
  
  static sw_inline void swProcessPool_set_start_id(swProcessPool *pool, int start_id)
  {
      int i;
      pool->start_id = start_id;
      for (i = 0; i < pool->worker_num; i++)
      {
          pool->workers[i].id = pool->start_id + i;
      }
  }
  
  static sw_inline void swProcessPool_set_type(swProcessPool *pool, int type)
  {
      int i;
      pool->type = type;
      for (i = 0; i < pool->worker_num; i++)
      {
          pool->workers[i].type = type;
      }
  }
  
  static sw_inline swWorker* swProcessPool_get_worker(swProcessPool *pool, int worker_id)
  {
      return &(pool->workers[worker_id - pool->start_id]);
  }
  
  //-----------------------------Channel---------------------------
  enum swChannel_flag
  {
      SW_CHAN_LOCK     = 1u << 1,
      SW_CHAN_NOTIFY   = 1u << 2,
      SW_CHAN_SHM      = 1u << 3,
  };
  
  typedef struct _swChannel
  {
      off_t head;
      off_t tail;
      size_t size;
      char head_tag;
      char tail_tag;
      int num;
      int max_num;
      /**
       * Data length, excluding structure
       */
      size_t bytes;
      int flag;
      int maxlen;
      /**
       * memory point
       */
      void *mem;
      swLock lock;
      swPipe notify_fd;
  } swChannel;
  
  swChannel* swChannel_new(size_t size, int maxlen, int flag);
  #define swChannel_empty(ch) (ch->num == 0)
  #define swChannel_full(ch) ((ch->head == ch->tail && ch->tail_tag != ch->head_tag) || (ch->bytes + sizeof(int) * ch->num == ch->size))
  int swChannel_pop(swChannel *object, void *out, int buffer_length);
  int swChannel_push(swChannel *object, void *in, int data_length);
  int swChannel_out(swChannel *object, void *out, int buffer_length);
  int swChannel_in(swChannel *object, void *in, int data_length);
  int swChannel_peek(swChannel *object, void *out, int buffer_length);
  int swChannel_wait(swChannel *object);
  int swChannel_notify(swChannel *object);
  void swChannel_free(swChannel *object);
  void swChannel_print(swChannel *);
  
  /*----------------------------LinkedList-------------------------------*/
  swLinkedList* swLinkedList_new(uint8_t type, swDestructor dtor);
  int swLinkedList_append(swLinkedList *ll, void *data);
  void swLinkedList_remove_node(swLinkedList *ll, swLinkedList_node *remove_node);
  int swLinkedList_prepend(swLinkedList *ll, void *data);
  void* swLinkedList_pop(swLinkedList *ll);
  void* swLinkedList_shift(swLinkedList *ll);
  swLinkedList_node* swLinkedList_find(swLinkedList *ll, void *data);
  void swLinkedList_free(swLinkedList *ll);
  #define swLinkedList_remove(ll, data) (swLinkedList_remove_node(ll, swLinkedList_find(ll, data)))
  /*----------------------------Thread Pool-------------------------------*/
  enum swThread_type
  {
      SW_THREAD_MASTER = 1,
      SW_THREAD_REACTOR = 2,
      SW_THREAD_WORKER = 3,
      SW_THREAD_UDP = 4,
      SW_THREAD_UNIX_DGRAM = 5,
      SW_THREAD_HEARTBEAT = 6,
  };
  
  typedef struct _swThreadPool
  {
      swCond cond;
  
      swThread *threads;
      swThreadParam *params;
  
      void *ptr1;
      void *ptr2;
  
  #ifdef SW_THREADPOOL_USE_CHANNEL
      swChannel *chan;
  #else
      swRingQueue queue;
  #endif
  
      int thread_num;
      int shutdown;
      sw_atomic_t task_num;
  
      void (*onStart)(struct _swThreadPool *pool, int id);
      void (*onStop)(struct _swThreadPool *pool, int id);
      int (*onTask)(struct _swThreadPool *pool, void *task, int task_len);
  
  } swThreadPool;
  
  struct _swThread
  {
      pthread_t tid;
      int id;
      swThreadPool *pool;
  };
  
  int swThreadPool_dispatch(swThreadPool *pool, void *task, int task_len);
  int swThreadPool_create(swThreadPool *pool, int max_num);
  int swThreadPool_run(swThreadPool *pool);
  int swThreadPool_free(swThreadPool *pool);
  
  //--------------------------------protocol------------------------------
  ssize_t swProtocol_get_package_length(swProtocol *protocol, swSocket *conn, char *data, uint32_t size);
  int swProtocol_recv_check_length(swProtocol *protocol, swSocket *conn, swString *buffer);
  int swProtocol_recv_check_eof(swProtocol *protocol, swSocket *conn, swString *buffer);
  
  //--------------------------------timer------------------------------
  #define SW_TIMER_MIN_MS  1
  #define SW_TIMER_MIN_SEC 0.001
  #define SW_TIMER_MAX_MS  LONG_MAX
  #define SW_TIMER_MAX_SEC ((double) (LONG_MAX / 1000))
  
  typedef struct _swTimer swTimer;
  typedef struct _swTimer_node swTimer_node;
  
  typedef void (*swTimerCallback)(swTimer *, swTimer_node *);
  typedef void (*swTimerDtor)(swTimer_node *);
  
  enum swTimer_type
  {
      SW_TIMER_TYPE_KERNEL,
      SW_TIMER_TYPE_PHP,
  };
  
  struct _swTimer_node
  {
      /*----------------properties--------------*/
      long id;
      enum swTimer_type type;
      int64_t exec_msec;
      int64_t interval;
      uint64_t round;
      uint8_t removed;
      swHeap_node *heap_node;
      /*-----------------callback---------------*/
      swTimerCallback callback;
      void *data;
      /*-----------------destructor-------------*/
      swTimerDtor dtor;
  };
  
  struct _swTimer
  {
      /*--------------signal timer--------------*/
      swReactor *reactor;
      swHeap *heap;
      swHashMap *map;
      uint32_t num;
      uint64_t round;
      long _next_id;
      long _current_id;
      long _next_msec;
      /*---------------event timer--------------*/
      struct timeval basetime;
      /*---------------system timer-------------*/
      long lasttime;
      /*----------------------------------------*/
      int (*set)(swTimer *timer, long exec_msec);
      void (*close)(swTimer *timer);
  };
  
  int swTimer_init(swTimer *timer, long msec);
  void swTimer_reinit(swTimer *timer, swReactor *reactor);
  swTimer_node* swTimer_add(swTimer *timer, long _msec, int interval, void *data, swTimerCallback callback);
  enum swBool_type swTimer_del(swTimer *timer, swTimer_node *node);
  void swTimer_free(swTimer *timer);
  int swTimer_select(swTimer *timer);
  int swTimer_now(struct timeval *time);
  
  static sw_inline swTimer_node* swTimer_get(swTimer *timer, long id)
  {
      return (swTimer_node*) swHashMap_find_int(timer->map, id);
  }
  
  static sw_inline swTimer_node* swTimer_get_ex(swTimer *timer, long id, const enum swTimer_type type)
  {
      swTimer_node* tnode = swTimer_get(timer, id);
      return (tnode && tnode->type == type) ? tnode : NULL;
  }
  
  int swSystemTimer_init(swTimer *timer, long msec);
  void swSystemTimer_signal_handler(int sig);
  //--------------------------------------------------------------
  
  //Worker process global Variable
  typedef struct
  {
      /**
       * Always run
       */
      uint8_t run_always;
  
      /**
       * for timer with block io
       */
      uint8_t signal_alarm;
  
      /**
       * Current Proccess Worker's id
       */
      uint32_t id;
  
      /**
       * pipe_worker
       */
      int pipe_used;
  
      uint32_t shutdown :1;
  
      uint32_t max_request;
  
      swString **buffer_input;
      swString **buffer_output;
      swWorker *worker;
      time_t exit_time;
  
  } swWorkerGlobal_t;
  
  typedef struct
  {
      uint16_t id;
      uint8_t type;
      uint8_t update_time;
      swString *buffer_stack;
      swReactor *reactor;
      swTimer *timer;
      uint8_t aio_init;
      uint8_t aio_schedule;
      uint32_t aio_task_num;
      swPipe aio_pipe;
      int aio_pipe_read;
      int aio_pipe_write;
  #ifdef SW_AIO_WRITE_LOCK
      swLock aio_lock;
  #endif
  } swThreadGlobal_t;
  
  typedef struct
  {
      union
      {
          char v4[INET_ADDRSTRLEN];
          char v6[INET6_ADDRSTRLEN];
      } address;
  } swDNS_server;
  
  typedef struct _swServer swServer;
  typedef struct _swFactory swFactory;
  
  typedef struct
  {
      uint8_t init :1;
      uint8_t running :1;
      uint8_t enable_coroutine :1;
      uint8_t use_signalfd :1;
      uint8_t enable_signalfd :1;
      uint8_t reuse_port :1;
      uint8_t socket_dontwait :1;
      uint8_t dns_lookup_random :1;
      uint8_t use_async_resolver :1;
  
      int error;
      int process_type;
      pid_t pid;
  
      int signal_fd;
      int log_fd;
      int null_fd;
  
      /**
       * worker(worker and task_worker) process chroot / user / group
       */
      char *chroot;
      char *user;
      char *group;
  
      uint32_t log_level;
      char *log_file;
      uint32_t trace_flags;
  
      void (*write_log)(int level, char *content, size_t len);
      void (*fatal_error)(int code, const char *str, ...);
  
      //-----------------------[System]--------------------------
      uint16_t cpu_num;
      uint32_t pagesize;
      struct utsname uname;
  
      //-----------------------[Socket]--------------------------
      uint32_t max_sockets;
      /**
       * tcp socket default buffer size
       */
      uint32_t socket_buffer_size;
      swArray *socket_array;
  
      swServer *serv;
  
      swMemoryPool *memory_pool;
      swLock lock;
  
      char *task_tmpdir;
      uint16_t task_tmpdir_len;
  
      char *dns_server_v4;
      char *dns_server_v6;
      double dns_cache_refresh_time;
  
      /**
       * aio-threads
       */
      uint32_t aio_core_worker_num;
      uint32_t aio_worker_num;
      double aio_max_wait_time;
      double aio_max_idle_time;
      int aio_default_pipe_fd;
  
      swHashMap *functions;
      swLinkedList *hooks[SW_MAX_HOOK_TYPE];
  
  } swGlobal_t;
  
  extern swGlobal_t SwooleG;              //Local Global Variable
  extern swWorkerGlobal_t SwooleWG;             //Worker Global Variable
  extern __thread swThreadGlobal_t SwooleTG;   //Thread Global Variable
  
  #define SW_CPU_NUM                    (SwooleG.cpu_num)
  
  //-----------------------------------------------
  //OS Feature
  #if defined(HAVE_KQUEUE) || !defined(HAVE_SENDFILE)
  int swoole_sendfile(int out_fd, int in_fd, off_t *offset, size_t size);
  #else
  #include <sys/sendfile.h>
  #define swoole_sendfile(out_fd, in_fd, offset, limit)    sendfile(out_fd, in_fd, offset, limit)
  #endif
  
  static sw_inline void sw_spinlock(sw_atomic_t *lock)
  {
      uint32_t i, n;
      while (1)
      {
          if (*lock == 0 && sw_atomic_cmp_set(lock, 0, 1))
          {
              return;
          }
          if (SW_CPU_NUM > 1)
          {
              for (n = 1; n < SW_SPINLOCK_LOOP_N; n <<= 1)
              {
                  for (i = 0; i < n; i++)
                  {
                      sw_atomic_cpu_pause();
                  }
  
                  if (*lock == 0 && sw_atomic_cmp_set(lock, 0, 1))
                  {
                      return;
                  }
              }
          }
          swYield();
      }
  }
  
  static sw_inline int64_t swTimer_get_relative_msec()
  {
      struct timeval now;
      if (!SwooleTG.timer)
      {
          return SW_ERR;
      }
      if (swTimer_now(&now) < 0)
      {
          return SW_ERR;
      }
      int64_t msec1 = (now.tv_sec - SwooleTG.timer->basetime.tv_sec) * 1000;
      int64_t msec2 = (now.tv_usec - SwooleTG.timer->basetime.tv_usec) / 1000;
      return msec1 + msec2;
  }
  
  static sw_inline int64_t swTimer_get_absolute_msec()
  {
      struct timeval now;
      if (swTimer_now(&now) < 0)
      {
          return SW_ERR;
      }
      int64_t msec1 = (now.tv_sec) * 1000;
      int64_t msec2 = (now.tv_usec) / 1000;
      return msec1 + msec2;
  }
  
  SW_EXTERN_C_END
  
  #endif /* SWOOLE_H_ */
  