Merge remote-tracking branch 'origin/master' into dev_mac_support_cross_compilation

This commit is contained in:
hailang 2022-04-10 17:29:58 +08:00
commit 5ef96d62fe
92 changed files with 2535 additions and 12255 deletions

187
.ycm_extra_conf.py Normal file
View File

@ -0,0 +1,187 @@
# Generated by YCM Generator at 2021-11-18 20:34:43.424020
# This file is NOT licensed under the GPLv3, which is the license for the rest
# of YouCompleteMe.
#
# Here's the license text for this file:
#
# This is free and unencumbered software released into the public domain.
#
# Anyone is free to copy, modify, publish, use, compile, sell, or
# distribute this software, either in source code form or as a compiled
# binary, for any purpose, commercial or non-commercial, and by any
# means.
#
# In jurisdictions that recognize copyright laws, the author or authors
# of this software dedicate any and all copyright interest in the
# software to the public domain. We make this dedication for the benefit
# of the public at large and to the detriment of our heirs and
# successors. We intend this dedication to be an overt act of
# relinquishment in perpetuity of all present and future rights to this
# software under copyright law.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
# For more information, please refer to <http://unlicense.org/>
import os
import ycm_core
flags = [
'-isystem'
'./lib_acl/include',
'-isystem'
'./lib_protocol/include',
'-isystem'
'./lib_acl_cpp/include',
'-isystem'
'./lib_fiber/c/include',
'-isystem'
'./lib_fiber/cpp/include',
'-x',
'c++',
'-I.',
'-I./lib_acl/include',
'-I./lib_acl/src',
'-I./lib_protocol/include',
'-I./lib_protocol/src',
'-I./lib_acl_cpp/include',
'-I./lib_acl_cpp/src',
'-I./lib_fiber/c/include',
'-I./lib_fiber/c/src',
'-I./lib_fiber/cpp/include',
'-I./lib_fiber/cpp/src',
'-DACL_PREPARE_COMPILE',
'-DACL_WRITEABLE_CHECK',
'-DHAVE_CONFIG_H',
'-DNO_TCMALLOC_SAMPLES',
'-DUSE_BOOST_JMP',
'-DUSE_FAST_RING',
'-D_FILE_OFFSET_BITS=64',
'-D_POSIX_PTHREAD_SEMANTICS',
'-D_REENTRANT',
'-D_USE_FAST_MACRO',
'-D__CLASSIC_C__',
'-W',
'-Wall',
'-Wdeclaration-after-statement',
'-Werror',
'-Wno-long-long',
'-Wpointer-arith',
'-Wshadow',
'-Wuninitialized',
'-std=c++11',
]
# Set this to the absolute path to the folder (NOT the file!) containing the
# compile_commands.json file to use that instead of 'flags'. See here for
# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html
#
# You can get CMake to generate this file for you by adding:
# set( CMAKE_EXPORT_COMPILE_COMMANDS 1 )
# to your CMakeLists.txt file.
#
# Most projects will NOT need to set this to anything; you can just change the
# 'flags' list of compilation flags. Notice that YCM itself uses that approach.
compilation_database_folder = ''
if os.path.exists( compilation_database_folder ):
database = ycm_core.CompilationDatabase( compilation_database_folder )
else:
database = None
SOURCE_EXTENSIONS = ['.cpp', '.cxx', '.cc', '.c' ]
def DirectoryOfThisScript():
return os.path.dirname( os.path.abspath( __file__ ) )
def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
if not working_directory:
return list( flags )
new_flags = []
make_next_absolute = False
path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
for flag in flags:
new_flag = flag
if make_next_absolute:
make_next_absolute = False
if not flag.startswith( '/' ):
new_flag = os.path.join( working_directory, flag )
for path_flag in path_flags:
if flag == path_flag:
make_next_absolute = True
break
if flag.startswith( path_flag ):
path = flag[ len( path_flag ): ]
new_flag = path_flag + os.path.join( working_directory, path )
break
if new_flag:
new_flags.append( new_flag )
return new_flags
def IsHeaderFile( filename ):
extension = os.path.splitext( filename )[ 1 ]
return extension in [ '.H', '.h', '.hxx', '.hpp', '.hh' ]
def GetCompilationInfoForFile( filename ):
# The compilation_commands.json file generated by CMake does not have entries
# for header files. So we do our best by asking the db for flags for a
# corresponding source file, if any. If one exists, the flags for that file
# should be good enough.
if IsHeaderFile( filename ):
basename = os.path.splitext( filename )[ 0 ]
for extension in SOURCE_EXTENSIONS:
replacement_file = basename + extension
if os.path.exists( replacement_file ):
compilation_info = database.GetCompilationInfoForFile(
replacement_file )
if compilation_info.compiler_flags_:
return compilation_info
return None
return database.GetCompilationInfoForFile( filename )
def FlagsForFile( filename, **kwargs ):
if database:
# Bear in mind that compilation_info.compiler_flags_ does NOT return a
# python list, but a "list-like" StringVec object
compilation_info = GetCompilationInfoForFile( filename )
if not compilation_info:
return None
final_flags = MakeRelativePathsInFlagsAbsolute(
compilation_info.compiler_flags_,
compilation_info.compiler_working_dir_ )
else:
relative_to = DirectoryOfThisScript()
final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )
return {
'flags': final_flags,
'do_cache': True
}
def Settings( **kwargs ):
language = kwargs[ 'language' ]
if language == 'cfamily':
return {
'flags': flags
}
return {}

View File

@ -185,7 +185,7 @@ int main(int argc, char **argv)
}
if (setsid() == -1 && getsid(0) != getpid())
acl_msg_fatal("unable to set session %s", acl_last_serror());
acl_msg_warn("unable to set session %s", acl_last_serror());
/*
* Make some room for plumbing with file descriptors. XXX This breaks

View File

@ -99,6 +99,9 @@ service $<PROGRAM>
# acl_master 退出时如果该值置1则该程序不等所有连接处理完毕便立即退出
fiber_quick_abort = 1
# 是否启用协程共享栈模式
fiber_share_stack = 0
# fiber_quick_abort 0 且本配置项大于 0 该配置项才有效指定了
# 本进程在所有连接退出前的最大等待时间()
fiber_wait_limit = 0

View File

@ -99,6 +99,9 @@ service $<PROGRAM>
# acl_master 退出时如果该值置1则该程序不等所有连接处理完毕便立即退出
fiber_quick_abort = 1
# 是否启用协程共享栈模式
fiber_share_stack = 0
# fiber_quick_abort 0 且本配置项大于 0 该配置项才有效指定了
# 本进程在所有连接退出前的最大等待时间()
fiber_wait_limit = 0

View File

@ -81,8 +81,7 @@ bool http_servlet::on_hello(request_t& req, response_t& res)
return false;
}
if (i % 10000 == 0)
{
if (i % 10000 == 0) {
sleep(1);
printf("i=%d\n", (int) i);
}
@ -96,22 +95,27 @@ bool http_servlet::on_hello(request_t& req, response_t& res)
bool http_servlet::transfer_get(request_t& req, response_t& res)
{
http_transfer fiber_peer(acl::HTTP_METHOD_GET, req, res, port_);
fiber_peer.start();
http_transfer* fiber_peer = new
http_transfer(acl::HTTP_METHOD_GET, req, res, port_);
fiber_peer->start();
bool keep_alive;
fiber_peer.wait(&keep_alive);
fiber_peer->wait(&keep_alive);
delete fiber_peer;
return keep_alive && req.isKeepAlive();
}
bool http_servlet::transfer_post(request_t& req, response_t& res)
{
http_transfer fiber_peer(acl::HTTP_METHOD_POST, req, res, port_);
fiber_peer.start();
http_transfer* fiber_peer = new
http_transfer(acl::HTTP_METHOD_POST, req, res, port_);
fiber_peer->start();
bool keep_alive;
fiber_peer.wait(&keep_alive);
fiber_peer->wait(&keep_alive);
delete fiber_peer;
printf("transfer_post finished\r\n");
return keep_alive && req.isKeepAlive();
}
@ -136,17 +140,25 @@ bool http_servlet::doConnect(request_t& req, response_t&)
} else {
host = phost;
}
printf("remote host=%s, current fiber=%p\r\n", host.c_str(), acl_fiber_running());
acl::socket_stream peer;
if (!peer.open(host, 5, 5, acl::time_unit_s)) {
acl::socket_stream* peer = new acl::socket_stream;
if (!peer->open(host, 5, 5, acl::time_unit_s)) {
logger_error("connect %s error %s", host.c_str(), acl::last_serror());
delete peer;
return false;
}
printf("connect %s ok, fd=%d\r\n", host.c_str(), peer.sock_handle());
printf("connect %s ok, fd=%d\r\n", host.c_str(), peer->sock_handle());
acl::socket_stream& local = req.getSocketStream();
local.set_rw_timeout(3);
#define USE_REFER
#ifdef USE_REFER
acl::socket_stream* local = &req.getSocketStream();
#else
acl::socket_stream* local = new acl::socket_stream;
local->open(req.getSocketStream().sock_handle());
#endif
#if 0
const char* ok = "";
@ -159,43 +171,68 @@ bool http_servlet::doConnect(request_t& req, response_t&)
const char* ok = "HTTP/1.1 200 Connection Established\r\n\r\n";
size_t n = strlen(ok);
if (local.write(ok, n) != (int) n) {
if (local->write(ok, n) != (int) n) {
logger_error("write connect response error");
delete peer;
local->unbind_sock();
delete local;
return false;
}
#endif
transfer_tcp(local, peer);
transfer_tcp(*local, *peer);
#ifndef USE_REFER
int fd = local->unbind_sock();
if (fd == -1) {
acl::socket_stream& ss = req.getSocketStream();
logger_warn("The socket=%d has been closed before!",
ss.sock_handle());
ss.unbind_sock();
}
delete local;
#endif
delete peer;
return false;
}
bool http_servlet::transfer_tcp(acl::socket_stream& local, acl::socket_stream& peer)
bool http_servlet::transfer_tcp(acl::socket_stream& local,
acl::socket_stream& peer)
{
local.set_rw_timeout(5);
peer.set_rw_timeout(5);
local.set_rw_timeout(20);
peer.set_rw_timeout(20);
tcp_transfer fiber_local(acl_fiber_running(), local, peer, false);
tcp_transfer fiber_peer(acl_fiber_running(), peer, local, false);
tcp_transfer* fiber_local = new
tcp_transfer(acl_fiber_running(), local, peer, false);
tcp_transfer* fiber_peer = new
tcp_transfer(acl_fiber_running(), peer, local, false);
fiber_local.set_peer(fiber_peer);
fiber_peer.set_peer(fiber_local);
fiber_local->set_peer(fiber_peer);
fiber_local->set_local(true);
fiber_peer.start();
fiber_local.start();
fiber_peer->set_peer(fiber_local);
fiber_peer->set_local(false);
fiber_peer->start();
fiber_local->start();
//int fd_local = local.sock_handle();
//int fd_peer = peer.sock_handle();
//printf("wait local fiber, local fd=%d, peer fd=%d\r\n", fd_local, fd_peer);
fiber_local.wait();
fiber_local->wait();
//printf("local fiber done, local fd=%d, peer fd=%d\r\n", fd_local, fd_peer);
//printf("wait peer fiber, local fd=%d, peer fd=%d\r\n", fd_local, fd_peer);
fiber_peer.wait();
fiber_peer->wait();
//printf("peer fiber done, local fd=%d, peer fd=%d\r\n", fd_local, fd_peer);
//printf("transfer_tcp finished, local fd=%d, %d, peer fd=%d, %d\r\n",
// fiber_local.get_input().sock_handle(), fd_local,
// fiber_local.get_output().sock_handle(), fd_peer);
delete fiber_peer;
delete fiber_local;
return true;
}

View File

@ -8,14 +8,27 @@ http_transfer::http_transfer(acl::http_method_t method, request_t& req,
, req_(req)
, res_(res)
, client_(NULL)
{}
{
box_ = new acl::fiber_tbox<bool>;
acl::socket_stream& sin = req_.getSocketStream();
req_in_.open(sin.sock_handle());
acl::socket_stream& sout = res_.getSocketStream();
res_out_.open(sout.sock_handle());
res_client_ = res_.getClient();
}
http_transfer::~http_transfer(void) {
req_in_.unbind_sock();
res_out_.unbind_sock();
delete client_;
delete box_;
}
void http_transfer::wait(bool* keep_alive) {
bool* res = box_.pop();
bool* res = box_->pop();
assert(res);
*keep_alive = *res;
delete res;
@ -36,7 +49,7 @@ void http_transfer::run(void) {
break;
}
box_.push(res);
box_->push(res);
}
bool http_transfer::open_peer(request_t& req, acl::socket_stream& conn)
@ -61,13 +74,17 @@ bool http_transfer::open_peer(request_t& req, acl::socket_stream& conn)
acl::string addr;
addr.format("%s|%d", buf.c_str(), port_);
if (conn.open(addr, 0, 0)) {
logger("connect %s ok", addr.c_str());
return true;
if (!conn.open(addr, 0, 0)) {
logger_error("connect %s error %s",
addr.c_str(), acl::last_serror());
return false;
}
logger_error("connect %s error %s", addr.c_str(), acl::last_serror());
return false;
logger("connect %s ok", addr.c_str());
bool is_request = true, unzip = false, fixed_stream = true;
client_ = new acl::http_client(&conn, is_request, unzip, fixed_stream);
return true;
}
bool http_transfer::transfer_request_head(acl::socket_stream& conn) {
@ -85,8 +102,7 @@ bool http_transfer::transfer_request_head(acl::socket_stream& conn) {
return false;
}
//printf(">>>send head: [%s]\r\n", header.c_str());
client_ = new acl::http_client(&conn, true);
printf(">>>send head: [%s]\r\n", header.c_str());
return true;
}
@ -96,12 +112,11 @@ bool http_transfer::transfer_request_body(acl::socket_stream& conn) {
return true;
}
acl::istream& in = req_.getInputStream();
long long n = 0;
char buf[8192];
while (n < length) {
int ret = in.read(buf, sizeof(buf), false);
int ret = req_in_.read(buf, sizeof(buf), false);
if (ret == -1) {
logger_error("read request body error");
return false;
@ -156,6 +171,9 @@ bool http_transfer::transfer_response(void) {
return false;
}
bool keep_alive = false; // xxxx
client_->header_update("Connection", "Close");
acl::string header;
client_->sprint_header(header, NULL);
if (header.empty()) {
@ -167,32 +185,47 @@ bool http_transfer::transfer_response(void) {
printf("response head:\r\n[%s]\r\n", header.c_str());
acl::ostream& out = res_.getOutputStream();
if (out.write(header) == -1) {
//acl::ostream* out = &res_->getOutputStream();
if (res_out_.write(header) == -1) {
logger_error("send response head error");
return false;
}
//acl::http_client* out_client = res_->getClient();
//assert(out_client);
long long length = client_->body_length();
if (length == 0) {
return client_->is_server_keep_alive();
return client_->is_server_keep_alive() && keep_alive;
}
HTTP_HDR_RES* hdr_res = client_->get_respond_head(NULL);
assert(hdr_res);
bool chunked = hdr_res->hdr.chunked ? true : false;
char buf[8192];
while (true) {
int ret = client_->read_body(buf, sizeof(buf));
if (ret <= 0) {
break;
} else if (out.write(buf, ret) == -1) {
} else if (chunked) {
if (!res_client_->write_chunk(res_out_, buf, ret)) {
logger_error("send response body error");
return false;
}
} else if (res_out_.write(buf, ret) == -1) {
logger_error("send response body error");
return false;
}
}
if (length < 0) {
return false;
if (chunked) {
if (!res_client_->write_chunk_trailer(res_out_)) {
logger_error("write chunked trailer error");
return false;
}
}
return client_->is_server_keep_alive();
return client_->is_server_keep_alive() && false;
}

View File

@ -14,7 +14,7 @@ protected:
void run(void);
private:
acl::fiber_tbox<bool> box_;
acl::fiber_tbox<bool>* box_;
int port_;
acl::http_method_t method_;
@ -23,6 +23,10 @@ private:
acl::socket_stream conn_;
acl::http_client* client_;
acl::socket_stream req_in_;
acl::socket_stream res_out_;
acl::http_client* res_client_;
bool open_peer(request_t& req, acl::socket_stream& conn);
bool transfer_get(void);

View File

@ -155,7 +155,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;..\..\..\lib_fiber\c\include;..\..\..\lib_fiber\cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;..\..\..\lib_fiber\c\include;..\..\..\lib_fiber\cpp\include;..\..\..\lib_protocol\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@ -199,7 +199,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;..\..\..\lib_fiber\c\include;..\..\..\lib_fiber\cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\..\lib_acl_cpp\include;..\..\..\lib_acl\include;..\..\..\lib_fiber\c\include;..\..\..\lib_fiber\cpp\include;..\..\..\lib_protocol\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>Use</PrecompiledHeader>

View File

@ -47,15 +47,18 @@ void master_service::on_accept(acl::socket_stream& conn)
conn.set_rw_timeout(120);
acl::memcache_session session("127.0.0.1:11211");
http_servlet servlet(&conn, &session);
acl::memcache_session* session = new acl::memcache_session("127.0.0.1:11211");
http_servlet* servlet = new http_servlet(&conn, session);
// charset: big5, gb2312, gb18030, gbk, utf-8
servlet.setLocalCharset("utf-8");
servlet->setLocalCharset("utf-8");
servlet->setParseBody(false);
while(servlet.doRun()) {}
while(servlet->doRun()) {}
logger("disconnect from %s, fd %d", conn.get_peer(), conn.sock_handle());
delete session;
delete servlet;
}
void master_service::proc_pre_jail(void)
@ -70,7 +73,8 @@ void master_service::proc_on_listen(acl::server_socket& ss)
void master_service::proc_on_init(void)
{
logger(">>>proc_on_init<<<");
logger(">>>proc_on_init: shared stack size=%zd<<<",
acl::fiber::get_shared_stack_size());
}
void master_service::proc_on_exit(void)

View File

@ -11,6 +11,7 @@
// TODO: 在此处引用程序要求的附加头文件
#include "lib_acl.h"
#include "lib_protocol.h"
#include "acl_cpp/lib_acl.hpp"
#include "fiber/lib_fiber.h"
#include "fiber/lib_fiber.hpp"

View File

@ -9,6 +9,7 @@ tcp_transfer::tcp_transfer(ACL_FIBER* parent, acl::socket_stream& in,
, in_(in)
, out_(out)
, peer_(NULL)
, is_local_(false)
{
}
@ -16,9 +17,14 @@ tcp_transfer::~tcp_transfer(void)
{
}
void tcp_transfer::set_peer(tcp_transfer& peer)
void tcp_transfer::set_peer(tcp_transfer* peer)
{
peer_ = &peer;
peer_ = peer;
}
void tcp_transfer::set_local(bool yes)
{
is_local_ = yes;
}
void tcp_transfer::unset_peer(void)
@ -45,7 +51,9 @@ void tcp_transfer::wait(void)
void tcp_transfer::run(void)
{
me_ = acl_fiber_running();
char buf[8192];
while (true) {
int fd = in_.sock_handle();
int ret = in_.read(buf, sizeof(buf) - 1, false);
@ -57,9 +65,24 @@ void tcp_transfer::run(void)
break;
}
buf[ret] = 0;
#if 0
printf("send from %s data, in=%d, out=%d\r\n",
is_local_ ? "local" : "remote",
in_->sock_handle(), out_->sock_handle());
#endif
if (out_.write(buf, ret) == -1) {
printf(">>>write error\n");
break;
}
#if 0
printf("send to %s data, in=%d, out=%d ok\r\n",
is_local_ ? "local" : "remote",
in_->sock_handle(), out_->sock_handle());
#endif
}
if (peer_) {

View File

@ -3,23 +3,16 @@
class tcp_transfer : public acl::fiber
{
public:
tcp_transfer(ACL_FIBER* parent, acl::socket_stream& in, acl::socket_stream& out, bool running);
tcp_transfer(ACL_FIBER* parent, acl::socket_stream& in,
acl::socket_stream& out, bool running);
~tcp_transfer(void);
void set_peer(tcp_transfer& peer);
void set_peer(tcp_transfer* peer);
void unset_peer(void);
void close(void);
void wait(void);
acl::socket_stream& get_input(void) const
{
return in_;
}
acl::socket_stream& get_output(void) const
{
return out_;
}
void set_local(bool yes);
ACL_FIBER* peer_fiber(void) const {
return me_;
@ -36,5 +29,6 @@ private:
acl::socket_stream& in_;
acl::socket_stream& out_;
tcp_transfer* peer_;
bool is_local_;
};

View File

@ -28,7 +28,7 @@ service server {
# 上游 DNS 服务器的 IP
# dns_neighbor_ip = 211.157.131.7
# dns_neighbor_ip = 192.168.198.47
dns_neighbor_ip = 8.8.8.8
dns_neighbor_ip = 114.114.114.114
# 上游 DNS 服务器的 PORT
dns_neighbor_port = 53
}

View File

@ -149,7 +149,8 @@ static ACL_VSTREAM *stream_udp_bind(struct sockaddr_in addr)
stream = stream_udp_open();
fd = ACL_VSTREAM_SOCK(stream);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
acl_msg_fatal("%s(%d): can't bind", myname, __LINE__);
acl_msg_fatal("%s(%d): bind, error: %s", myname,
__LINE__, acl_last_serror());
return stream;
}
@ -456,7 +457,7 @@ void service_udp_init(SERVICE *service, const char *local_ip,
ACL_SAFE_STRNCPY(ctx->local_ip, local_ip, sizeof(ctx->local_ip));
ctx->local_port = local_port;
ctx->local_addr.sin_addr.s_addr = inet_addr(local_ip);
ctx->local_addr.sin_port = htons(local_port);
ctx->local_addr.sin_port = htons(local_port + 1);
ctx->local_addr.sin_family = AF_INET;
ACL_SAFE_STRNCPY(ctx->remote_ip, remote_ip, sizeof(ctx->remote_ip));
@ -465,6 +466,8 @@ void service_udp_init(SERVICE *service, const char *local_ip,
ctx->remote_addr.sin_port = htons(remote_port);
ctx->remote_addr.sin_family = AF_INET;
printf("begin bind %s:%d\r\n", local_ip, local_port);
// 创建接收客户端请求的流
stream = stream_udp_bind(ctx->local_addr);
acl_vstream_ctl(stream,

View File

@ -539,6 +539,8 @@ int acl_read_wait(ACL_SOCKET fd, int timeout)
return acl_read_wait_ms(fd, timeout * 1000);
}
/* #define USE_EPOLL */
int acl_read_wait_ms(ACL_SOCKET fd, int timeout)
{
#if defined(ACL_LINUX) && !defined(MINGW) && defined(USE_EPOLL)

View File

@ -69,14 +69,13 @@ public:
HttpServlet& setRwTimeout(int rw_timeout);
/**
* POST
* doRun MIME 使
*
* @param on {bool}
* POST Form
* doRun MIME
* 使
* @param yes {bool}
* @return {HttpServlet&}
* xxxx:
*/
HttpServlet& setParseBody(bool on);
HttpServlet& setParseBody(bool yes);
/**
* POST
@ -207,6 +206,7 @@ protected:
protected:
HttpServletRequest* req_;
HttpServletResponse* res_;
bool parse_body_;
private:
session* session_;

View File

@ -47,6 +47,14 @@ public:
int body_limit = 102400);
~HttpServletRequest(void);
/**
* POST Form
* doRun MIME
* 使
* @param yes {bool}
*/
void setParseBody(bool yes);
/**
* HTTP GET, POST, PUT, CONNECT, PURGE
* @param method_s {string*}
@ -413,6 +421,7 @@ private:
int rw_timeout_;
std::vector<HTTP_PARAM*> params_;
http_request_t request_type_;
bool parse_body_;
http_mime* mime_;
string* body_;
json* json_;

View File

@ -54,11 +54,18 @@ public:
tbox_ = new tbox<redis_pipeline_message>(false);
mbox_ = NULL;
}
size_ = 10;
argc_ = 0;
argv_ = new const char* [size_];
lens_ = new size_t [size_];
}
~redis_pipeline_message(void) {
delete mbox_;
delete tbox_;
delete [] argv_;
delete [] lens_;
}
redis_pipeline_message& set_type(redis_pipeline_type_t type) {
@ -83,9 +90,25 @@ public:
}
void set_request(size_t argc, const char** argv, size_t* lens) {
#if 0
argc_ = argc;
argv_ = argv;
lens_ = lens;
#else
if (argc_ > size_) {
delete [] argv_;
delete [] lens_;
size_ = argc;
argv_ = new const char* [size_];
lens_ = new size_t [size_];
}
argc_ = argc;
for (size_t i = 0; i < size_; i++) {
argv_[i] = argv[i];
lens_[i] = lens[i];
}
#endif
}
void set_addr(const char* addr) {
@ -142,6 +165,7 @@ private:
size_t redirect_count_;
public:
size_t size_;
size_t argc_;
const char** argv_;
size_t* lens_;

View File

@ -19,6 +19,7 @@ namespace acl
HttpServlet::HttpServlet(socket_stream* stream, session* session)
: req_(NULL)
, res_(NULL)
, parse_body_(true)
, stream_(stream)
{
init();
@ -88,8 +89,9 @@ HttpServlet& HttpServlet::setRwTimeout(int rw_timeout)
return *this;
}
HttpServlet& HttpServlet::setParseBody(bool)
HttpServlet& HttpServlet::setParseBody(bool yes)
{
parse_body_ = yes;
return *this;
}
@ -161,6 +163,7 @@ bool HttpServlet::start(void)
res_ = NEW HttpServletResponse(*out);
req_ = NEW HttpServletRequest(*res_, *session_, *in, local_charset_,
parse_body_limit_);
req_->setParseBody(parse_body_);
// ÉèÖÃ HttpServletRequest ¶ÔÏó
res_->setHttpServletRequest(req_);

View File

@ -43,6 +43,7 @@ HttpServletRequest::HttpServletRequest(HttpServletResponse& res,
, client_(NULL)
, method_(HTTP_METHOD_UNKNOWN)
, request_type_(HTTP_REQUEST_NORMAL)
, parse_body_(true)
, mime_(NULL)
, body_(NULL)
, json_(NULL)
@ -90,6 +91,11 @@ http_method_t HttpServletRequest::getMethod(string* method_s /* = NULL */) const
return method_;
}
void HttpServletRequest::setParseBody(bool yes)
{
parse_body_ = yes;
}
void HttpServletRequest::add_cookie(char* data)
{
SKIP_SPACE(data);
@ -826,6 +832,10 @@ bool HttpServletRequest::readHeader(string* method_s)
// 当数据体为 form 格式时:
if (EQ(ctype, "application") && EQ(stype, "x-www-form-urlencoded")) {
request_type_ = HTTP_REQUEST_NORMAL;
if (!parse_body_) {
return true;
}
char* query = (char*) dbuf_->dbuf_alloc((size_t) len + 1);
int ret = getInputStream().read(query, (size_t) len);
if (ret > 0) {

View File

@ -164,11 +164,13 @@ void redis_client_cluster::set_all_slot(const char* addr, size_t max_conns,
char buf[128];
safe_snprintf(buf, sizeof(buf), "%s:%d", ip, port);
redis_client_pool* conns = (redis_client_pool*) get(buf);
if (conns == NULL)
if (conns == NULL) {
set(buf, max_conns, conn_timeout, rw_timeout);
}
for (size_t i = slot_min; i <= slot_max; i++)
for (size_t i = slot_min; i <= slot_max; i++) {
set_slot((int) i, buf);
}
}
}

View File

@ -112,13 +112,13 @@ int redis_cluster::cluster_getkeysinslot(size_t slot, size_t max,
argv[1] = "GETKEYSINSLOT";
lens[1] = sizeof("GETKEYSINSLOT") - 1;
char slot_s[LONG_LEN];
safe_snprintf(slot_s, sizeof(slot_s), "%lu", (unsigned long) slot);
char* slot_s = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(slot_s, LONG_LEN, "%lu", (unsigned long) slot);
argv[2] = slot_s;
lens[2] = strlen(slot_s);
char max_s[LONG_LEN];
safe_snprintf(max_s, sizeof(max_s), "%lu", (unsigned long) max);
char* max_s = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(max_s, LONG_LEN, "%lu", (unsigned long) max);
argv[3] = max_s;
lens[3] = strlen(max_s);
@ -140,8 +140,8 @@ bool redis_cluster::cluster_meet(const char* ip, int port)
argv[2] = ip;
lens[2] = strlen(ip);
char port_s[INT_LEN];
safe_snprintf(port_s, sizeof(port_s), "%d", port);
char* port_s = (char*) dbuf_->dbuf_alloc(INT_LEN);
safe_snprintf(port_s, INT_LEN, "%d", port);
argv[3] = port_s;
lens[3] = strlen(port_s);
@ -212,8 +212,8 @@ bool redis_cluster::cluster_setslot_importing(size_t slot, const char* src_node)
argv[1] = "SETSLOT";
lens[1] = sizeof("SETSLOT") - 1;
char slot_s[LONG_LEN];
safe_snprintf(slot_s, sizeof(slot_s), "%lu", (unsigned long) slot);
char* slot_s = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(slot_s, LONG_LEN, "%lu", (unsigned long) slot);
argv[2] = slot_s;
lens[2] = strlen(slot_s);
@ -238,8 +238,8 @@ bool redis_cluster::cluster_setslot_migrating(size_t slot, const char* dst_node)
argv[1] = "SETSLOT";
lens[1] = sizeof("SETSLOT") - 1;
char slot_s[LONG_LEN];
safe_snprintf(slot_s, sizeof(slot_s), "%lu", (unsigned long) slot);
char* slot_s = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(slot_s, LONG_LEN, "%lu", (unsigned long) slot);
argv[2] = slot_s;
lens[2] = strlen(slot_s);
@ -264,8 +264,8 @@ bool redis_cluster::cluster_setslot_stable(size_t slot)
argv[1] = "SETSLOT";
lens[1] = sizeof("SETSLOT") - 1;
char slot_s[LONG_LEN];
safe_snprintf(slot_s, sizeof(slot_s), "%lu", (unsigned long) slot);
char* slot_s = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(slot_s, LONG_LEN, "%lu", (unsigned long) slot);
argv[2] = slot_s;
lens[2] = strlen(slot_s);
@ -287,8 +287,8 @@ bool redis_cluster::cluster_setslot_node(size_t slot, const char* node)
argv[1] = "SETSLOT";
lens[1] = sizeof("SETSLOT") - 1;
char slot_s[LONG_LEN];
safe_snprintf(slot_s, sizeof(slot_s), "%lu", (unsigned long) slot);
char* slot_s = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(slot_s, LONG_LEN, "%lu", (unsigned long) slot);
argv[2] = slot_s;
lens[2] = strlen(slot_s);
@ -432,8 +432,8 @@ int redis_cluster::cluster_countkeysinslot(size_t slot)
argv[1] = "COUNTKEYSINSLOT";
lens[1] = sizeof("COUNTKEYSINSLOT") - 1;
char slot_s[LONG_LEN];
safe_snprintf(slot_s, sizeof(slot_s), "%lu", (unsigned long) slot);
char* slot_s = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(slot_s, LONG_LEN, "%lu", (unsigned long) slot);
argv[2] = slot_s;
lens[2] = strlen(slot_s);

View File

@ -859,8 +859,8 @@ const redis_result** redis_command::scan_keys(const char* cmd, const char* key,
argc++;
}
char cursor_s[INT_LEN];
safe_snprintf(cursor_s, sizeof(cursor_s), "%d", cursor);
char* cursor_s = (char*) dbuf_->dbuf_alloc(INT_LEN);
safe_snprintf(cursor_s, INT_LEN, "%d", cursor);
argv[argc] = cursor_s;
lens[argc] = strlen(cursor_s);
argc++;
@ -880,8 +880,8 @@ const redis_result** redis_command::scan_keys(const char* cmd, const char* key,
lens[argc] = sizeof("COUNT") - 1;
argc++;
char count_s[LONG_LEN];
safe_snprintf(count_s, sizeof(count_s), "%lu",
char* count_s = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(count_s, LONG_LEN, "%lu",
(unsigned long) (*count));
argv[argc] = count_s;
lens[argc] = strlen(count_s);

View File

@ -62,8 +62,8 @@ bool redis_connection::select(int dbnum)
argv[0] = "SELECT";
lens[0] = strlen(argv[0]);
char buf[21];
safe_snprintf(buf, sizeof(buf), "%d", dbnum);
char* buf = (char*) dbuf_->dbuf_alloc(21);
safe_snprintf(buf, 21, "%d", dbnum);
argv[1] = buf;
lens[1] = strlen(argv[1]);

View File

@ -440,8 +440,8 @@ bool redis_hash::hincrbyfloat(const char* key, const char* name,
const char* values[1];
names[0] = name;
char buf[FLOAT_LEN];
(void) safe_snprintf(buf, sizeof(buf), "%f", inc);
char* buf = (char*) dbuf_->dbuf_alloc(FLOAT_LEN);
(void) safe_snprintf(buf, FLOAT_LEN, "%f", inc);
values[0] = buf;
hash_slot(key);

View File

@ -195,7 +195,7 @@ int redis_key::expire(const char* key, size_t len, int n)
argv[1] = key;
lens[1] = len;
char buf[INT_LEN];
char* buf = (char*) dbuf_->dbuf_alloc(INT_LEN);
(void) safe_snprintf(buf, INT_LEN, "%d", n);
argv[2] = buf;
lens[2] = strlen(buf);
@ -221,8 +221,8 @@ int redis_key::expireat(const char* key, size_t len, time_t stamp)
argv[1] = key;
lens[1] = len;
char stamp_s[LONG_LEN];
safe_snprintf(stamp_s, sizeof(stamp_s), "%lu", (unsigned long) stamp);
char* stamp_s = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(stamp_s, LONG_LEN, "%lu", (unsigned long) stamp);
argv[2] = stamp_s;
lens[2] = strlen(stamp_s);
@ -284,7 +284,7 @@ int redis_key::pexpire(const char* key, size_t len, int n)
argv[1] = key;
lens[1] = len;
char buf[INT_LEN];
char* buf = (char*) dbuf_->dbuf_alloc(INT_LEN);
(void) safe_snprintf(buf, INT_LEN, "%d", n);
argv[2] = buf;
lens[2] = strlen(buf);
@ -422,8 +422,8 @@ bool redis_key::restore(const char* key, const char* value, size_t len,
argv[1] = key;
lens[1] = strlen(key);
char ttl_s[INT_LEN];
safe_snprintf(ttl_s, sizeof(ttl_s), "%d", nttl);
char* ttl_s = (char*) dbuf_->dbuf_alloc(INT_LEN);
safe_snprintf(ttl_s, INT_LEN, "%d", nttl);
argv[2] = ttl_s;
lens[2] = strlen(ttl_s);
@ -517,8 +517,8 @@ bool redis_key::migrate(const char* key, const char* addr, unsigned dest_db,
bool redis_key::migrate(const char* key, size_t len, const char* addr,
unsigned dest_db, unsigned timeout, const char* option /* = NULL */)
{
char addrbuf[64];
safe_snprintf(addrbuf, sizeof(addrbuf), "%s", addr);
char* addrbuf = (char*) dbuf_->dbuf_alloc(64);
safe_snprintf(addrbuf, 64, "%s", addr);
char* at = strchr(addrbuf, ':');
if (at == NULL || *(at + 1) == 0)
return false;
@ -540,13 +540,13 @@ bool redis_key::migrate(const char* key, size_t len, const char* addr,
argv[3] = key;
lens[3] = len;
char db_s[11];
safe_snprintf(db_s, sizeof(db_s), "%u", dest_db);
char* db_s = (char*) dbuf_->dbuf_alloc(11);
safe_snprintf(db_s, 11, "%u", dest_db);
argv[4] = db_s;
lens[4] = strlen(db_s);
char timeout_s[11];
safe_snprintf(timeout_s, sizeof(timeout_s), "%u", timeout);
char* timeout_s = (char*) dbuf_->dbuf_alloc(11);
safe_snprintf(timeout_s, 11, "%u", timeout);
argv[5] = timeout_s;
lens[5] = strlen(timeout_s);
@ -575,8 +575,8 @@ int redis_key::move(const char* key, size_t len, unsigned dest_db)
argv[1] = key;
lens[1] = len;
char db_s[11];
safe_snprintf(db_s, sizeof(db_s), "%u", dest_db);
char* db_s = (char*) dbuf_->dbuf_alloc(11);
safe_snprintf(db_s, 11, "%u", dest_db);
argv[2] = db_s;
lens[2] = strlen(db_s);

View File

@ -71,8 +71,8 @@ bool redis_list::lindex(const char* key, size_t idx, string& buf)
argv[1] = key;
lens[1] = strlen(key);
char tmp[LONG_LEN];
(void) safe_snprintf(tmp, sizeof(tmp), "%lu", (unsigned long) idx);
char* tmp = (char*) dbuf_->dbuf_alloc(LONG_LEN);
(void) safe_snprintf(tmp, LONG_LEN, "%lu", (unsigned long) idx);
argv[2] = tmp;
lens[2] = strlen(tmp);
@ -96,8 +96,8 @@ bool redis_list::lset(const char* key, int idx, const char* value, size_t len)
argv[1] = key;
lens[1] = strlen(key);
char tmp[LONG_LEN];
(void) safe_snprintf(tmp, sizeof(tmp), "%lu", (unsigned long) idx);
char* tmp = (char*) dbuf_->dbuf_alloc(LONG_LEN);
(void) safe_snprintf(tmp, LONG_LEN, "%lu", (unsigned long) idx);
argv[2] = tmp;
lens[2] = strlen(tmp);
@ -388,8 +388,8 @@ bool redis_list::bpop(const char* cmd, const std::vector<const char*>& keys,
i++;
}
char buf[LONG_LEN];
safe_snprintf(buf, sizeof(buf), "%lu", (unsigned long) timeout);
char* buf = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(buf, LONG_LEN, "%lu", (unsigned long) timeout);
args[i] = buf;
lens[i] = strlen(args[i]);
@ -415,8 +415,8 @@ bool redis_list::bpop(const char* cmd, const std::vector<string>& keys,
i++;
}
char buf[LONG_LEN];
safe_snprintf(buf, sizeof(buf), "%lu", (unsigned long) timeout);
char* buf = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(buf, LONG_LEN, "%lu", (unsigned long) timeout);
args[i] = buf;
lens[i] = strlen(args[i]);
@ -486,8 +486,8 @@ bool redis_list::brpoplpush(const char* src, const char* dst,
argv[2] = dst;
lens[2] = strlen(dst);
char tmp[LONG_LEN];
safe_snprintf(tmp, sizeof(tmp), "%lu", (unsigned long) timeout);
char* tmp = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(tmp, LONG_LEN, "%lu", (unsigned long) timeout);
argv[3] = tmp;
lens[3] = strlen(argv[3]);
@ -506,9 +506,10 @@ bool redis_list::lrange(const char* key, int start, int end,
argv[1] = key;
lens[1] = strlen(key);
char start_s[LONG_LEN], end_s[LONG_LEN];
safe_snprintf(start_s, sizeof(start_s), "%d", start);
safe_snprintf(end_s, sizeof(end_s), "%d", end);
char* start_s = (char*) dbuf_->dbuf_alloc(LONG_LEN);
char* end_s = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(start_s, LONG_LEN, "%d", start);
safe_snprintf(end_s, LONG_LEN, "%d", end);
argv[2] = start_s;
lens[2] = strlen(start_s);
@ -535,8 +536,8 @@ int redis_list::lrem(const char* key, int count, const char* value, size_t len)
argv[1] = key;
lens[1] = strlen(key);
char buf[INT_LEN];
safe_snprintf(buf, sizeof(buf), "%d", count);
char* buf = (char*) dbuf_->dbuf_alloc(INT_LEN);
safe_snprintf(buf, INT_LEN, "%d", count);
argv[2] = buf;
lens[2] = strlen(buf);
@ -558,9 +559,10 @@ bool redis_list::ltrim(const char* key, int start, int end)
argv[1] = key;
lens[1] = strlen(key);
char start_s[LONG_LEN], end_s[LONG_LEN];
safe_snprintf(start_s, sizeof(start_s), "%d", start);
safe_snprintf(end_s, sizeof(end_s), "%d", end);
char* start_s = (char*) dbuf_->dbuf_alloc(LONG_LEN);
char* end_s = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(start_s, LONG_LEN, "%d", start);
safe_snprintf(end_s, LONG_LEN, "%d", end);
argv[2] = start_s;
lens[2] = strlen(start_s);

View File

@ -1,6 +1,5 @@
#include "acl_stdafx.hpp"
#ifndef ACL_PREPARE_COMPILE
#include "acl_cpp/stdlib/snprintf.hpp"
#include "acl_cpp/stdlib/dbuf_pool.hpp"
#include "acl_cpp/stdlib/string.hpp"
#include "acl_cpp/redis/redis_client.hpp"

View File

@ -392,8 +392,8 @@ const redis_result* redis_script::eval_cmd(const char* cmd,
argv[1] = script;
lens[1] = strlen(script);
char buf[LONG_LEN];
safe_snprintf(buf, sizeof(buf), "%lu", (unsigned long) keys.size());
char* buf = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(buf, LONG_LEN, "%lu", (unsigned long) keys.size());
argv[2] = buf;
lens[2] = strlen(buf);
@ -437,8 +437,8 @@ const redis_result* redis_script::eval_cmd(const char* cmd,
argv[1] = script;
lens[1] = strlen(script);
char buf[LONG_LEN];
safe_snprintf(buf, sizeof(buf), "%lu", (unsigned long) keys.size());
char* buf = (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(buf, LONG_LEN, "%lu", (unsigned long) keys.size());
argv[2] = buf;
lens[2] = strlen(buf);

View File

@ -399,13 +399,13 @@ bool redis_sentinel::sentinel_monitor(const char* master_name, const char* ip,
argv[3] = ip;
lens[3] = strlen(ip);
char port_s[64];
safe_snprintf(port_s, sizeof(port_s), "%d", port);
char* port_s = (char*) dbuf_->dbuf_alloc(64);
safe_snprintf(port_s, 64, "%d", port);
argv[4] = port_s;
lens[4] = strlen(argv[4]);
char quorum_s[64];
safe_snprintf(quorum_s, sizeof(quorum_s), "%d", quorum);
char* quorum_s = (char*) dbuf_->dbuf_alloc(64);
safe_snprintf(quorum_s, 64, "%d", quorum);
argv[5] = quorum_s;
lens[5] = strlen(argv[5]);
@ -441,8 +441,8 @@ bool redis_sentinel::sentinel_set(const char* master_name, const char* name,
bool redis_sentinel::sentinel_set(const char* master_name, const char* name,
unsigned value)
{
char buf[64];
safe_snprintf(buf, sizeof(buf), "%u", value);
char* buf = (char*) dbuf_->dbuf_alloc(64);
safe_snprintf(buf, 64, "%u", value);
return sentinel_set(master_name, name, buf);
}

View File

@ -358,8 +358,8 @@ bool redis_server::slaveof(const char* ip, int port)
argv[1] = ip;
lens[1] = strlen(ip);
char port_s[INT_LEN];
safe_snprintf(port_s, sizeof(port_s), "%d", port);
char* port_s= (char*) dbuf_->dbuf_alloc(INT_LEN);
safe_snprintf(port_s, INT_LEN, "%d", port);
argv[2] = port_s;
lens[2] = strlen(port_s);
@ -380,9 +380,9 @@ const redis_result* redis_server::slowlog_get(int number /* = 0 */)
size_t argc = 2;
char buf[INT_LEN];
if (number > 0) {
safe_snprintf(buf, sizeof(buf), "%d", number);
char* buf = (char*) dbuf_->dbuf_alloc(INT_LEN);
safe_snprintf(buf, INT_LEN, "%d", number);
argv[2] = buf;
lens[2] = strlen(buf);
argc++;

View File

@ -380,8 +380,8 @@ int redis_set::srandmember(const char* key, size_t n, std::vector<string>& out)
argv[1] = key;
lens[1] = strlen(key);
char buf[LONG_LEN];
safe_snprintf(buf, sizeof(buf), "%lu", (unsigned long) n);
char* buf= (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(buf, LONG_LEN, "%lu", (unsigned long) n);
argv[2] = buf;
lens[2] = strlen(buf);

View File

@ -149,8 +149,8 @@ bool redis_stream::xadd_with_maxlen(const char* key, size_t maxlen,
argv_lens_[i] = 1;
i++;
char buf[LONG_LEN];
safe_snprintf(buf, sizeof(buf), "%ld", (long) maxlen);
char* buf= (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(buf, LONG_LEN, "%ld", (long) maxlen);
argv_[i] = buf;
argv_lens_[i] = strlen(buf);
i++;
@ -196,26 +196,25 @@ int redis_stream::xlen(const char* key)
void redis_stream::build(const std::map<string, string>& streams, size_t i,
size_t count, ssize_t block, bool noack /* = false */)
{
char count_s[LONG_LEN];
if (count > 0) {
argv_[i] = "COUNT";
argv_lens_[i] = sizeof("COUNT") - 1;
i++;
safe_snprintf(count_s, sizeof(count_s), "%lu",
(unsigned long) count);
char* count_s= (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(count_s, LONG_LEN, "%lu", (unsigned long) count);
argv_[i] = count_s;
argv_lens_[i] = strlen(count_s);
i++;
}
char block_s[LONG_LEN];
if (block >= 0) {
argv_[i] = "BLOCK";
argv_lens_[i] = sizeof("BLOCK") - 1;
i++;
safe_snprintf(block_s, sizeof(block_s), "%ld", (long) block);
char* block_s= (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(block_s, LONG_LEN, "%ld", (long) block);
argv_[i] = block_s;
argv_lens_[i] = strlen(block_s);
i++;
@ -359,14 +358,13 @@ bool redis_stream::range(redis_stream_messages& messages, const char* cmd,
lens[i] = strlen(end);
i++;
char count_s[LONG_LEN];
if (count > 0) {
argv[i] = "COUNT";
lens[i] = sizeof("COUNT") - 1;
i++;
safe_snprintf(count_s, sizeof(count_s), "%lu",
(unsigned long) count);
char* count_s= (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(count_s, LONG_LEN, "%lu", (unsigned long) count);
argv[i] = count_s;
lens[i] = strlen(count_s);
i++;
@ -545,8 +543,8 @@ void redis_stream::xclaim_build(const char* key, const char* group,
argv_lens_[i] = strlen(consumer);
i++;
char min_idle_s[LONG_LEN];
safe_snprintf(min_idle_s, sizeof(min_idle_s), "%lu", min_idle_time);
char* min_idle_s= (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(min_idle_s, LONG_LEN, "%lu", min_idle_time);
argv_[i] = min_idle_s;
argv_lens_[i] = strlen(min_idle_s);
i++;
@ -559,22 +557,23 @@ void redis_stream::xclaim_build(const char* key, const char* group,
i++;
}
char tbuf[LONG_LEN];
if (idle > 0) {
safe_snprintf(tbuf, sizeof(tbuf), "%lu", (unsigned long) idle);
char* tbuf= (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(tbuf, LONG_LEN, "%lu", (unsigned long) idle);
argv_[i] = tbuf;
argv_lens_[i] = strlen(tbuf);
i++;
} else if (time_ms > 0) {
safe_snprintf(tbuf, sizeof(tbuf), "%lld", time_ms);
char* tbuf= (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(tbuf, LONG_LEN, "%lld", time_ms);
argv_[i] = tbuf;
argv_lens_[i] = strlen(tbuf);
i++;
}
char retry_buf[INT_LEN];
if (retry_count > 0) {
safe_snprintf(retry_buf, sizeof(retry_buf), "%d", retry_count);
char* retry_buf= (char*) dbuf_->dbuf_alloc(INT_LEN);
safe_snprintf(retry_buf, INT_LEN, "%d", retry_count);
argv_[i] = retry_buf;
argv_lens_[i] = strlen(retry_buf);
i++;
@ -968,8 +967,8 @@ bool redis_stream::xpending_detail(redis_pending_detail& result,
lens[i] = strlen(end_id);
i++;
char count_s[LONG_LEN];
safe_snprintf(count_s, sizeof(count_s), "%lu", (unsigned long) count);
char* count_s= (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(count_s, LONG_LEN, "%lu", (unsigned long) count);
argv[i] = count_s;
lens[i] = strlen(count_s);
i++;
@ -1105,8 +1104,8 @@ int redis_stream::xtrim(const char* key, size_t maxlen, bool tilde)
i++;
}
char buf[LONG_LEN];
safe_snprintf(buf, sizeof(buf), "%lu", (unsigned long) maxlen);
char* buf= (char*) dbuf_->dbuf_alloc(LONG_LEN);
safe_snprintf(buf, LONG_LEN, "%lu", (unsigned long) maxlen);
argv[i] = buf;
lens[i] = strlen(buf);
i++;

View File

@ -104,8 +104,8 @@ bool redis_string::set(const char* key, size_t key_len, const char* value,
goto NEXT_X;
}
char buf[INT_LEN];
(void) safe_snprintf(buf, sizeof(buf), "%d", timeout);
char* buf= (char*) dbuf_->dbuf_alloc(INT_LEN);
(void) safe_snprintf(buf, INT_LEN, "%d", timeout);
argv[n] = buf;
lens[n] = strlen(buf);
n++;
@ -144,8 +144,8 @@ bool redis_string::setex(const char* key, size_t key_len, const char* value,
argv[1] = key;
lens[1] = key_len;
char buf[INT_LEN];
(void) safe_snprintf(buf, sizeof(buf), "%d", timeout);
char* buf= (char*) dbuf_->dbuf_alloc(INT_LEN);
(void) safe_snprintf(buf, INT_LEN, "%d", timeout);
argv[2] = buf;
lens[2] = strlen(buf);
@ -174,8 +174,8 @@ bool redis_string::psetex(const char* key, size_t key_len, const char* value,
argv[1] = key;
lens[1] = key_len;
char buf[INT_LEN];
(void) safe_snprintf(buf, sizeof(buf), "%d", timeout);
char* buf= (char*) dbuf_->dbuf_alloc(INT_LEN);
(void) safe_snprintf(buf, INT_LEN, "%d", timeout);
argv[2] = buf;
lens[2] = strlen(buf);
@ -378,12 +378,13 @@ bool redis_string::getrange(const char* key, size_t key_len,
argv[1] = key;
lens[1] = key_len;
char start_buf[INT_LEN], end_buf[INT_LEN];
(void) safe_snprintf(start_buf, sizeof(start_buf), "%d", start);
char* start_buf= (char*) dbuf_->dbuf_alloc(INT_LEN);
(void) safe_snprintf(start_buf, INT_LEN, "%d", start);
argv[2] = start_buf;
lens[2] = strlen(start_buf);
(void) safe_snprintf(end_buf, sizeof(end_buf), "%d", end);
char* end_buf= (char*) dbuf_->dbuf_alloc(INT_LEN);
(void) safe_snprintf(end_buf, INT_LEN, "%d", end);
argv[3] = end_buf;
lens[3] = strlen(end_buf);
@ -411,8 +412,8 @@ bool redis_string::setbit_(const char* key, size_t len,
argv[1] = key;
lens[1] = len;
char buf4off[INT_LEN];
(void) safe_snprintf(buf4off, sizeof(buf4off), "%d", offset);
char* buf4off= (char*) dbuf_->dbuf_alloc(INT_LEN);
(void) safe_snprintf(buf4off, INT_LEN, "%d", offset);
argv[2] = buf4off;
lens[2] = strlen(buf4off);
@ -441,8 +442,8 @@ bool redis_string::getbit(const char* key, size_t len,
argv[1] = key;
lens[1] = len;
char buf4off[INT_LEN];
(void) safe_snprintf(buf4off, sizeof(buf4off), "%d", offset);
char* buf4off= (char*) dbuf_->dbuf_alloc(INT_LEN);
(void) safe_snprintf(buf4off, INT_LEN, "%d", offset);
argv[2] = buf4off;
lens[2] = strlen(buf4off);
@ -492,13 +493,13 @@ int redis_string::bitcount(const char* key, size_t len, int start, int end)
argv[1] = key;
lens[1] = len;
char buf4start[INT_LEN];
(void) safe_snprintf(buf4start, sizeof(buf4start), "%d", start);
char* buf4start= (char*) dbuf_->dbuf_alloc(INT_LEN);
(void) safe_snprintf(buf4start, INT_LEN, "%d", start);
argv[2] = buf4start;
lens[2] = strlen(buf4start);
char buf4end[INT_LEN];
(void) safe_snprintf(buf4end, sizeof(buf4end), "%d", end);
char* buf4end= (char*) dbuf_->dbuf_alloc(INT_LEN);
(void) safe_snprintf(buf4end, INT_LEN, "%d", end);
argv[3] = buf4end;
lens[3] = strlen(buf4end);
@ -800,8 +801,8 @@ bool redis_string::incrbyfloat(const char* key, double inc,
argv[1] = key;
lens[1] = strlen(key);
char buf[FLOAT_LEN];
(void) safe_snprintf(buf, sizeof(buf), "%f", inc);
char* buf= (char*) dbuf_->dbuf_alloc(FLOAT_LEN);
(void) safe_snprintf(buf, FLOAT_LEN, "%f", inc);
argv[2] = buf;
lens[2] = strlen(buf);

View File

@ -344,8 +344,8 @@ bool redis_zset::zadd_with_incr(const char* key, const char* member,
i++;
}
char score_s[BUFLEN];
safe_snprintf(score_s, sizeof(score_s), "%.8f", score);
char* score_s= (char*) dbuf_->dbuf_alloc(BUFLEN);
safe_snprintf(score_s, BUFLEN, "%.8f", score);
argv[i] = score_s;
lens[i] = strlen(score_s);
i++;
@ -410,9 +410,10 @@ int redis_zset::zcount(const char* key, double min, double max)
argv[1] = key;
lens[1] = strlen(key);
char min_buf[BUFLEN], max_buf[BUFLEN];
safe_snprintf(min_buf, sizeof(min_buf), "%.8f", min);
safe_snprintf(max_buf, sizeof(max_buf), "%.8f", max);
char* min_buf= (char*) dbuf_->dbuf_alloc(BUFLEN);
char* max_buf= (char*) dbuf_->dbuf_alloc(BUFLEN);
safe_snprintf(min_buf, BUFLEN, "%.8f", min);
safe_snprintf(max_buf, BUFLEN, "%.8f", max);
argv[2] = min_buf;
lens[2] = strlen(min_buf);
@ -443,8 +444,8 @@ bool redis_zset::zincrby(const char* key, double inc,
argv[1] = key;
lens[1] = strlen(key);
char score[BUFLEN];
safe_snprintf(score, sizeof(score), "%.8f", inc);
char* score= (char*) dbuf_->dbuf_alloc(BUFLEN);
safe_snprintf(score, BUFLEN, "%.8f", inc);
argv[2] = score;
lens[2] = strlen(score);
@ -474,9 +475,10 @@ int redis_zset::zrange_get(const char* cmd, const char* key, int start,
argv[1] = key;
lens[1] = strlen(key);
char start_s[INTLEN], stop_s[INTLEN];
safe_snprintf(start_s, sizeof(start_s), "%d", start);
safe_snprintf(stop_s, sizeof(stop_s), "%d", stop);
char* start_s= (char*) dbuf_->dbuf_alloc(INTLEN);
char* stop_s= (char*) dbuf_->dbuf_alloc(INTLEN);
safe_snprintf(start_s, INTLEN, "%d", start);
safe_snprintf(stop_s, INTLEN, "%d", stop);
argv[2] = start_s;
lens[2] = strlen(start_s);
@ -550,9 +552,10 @@ int redis_zset::zrange_get_with_scores(const char* cmd, const char* key,
argv[1] = key;
lens[1] = strlen(key);
char start_s[INTLEN], stop_s[INTLEN];
safe_snprintf(start_s, sizeof(start_s), "%d", start);
safe_snprintf(stop_s, sizeof(stop_s), "%d", stop);
char* start_s= (char*) dbuf_->dbuf_alloc(INTLEN);
char* stop_s= (char*) dbuf_->dbuf_alloc(INTLEN);
safe_snprintf(start_s, INTLEN, "%d", start);
safe_snprintf(stop_s, INTLEN, "%d", stop);
argv[2] = start_s;
lens[2] = strlen(start_s);
@ -595,10 +598,11 @@ int redis_zset::zrangebyscore_get(const char* cmd, const char* key,
argv[3] = max;
lens[3] = strlen(max);
char offset_s[INTLEN], count_s[INTLEN];
if (offset && count) {
safe_snprintf(offset_s, sizeof(offset_s), "%d", *offset);
safe_snprintf(count_s, sizeof(count_s), "%d", *count);
char* offset_s= (char*) dbuf_->dbuf_alloc(INTLEN);
char* count_s= (char*) dbuf_->dbuf_alloc(INTLEN);
safe_snprintf(offset_s, INTLEN, "%d", *offset);
safe_snprintf(count_s, INTLEN, "%d", *count);
argv[4] = "LIMIT";
lens[4] = sizeof("LIMIT") - 1;
@ -629,9 +633,10 @@ int redis_zset::zrangebyscore(const char* key, double min,
double max, std::vector<string>* out,
const int* offset /* = NULL */, const int* count /* = NULL */)
{
char min_s[BUFLEN], max_s[BUFLEN];
safe_snprintf(min_s, sizeof(min_s), "%.8f", min);
safe_snprintf(max_s, sizeof(max_s), "%.8f", max);
char* min_s= (char*) dbuf_->dbuf_alloc(BUFLEN);
char* max_s= (char*) dbuf_->dbuf_alloc(BUFLEN);
safe_snprintf(min_s, BUFLEN, "%.8f", min);
safe_snprintf(max_s, BUFLEN, "%.8f", max);
return zrangebyscore(key, min_s, max_s, out, offset, count);
}
@ -660,10 +665,11 @@ int redis_zset::zrangebyscore_get_with_scores(const char* cmd,
argv[4] = "WITHSCORES";
lens[4] = sizeof("WITHSCORES") - 1;
char offset_s[INTLEN], count_s[INTLEN];
if (offset && count) {
safe_snprintf(offset_s, sizeof(offset_s), "%d", *offset);
safe_snprintf(count_s, sizeof(count_s), "%d", *count);
char* offset_s = (char*) dbuf_->dbuf_alloc(INTLEN);
char* count_s = (char*) dbuf_->dbuf_alloc(INTLEN);
safe_snprintf(offset_s, INTLEN, "%d", *offset);
safe_snprintf(count_s, INTLEN, "%d", *count);
argv[5] = "LIMIT";
lens[5] = sizeof("LIMIT") - 1;
@ -695,9 +701,10 @@ int redis_zset::zrangebyscore_with_scores(const char* key, double min,
double max, std::vector<std::pair<string, double> >& out,
const int* offset /* = NULL */, const int* count /* = NULL */)
{
char min_s[BUFLEN], max_s[BUFLEN];
safe_snprintf(min_s, sizeof(min_s), "%.8f", min);
safe_snprintf(max_s, sizeof(max_s), "%.8f", max);
char* min_s = (char*) dbuf_->dbuf_alloc(BUFLEN);
char* max_s = (char*) dbuf_->dbuf_alloc(BUFLEN);
safe_snprintf(min_s, BUFLEN, "%.8f", min);
safe_snprintf(max_s, BUFLEN, "%.8f", max);
return zrangebyscore_with_scores(key, min_s, max_s, out, offset, count);
}
@ -772,9 +779,10 @@ int redis_zset::zremrangebyrank(const char* key, int start, int stop)
argv[1] = key;
lens[1] = strlen(key);
char start_s[INTLEN], stop_s[INTLEN];
safe_snprintf(start_s, sizeof(start_s), "%d", start);
safe_snprintf(stop_s, sizeof(stop_s), "%d", stop);
char* start_s = (char*) dbuf_->dbuf_alloc(INTLEN);
char*stop_s = (char*) dbuf_->dbuf_alloc(INTLEN);
safe_snprintf(start_s, INTLEN, "%d", start);
safe_snprintf(stop_s, INTLEN, "%d", stop);
argv[2] = start_s;
lens[2] = strlen(start_s);
@ -789,9 +797,10 @@ int redis_zset::zremrangebyrank(const char* key, int start, int stop)
int redis_zset::zremrangebyscore(const char* key, double min, double max)
{
char min_s[BUFLEN], max_s[BUFLEN];
safe_snprintf(min_s, sizeof(min_s), "%.8f", min);
safe_snprintf(max_s, sizeof(max_s), "%.8f", max);
char* min_s = (char*) dbuf_->dbuf_alloc(BUFLEN);
char* max_s = (char*) dbuf_->dbuf_alloc(BUFLEN);
safe_snprintf(min_s, BUFLEN, "%.8f", min);
safe_snprintf(max_s, BUFLEN, "%.8f", max);
return zremrangebyscore(key, min_s, max_s);
}
@ -843,9 +852,10 @@ int redis_zset::zrevrangebyscore_with_scores(const char* key, double min,
double max, std::vector<std::pair<string, double> >& out,
const int* offset /* = NULL */, const int* count /* = NULL */)
{
char min_s[BUFLEN], max_s[BUFLEN];
safe_snprintf(min_s, sizeof(min_s), "%.8f", min);
safe_snprintf(max_s, sizeof(max_s), "%.8f", max);
char* min_s = (char*) dbuf_->dbuf_alloc(BUFLEN);
char* max_s = (char*) dbuf_->dbuf_alloc(BUFLEN);
safe_snprintf(min_s, BUFLEN, "%.8f", min);
safe_snprintf(max_s, BUFLEN, "%.8f", max);
return zrevrangebyscore_with_scores(key, min_s, max_s,
out, offset, count);
@ -925,8 +935,8 @@ int redis_zset::zstore(const char* cmd, const char* dst,
argv[1] = dst;
lens[1] = strlen(dst);
char num_s[BUFLEN];
safe_snprintf(num_s, sizeof(num_s), "%d", (int) num);
char* num_s = (char*) dbuf_->dbuf_alloc(INTLEN);
safe_snprintf(num_s, INTLEN, "%d", (int) num);
argv[2] = num_s;
lens[2] = strlen(num_s);
@ -1002,8 +1012,8 @@ int redis_zset::zstore(const char* cmd, const char* dst,
argv[1] = dst;
lens[1] = strlen(dst);
char num_s[INTLEN];
safe_snprintf(num_s, sizeof(num_s), "%d", (int) keys.size());
char* num_s = (char*) dbuf_->dbuf_alloc(INTLEN);
safe_snprintf(num_s, INTLEN, "%d", (int) keys.size());
argv[2] = num_s;
lens[2] = strlen(num_s);
@ -1201,8 +1211,8 @@ int redis_zset::zpop(const char* cmd, const char* key,
argv[1] = key;
lens[1] = strlen(key);
char count_s[BUFLEN];
safe_snprintf(count_s, sizeof(count_s), "%lu", (unsigned long) count);
char* count_s = (char*) dbuf_->dbuf_alloc(BUFLEN);
safe_snprintf(count_s, BUFLEN, "%lu", (unsigned long) count);
argv[2] = count_s;
lens[2] = strlen(count_s);
argc = 3;
@ -1251,8 +1261,8 @@ int redis_zset::bzpop(const char* cmd, const char* key, size_t timeout,
argv[1] = key;
lens[1] = strlen(key);
char buf[BUFLEN];
safe_snprintf(buf, sizeof(buf), "%lu", (unsigned long) timeout);
char* buf = (char*) dbuf_->dbuf_alloc(BUFLEN);
safe_snprintf(buf, BUFLEN, "%lu", (unsigned long) timeout);
argv[2] = buf;
lens[2] = strlen(buf);
@ -1278,8 +1288,8 @@ int redis_zset::bzpop(const char* cmd, const std::vector<string>& keys,
i++;
}
char buf[BUFLEN];
safe_snprintf(buf, sizeof(buf), "%lu", (unsigned long) timeout);
char* buf = (char*) dbuf_->dbuf_alloc(BUFLEN);
safe_snprintf(buf, BUFLEN, "%lu", (unsigned long) timeout);
argv_[i] = buf;
argv_lens_[i] = strlen(buf);
build_request(argc_, argv_, argv_lens_);

View File

@ -89,7 +89,7 @@ bool server_socket::opened(void) const
bool server_socket::open(const char* addr)
{
if (fd_ != ACL_SOCKET_INVALID) {
logger_error("listen fd already opened");
logger_error("listen fd already opened, fd_=%d", (int) fd_);
return true;
}

View File

@ -57,6 +57,7 @@ add_definitions(
"-Wno-long-long"
"-Wuninitialized"
# "-DUSE_JMP"
# "-DSHARE_STACK"
"-DUSE_FAST_RING"
"-D_POSIX_PTHREAD_SEMANTICS"
"-DACL_PREPARE_COMPILE"

View File

@ -7,7 +7,9 @@ ARFL = rv
#ARFL = cru
RANLIB = ${ENV_RANLIB}
#JMP_CTX = DUMMY
JMP_CTX = USE_JMP_DEF
#JMP_CTX = USE_BOOST_JMP
CFLAGS = -c -g -W \
-std=gnu99 \
@ -22,8 +24,7 @@ CFLAGS = -c -g -W \
-Wmissing-prototypes \
-Wcast-qual \
-DUSE_FAST_RING \
#-DUSE_JMP_DEF \
#-DUSE_BOOST_JMP \
#-DSHARE_STACK \
#-DUSE_VALGRIND \
#-DUSE_FAST_TIME \
#-Waggregate-return \
@ -70,10 +71,10 @@ ifeq ($(findstring gcc, $(CC)), gcc)
GCC_MINOR:=$(shell echo "$(GCC_VERSION)" | cut -d'.' -f2)
GCC_SUB:=$(shell echo "$(GCC_VERSION)" | cut -d'.' -f3)
GCC_VER:=$(shell [ $(GCC_MAJOR) -gt 4 -o \( $(GCC_MAJOR) -eq 4 -a $(GCC_MINOR) -gt 4 \) ] && echo true)
ifeq ($(GCC_VER), true)
CFLAGS += -Wno-implicit-fallthrough
CFLAGS += -Wno-absolute-value
endif
# ifeq ($(GCC_VER), true)
# CFLAGS += -Wno-implicit-fallthrough
# CFLAGS += -Wno-absolute-value
# endif
endif
ifeq ($(findstring clang, $(CC)), clang)

View File

@ -8,7 +8,18 @@
extern "C" {
#endif
typedef ACL_FIBER *((*FIBER_ALLOC_FN)(void (*)(ACL_FIBER *), size_t));
typedef struct ACL_FIBER_ATTR {
unsigned int oflag;
#define ACL_FIBER_ATTR_SHARE_STACK (unsigned) 1 << 0
size_t stack_size;
} ACL_FIBER_ATTR;
void acl_fiber_attr_init(ACL_FIBER_ATTR *attr);
void acl_fiber_attr_setstacksize(ACL_FIBER_ATTR *attr, size_t size);
void acl_fiber_attr_setsharestack(ACL_FIBER_ATTR *attr, int on);
typedef ACL_FIBER *((*FIBER_ALLOC_FN)(void (*)(ACL_FIBER *), const ACL_FIBER_ATTR *));
typedef ACL_FIBER *((*FIBER_ORIGIN_FN)(void));
FIBER_API void acl_fiber_register(FIBER_ALLOC_FN alloc_fn,
@ -17,19 +28,31 @@ FIBER_API void acl_fiber_register(FIBER_ALLOC_FN alloc_fn,
FIBER_API ACL_FIBER *acl_fiber_alloc(size_t size, void **pptr);
/**
* set flag if the system API should be hooked, default value is 1 internal
* Set flag if the system API should be hooked, default value is 1 internal
* @param onoff {int} if need to hook the system API
*/
FIBER_API void acl_fiber_hook_api(int onoff);
/**
* set the global flag that if in non-blocking status, just for windows
* Set the global flag that if in non-blocking status, just for windows
* @param yes {int} set in non-blocking status global if yes not 0
*/
FIBER_API void acl_fiber_set_non_blocking(int yes);
/**
* create and start one fiber
* Set the shared stack's memory size in shared stack mode
* @param size {size_t} must more than 1024 for shared stack mode.
*/
FIBER_API void acl_fiber_set_shared_stack_size(size_t size);
/**
* Get the shared stack's memory size if shared stack was enabled
* @return {size_t} return > 0 if shared stack was enabled, or return 0.
*/
FIBER_API size_t acl_fiber_get_shared_stack_size(void);
/**
* Create and start one fiber
* @param fn {void (*)(ACL_FIBER*, void*)} the callback of fiber running
* @param arg {void*} the second parameter of the callback fn
* @param size {size_t} the virual memory size of the fiber created
@ -38,46 +61,56 @@ FIBER_API void acl_fiber_set_non_blocking(int yes);
FIBER_API ACL_FIBER* acl_fiber_create(void (*fn)(ACL_FIBER*, void*),
void* arg, size_t size);
FIBER_API ACL_FIBER* acl_fiber_create2(const ACL_FIBER_ATTR *attr,
void (*fn)(ACL_FIBER*, void*), void* arg);
/**
* get the fibers count in deading status
* Get the fibers count in deading status
* @return {unsigned}
*/
FIBER_API unsigned acl_fiber_ndead(void);
/**
* get the fibers count in aliving status
* Get the fibers count in aliving status
* @return {unsigned}
*/
FIBER_API unsigned acl_fiber_number(void);
/**
* create one fiber in background for freeing the dead fibers, specify the
* Create one fiber in background for freeing the dead fibers, specify the
* maximum fibers in every recyling process
* @param max {size_t} the maximum fibers to freed in every recyling process
*/
FIBER_API void acl_fiber_check_timer(size_t max);
/**
* get the current running fiber
* Get the current running fiber
* @retur {ACL_FIBER*} if no running fiber NULL will be returned
*/
FIBER_API ACL_FIBER* acl_fiber_running(void);
/**
* get the fiber ID of the specified fiber
* If the fiber using shared stack?
* @param fiber {const ACL_FIBER*}
* @return {int} return 0 if using private stack, or the shared stack was used
*/
FIBER_API int acl_fiber_use_share_stack(const ACL_FIBER *fiber);
/**
* Get the fiber ID of the specified fiber
* @param fiber {const ACL_FIBER*} the specified fiber object
* @return {unsigned int} return the fiber ID
*/
FIBER_API unsigned int acl_fiber_id(const ACL_FIBER* fiber);
/**
* get the current running fiber's ID
* Get the current running fiber's ID
* @return {unsigned int} the current fiber's ID
*/
FIBER_API unsigned int acl_fiber_self(void);
/**
* set the error number to the specified fiber object
* Set the error number to the specified fiber object
* @param fiber {ACL_FIBER*} the specified fiber, if NULL the current running
* fiber will be used
* @param errnum {int} the error number
@ -85,7 +118,7 @@ FIBER_API unsigned int acl_fiber_self(void);
FIBER_API void acl_fiber_set_errno(ACL_FIBER* fiber, int errnum);
/**
* get the error number of assosiated fiber
* Get the error number of assosiated fiber
* @param fiber {ACL_FIBER*} the specified fiber, if NULL the current running
* @return {int} get the error number of assosiated fiber
*/
@ -99,79 +132,79 @@ FIBER_API int acl_fiber_errno(ACL_FIBER* fiber);
FIBER_API void acl_fiber_keep_errno(ACL_FIBER* fiber, int yesno);
/**
* get the assosiated fiber's status
* Get the assosiated fiber's status
* @param fiber {ACL_FIBER*} the specified fiber, if NULL the current running
* @return {int}
*/
FIBER_API int acl_fiber_status(const ACL_FIBER* fiber);
/**
* kill the suspended fiber and notify it to exit
* Kill the suspended fiber and notify it to exit
* @param fiber {const ACL_FIBER*} the specified fiber, NOT NULL
*/
FIBER_API void acl_fiber_kill(ACL_FIBER* fiber);
/**
* check if the specified fiber has been killed
* Check if the specified fiber has been killed
* @param fiber {ACL_FIBER*} the specified fiber, if NULL the current running
* @return {int} non zero returned if been killed
*/
FIBER_API int acl_fiber_killed(ACL_FIBER* fiber);
/**
* check if the specified fiber has been signaled
* Check if the specified fiber has been signaled
* @param fiber {ACL_FIBER*} the specified fiber, if NULL the current running
* @return {int} non zero returned if been signed
*/
FIBER_API int acl_fiber_signaled(ACL_FIBER* fiber);
/**
* check if the specified fiber's socket has been closed by another fiber
* Check if the specified fiber's socket has been closed by another fiber
* @param fiber {ACL_FIBER*} the specified fiber, if NULL the current running
* @return {int} non zero returned if been closed
*/
FIBER_API int acl_fiber_closed(ACL_FIBER* fiber);
/**
* check if the specified fiber has been canceled
* Check if the specified fiber has been canceled
* @param fiber {ACL_FIBER*} the specified fiber, if NULL the current running
* @return {int} non zero returned if been canceled
*/
FIBER_API int acl_fiber_canceled(ACL_FIBER* fiber);
/**
* wakeup the suspended fiber with the assosiated signal number
* Wakeup the suspended fiber with the assosiated signal number
* @param fiber {const ACL_FIBER*} the specified fiber, NOT NULL
* @param signum {int} SIGINT, SIGKILL, SIGTERM ... refer to bits/signum.h
*/
FIBER_API void acl_fiber_signal(ACL_FIBER* fiber, int signum);
/**
* get the signal number got from other fiber
* Get the signal number got from other fiber
* @param fiber {ACL_FIBER*} the specified fiber, if NULL the current running
* @retur {int} the signal number got
*/
FIBER_API int acl_fiber_signum(ACL_FIBER* fiber);
/**
* suspend the current running fiber
* Suspend the current running fiber
* @return {int}
*/
FIBER_API int acl_fiber_yield(void);
/**
* add the suspended fiber into resuming queue
* Add the suspended fiber into resuming queue
* @param fiber {ACL_FIBER*} the fiber, NOT NULL
*/
FIBER_API void acl_fiber_ready(ACL_FIBER* fiber);
/**
* suspend the current fiber and switch to run the next ready fiber
* Suspend the current fiber and switch to run the next ready fiber
*/
FIBER_API void acl_fiber_switch(void);
/**
* set the fiber schedule process with automatically, in this way, when one
* Set the fiber schedule process with automatically, in this way, when one
* fiber was created, the schedule process will start automatically, but only
* the first fiber was started, so you can create the other fibers in this
* fiber. The default schedule mode is non-automatically, you should call the
@ -180,13 +213,13 @@ FIBER_API void acl_fiber_switch(void);
FIBER_API void acl_fiber_schedule_init(int on);
/**
* start the fiber schedule process, the fibers in the ready quque will be
* Start the fiber schedule process, the fibers in the ready quque will be
* started in sequence.
*/
FIBER_API void acl_fiber_schedule(void);
/**
* start the fiber schedule process with the specified event type, the default
* Start the fiber schedule process with the specified event type, the default
* event type is FIBER_EVENT_KERNEL. acl_fiber_schedule using the default
* event type. FIBER_EVENT_KERNEL is diffrent for diffrent OS platform:
* Linux: epoll; BSD: kqueue; Windows: iocp.
@ -199,39 +232,39 @@ FIBER_API void acl_fiber_schedule(void);
FIBER_API void acl_fiber_schedule_with(int event_mode);
/**
* set the event type, the default type is FIBER_EVENT_KERNEL, this function
* Set the event type, the default type is FIBER_EVENT_KERNEL, this function
* must be called before acl_fiber_schedule.
* @param event_mode {int} the event type, defined as FIBER_EVENT_XXX
*/
FIBER_API void acl_fiber_schedule_set_event(int event_mode);
/**
* check if the current thread is in fiber schedule status
* Check if the current thread is in fiber schedule status
* @return {int} non zero returned if in fiber schedule status
*/
FIBER_API int acl_fiber_scheduled(void);
/**
* stop the fiber schedule process, all fibers will be stopped
* Stop the fiber schedule process, all fibers will be stopped
*/
FIBER_API void acl_fiber_schedule_stop(void);
/**
* let the current fiber sleep for a while
* Let the current fiber sleep for a while
* @param milliseconds {unsigned int} the milliseconds to sleep
* @return {unsigned int} the rest milliseconds returned after wakeup
*/
FIBER_API unsigned int acl_fiber_delay(unsigned int milliseconds);
/**
* let the current fiber sleep for a while
* Let the current fiber sleep for a while
* @param seconds {unsigned int} the seconds to sleep
* @return {unsigned int} the rest seconds returned after wakeup
*/
FIBER_API unsigned int acl_fiber_sleep(unsigned int seconds);
/**
* create one fiber timer
* Create one fiber timer
* @param milliseconds {unsigned int} the timer wakeup milliseconds
* @param size {size_t} the virtual memory of the created fiber
* @param fn {void (*)(ACL_FIBER*, void*)} the callback when fiber wakeup
@ -242,23 +275,23 @@ FIBER_API ACL_FIBER* acl_fiber_create_timer(unsigned int milliseconds,
size_t size, void (*fn)(ACL_FIBER*, void*), void* ctx);
/**
* reset the timer milliseconds time before the timer fiber wakeup
* Reset the timer milliseconds time before the timer fiber wakeup
* @param timer {ACL_FIBER*} the fiber created by acl_fiber_create_timer
* @param milliseconds {unsigned int} the new timer wakeup milliseconds
*/
FIBER_API void acl_fiber_reset_timer(ACL_FIBER* timer, unsigned int milliseconds);
/**
* set the DNS service addr
* Set the DNS service addr
* @param ip {const char*} ip of the DNS service
* @param port {int} port of the DNS service
*/
FIBER_API void acl_fiber_set_dns(const char* ip, int port);
/* for fiber specific */
/* For fiber specific */
/**
* set the current fiber's local object
* Set the current fiber's local object
* @param key {int*} the addr of indexed key, its initial value should <= 0,
* and one integer which > 0 will be set for it; the fiber local object will
* be assosiated with the indexed key.
@ -271,7 +304,7 @@ FIBER_API void acl_fiber_set_dns(const char* ip, int port);
FIBER_API int acl_fiber_set_specific(int* key, void* ctx, void (*free_fn)(void*));
/**
* get the current fiber's local object assosiated with the specified indexed key
* Get the current fiber's local object assosiated with the specified indexed key
* @param key {int} the integer value returned by acl_fiber_set_specific
* @retur {void*} NULL returned if no fiber local object with the specified key
*/
@ -280,7 +313,7 @@ FIBER_API void* acl_fiber_get_specific(int key);
/****************************************************************************/
/**
* log function type used in fiber logging process, should be set by the
* Log function type used in fiber logging process, should be set by the
* function acl_fiber_msg_pre_write
* @param ctx {void*} the user's context
* @param fmt {const char*} format of parameters
@ -289,7 +322,7 @@ FIBER_API void* acl_fiber_get_specific(int key);
typedef void (*FIBER_MSG_PRE_WRITE_FN)(void *ctx, const char *fmt, va_list ap);
/**
* log function type used in fiber logging process, should be set by the
* Log function type used in fiber logging process, should be set by the
* function acl_fiber_msg_register. This can be used by user for get the
* logging information of fiber
* @param ctx {void*} the user's context
@ -299,44 +332,44 @@ typedef void (*FIBER_MSG_PRE_WRITE_FN)(void *ctx, const char *fmt, va_list ap);
typedef void (*FIBER_MSG_WRITE_FN) (void *ctx, const char *fmt, va_list ap);
/**
* set the user's log saving function when process started
* Set the user's log saving function when process started
* @param write_fn {MSG_WRITE_FN} log function defined by the user
* @param ctx {void*} parameter will be transfered to write_fn
*/
FIBER_API void acl_fiber_msg_register(FIBER_MSG_WRITE_FN write_fn, void *ctx);
/**
* cleanup the registered log callback by acl_fiber_msg_register
* Cleanup the registered log callback by acl_fiber_msg_register
*/
FIBER_API void acl_fiber_msg_unregister(void);
/**
* register the user's callback
* Register the user's callback
* @param pre_write {MSG_PRE_WRITE_FN}
* @param ctx {void*}
*/
FIBER_API void acl_fiber_msg_pre_write(FIBER_MSG_PRE_WRITE_FN pre_write, void *ctx);
/**
* if showing the fiber schedule process's log to stdout
* If showing the fiber schedule process's log to stdout
* @param onoff {int} log will be showed to stdout if onoff isn't 0
*/
FIBER_API void acl_fiber_msg_stdout_enable(int onoff);
/**
* get the system error number of last system API calling
* Get the system error number of last system API calling
* @return {int} error number
*/
FIBER_API int acl_fiber_last_error(void);
/**
* get the error information of last system API calling
* Get the error information of last system API calling
* @return {const char*}
*/
FIBER_API const char *acl_fiber_last_serror(void);
/**
* convert errno to string
* Convert errno to string
* @param errnum {int}
* @param buf {char*} hold the result
* @param size {size_t} buf's size
@ -345,13 +378,13 @@ FIBER_API const char *acl_fiber_last_serror(void);
FIBER_API const char *acl_fiber_strerror(int errnum, char *buf, size_t size);
/**
* set the system error number
* Set the system error number
* @param errnum {int} the error number
*/
FIBER_API void acl_fiber_set_error(int errnum);
/**
* set the fd limit for the current process
* Set the fd limit for the current process
* @param limit {int} the fd limit to be set
* @return {int} the real fd limit will be returned
*/

View File

@ -7,15 +7,15 @@
extern "C" {
#endif
/* channel communication */
/* Channel communication */
/**
* the fiber channel type definition
* The fiber channel type definition
*/
typedef struct ACL_CHANNEL ACL_CHANNEL;
/**
* create one fiber channel
* Create one fiber channel
* @param elemsize {int} the fixed object size transfered in fiber channel
* @param bufsize {int} the buffered of objects in fiber channel
* @return {ACL_CHANNNEL*}
@ -23,13 +23,13 @@ typedef struct ACL_CHANNEL ACL_CHANNEL;
FIBER_API ACL_CHANNEL* acl_channel_create(int elemsize, int bufsize);
/**
* free fiber channel created by acl_channel_create
* Free fiber channel created by acl_channel_create
* @param c {ACL_CHANNEL*} created by acl_channel_create
*/
FIBER_API void acl_channel_free(ACL_CHANNEL* c);
/**
* send object to specified fiber channel in block mode
* Send object to specified fiber channel in block mode
* @param c {ACL_CHANNEL*} created by acl_channel_create
* @param v {void*} the object to be transfered
* @return {int} value (>= 0) returned
@ -37,7 +37,7 @@ FIBER_API void acl_channel_free(ACL_CHANNEL* c);
FIBER_API int acl_channel_send(ACL_CHANNEL* c, void* v);
/**
* send object to specified fiber channel in non-block mode, one new object
* Send object to specified fiber channel in non-block mode, one new object
* copied from which will be created internal
* @param c {ACL_CHANNEL*} created by acl_channel_create
* @param v {void*} the object to be transfered
@ -46,7 +46,7 @@ FIBER_API int acl_channel_send(ACL_CHANNEL* c, void* v);
FIBER_API int acl_channel_send_nb(ACL_CHANNEL* c, void* v);
/**
* read one object from specified channel in block mode
* Read one object from specified channel in block mode
* @param c {ACL_CHANNEL*} created by acl_channel_create
* @param v {void*} will store the result
* @return {int} value(>= 0) returned if get one object
@ -54,7 +54,7 @@ FIBER_API int acl_channel_send_nb(ACL_CHANNEL* c, void* v);
FIBER_API int acl_channel_recv(ACL_CHANNEL* c, void* v);
/**
* read one object from specified channel in non-block ode
* Read one object from specified channel in non-block ode
* @param c {ACL_CHANNEL*} created by acl_channel_create
* @param v {void*} will store the result
* @return {int} value(>= 0) returned if get one object, or NULL returned if
@ -63,7 +63,7 @@ FIBER_API int acl_channel_recv(ACL_CHANNEL* c, void* v);
FIBER_API int acl_channel_recv_nb(ACL_CHANNEL* c, void* v);
/**
* send object's addr to specified channel in block mode
* Send object's addr to specified channel in block mode
* @param c {ACL_CHANNEL*} created by acl_channel_create
* @param v {void*} the addr of the object to be transfered
* @return {int} value (>= 0) returned
@ -71,14 +71,14 @@ FIBER_API int acl_channel_recv_nb(ACL_CHANNEL* c, void* v);
FIBER_API int acl_channel_sendp(ACL_CHANNEL* c, void* v);
/**
* get object's addr from specified channel in block mode
* Get object's addr from specified channel in block mode
* @param c {ACL_CHANNEL*} created by acl_channel_create
* @return {void*} non-NULL addr returned
*/
FIBER_API void *acl_channel_recvp(ACL_CHANNEL* c);
/**
* send the object's addr to specified channel in non-block mode
* Send the object's addr to specified channel in non-block mode
* @param c {ACL_CHANNEL*} created by acl_channel_create
* @param v {void*} the addr of the object to be transfered
* @return {int} value which is >= 0 returned
@ -86,14 +86,14 @@ FIBER_API void *acl_channel_recvp(ACL_CHANNEL* c);
FIBER_API int acl_channel_sendp_nb(ACL_CHANNEL* c, void* v);
/**
* get the object's addr form specified channel in non-block mode
* Get the object's addr form specified channel in non-block mode
* @param c {ACL_CHANNEL*} created by acl_channel_create
* @return {void*} * non-NULL returned when got one, or NULL returned
*/
FIBER_API void *acl_channel_recvp_nb(ACL_CHANNEL* c);
/**
* send unsigned integer to specified channel in block mode
* Send unsigned integer to specified channel in block mode
* @param c {ACL_CHANNEL*} created by acl_channel_create
* @param val {unsigned long} the integer to be sent
* @return {int} value (>= 0) returned
@ -101,14 +101,14 @@ FIBER_API void *acl_channel_recvp_nb(ACL_CHANNEL* c);
FIBER_API int acl_channel_sendul(ACL_CHANNEL* c, unsigned long val);
/**
* get unsigned integer from specified channel in block mode
* Get unsigned integer from specified channel in block mode
* @param c {ACL_CHANNEL*} created by acl_channel_create
* @return {unsigned long}
*/
FIBER_API unsigned long acl_channel_recvul(ACL_CHANNEL* c);
/**
* sent unsigned integer to specified channel in non-block mode
* Sent unsigned integer to specified channel in non-block mode
* @param c {ACL_CHANNEL*} created by acl_channel_create
* @param val {unsigned long} integer to be sent
* @return {int} value(>= 0) returned
@ -116,7 +116,7 @@ FIBER_API unsigned long acl_channel_recvul(ACL_CHANNEL* c);
FIBER_API int acl_channel_sendul_nb(ACL_CHANNEL* c, unsigned long val);
/**
* get one unsigned integer from specified channel in non-block mode
* Get one unsigned integer from specified channel in non-block mode
* @param c {ACL_CHANNEL*} created by acl_channel_create
* @return {unsigned long}
*/

View File

@ -11,26 +11,26 @@ extern "C" {
/* fiber_cond.h */
/**
* fiber_cond object look like pthread_cond_t which is used between threads
* Fiber_cond object look like pthread_cond_t which is used between threads
* and fibers
*/
typedef struct ACL_FIBER_COND ACL_FIBER_COND;
/**
* create fiber cond which can be used in fibers more or threads mode
* Create fiber cond which can be used in fibers more or threads mode
* @param flag {unsigned} current not used, just for the future extend
* @return {ACL_FIBER_COND *}
*/
FIBER_API ACL_FIBER_COND *acl_fiber_cond_create(unsigned flag);
/**
* free cond created by acl_fiber_cond_create
* Free cond created by acl_fiber_cond_create
* @param cond {ACL_FIBER_COND *}
*/
FIBER_API void acl_fiber_cond_free(ACL_FIBER_COND *cond);
/**
* wait for cond event to be signaled
* Wait for cond event to be signaled
* @param cond {ACL_FIBER_COND *}
* @param event {ACL_FIBER_EVENT *} must be owned by the current caller
* @return {int} return 0 if ok or return error value
@ -38,7 +38,7 @@ FIBER_API void acl_fiber_cond_free(ACL_FIBER_COND *cond);
FIBER_API int acl_fiber_cond_wait(ACL_FIBER_COND *cond, ACL_FIBER_EVENT *event);
/**
* wait for cond event to be signaled with the specified timeout
* Wait for cond event to be signaled with the specified timeout
* @param cond {ACL_FIBER_COND *}
* @return {int} return 0 if ok or return error value, when timedout ETIMEDOUT
* will be returned
@ -47,7 +47,7 @@ FIBER_API int acl_fiber_cond_timedwait(ACL_FIBER_COND *cond,
ACL_FIBER_EVENT *event, int delay_ms);
/**
* signle the cond which will wakeup one waiter for the cond to be signaled
* Signal the cond which will wakeup one waiter for the cond to be signaled
* @param cond {ACL_FIBER_COND *}
* @return {int} return 0 if ok or return error value
*/

View File

@ -95,7 +95,7 @@ typedef int socket_t;
#endif
/**
* the fiber struct type definition
* The fiber struct type definition
*/
typedef struct ACL_FIBER ACL_FIBER;

View File

@ -10,13 +10,13 @@ extern "C" {
/* fiber_event.c */
/**
* fiber event mutex object based on IO event, which is thread safety. That's
* Fiber event mutex object based on IO event, which is thread safety. That's
* to say one event object can used in different threads
*/
typedef struct ACL_FIBER_EVENT ACL_FIBER_EVENT;
/**
* when the fiber_event is used in multiple threads for sync, if there're
* When the fiber_event is used in multiple threads for sync, if there're
* many threads, the flag FIBER_FLAG_USE_MUTEX should be set to avoid internal
* thundering herd which maybe happen by using atomic; if the threads' number
* is less than one hundred, the flag FIBER_FLAG_USE_MUTEX needn't be set
@ -24,40 +24,40 @@ typedef struct ACL_FIBER_EVENT ACL_FIBER_EVENT;
#define FIBER_FLAG_USE_MUTEX (1 << 0)
/**
* if this flag is set, msg_fatal will be used other msg_error when error
* If this flag is set, msg_fatal will be used other msg_error when error
* happened, this flag is optional for users
*/
#define FIBER_FLAG_USE_FATAL (1 << 1)
/**
* create fiber event mutex which can be used in fibers mode or threads mode
* Create fiber event mutex which can be used in fibers mode or threads mode
* @param flag {unsigned} define as FIBER_FLAG_XXX above
* @return {ACL_FIBER_EVENT *}
*/
FIBER_API ACL_FIBER_EVENT *acl_fiber_event_create(unsigned flag);
/**
* free event mutex returned by acl_fiber_event_create
* Free event mutex returned by acl_fiber_event_create
* @param {ACL_FIBER_EVENT *}
*/
FIBER_API void acl_fiber_event_free(ACL_FIBER_EVENT *event);
/**
* wait for event can be available
* Wait for event can be available
* @param {ACL_FIBER_EVENT *}
* @return {int} 0 returned if successful, or -1 if error happened
*/
FIBER_API int acl_fiber_event_wait(ACL_FIBER_EVENT *event);
/**
* try to wait for event can be available
* Try to wait for event can be available
* @param {ACL_FIBER_EVENT *}
* @return {int} 0 returned if successful, or -1 if the event been locked
*/
FIBER_API int acl_fiber_event_trywait(ACL_FIBER_EVENT *event);
/**
* the event's owner notify the waiters that the event mutex can be available,
* The event's owner notify the waiters that the event mutex can be available,
* and the waiter will get the event mutex
* @param {ACL_FIBER_EVENT *}
* @return {int} 0 returned if successful, or -1 if error happened

View File

@ -7,40 +7,40 @@
extern "C" {
#endif
/* fiber locking */
/* Fiber locking */
/**
* fiber mutex, thread unsafety, one fiber mutex can only be used in the
* Fiber mutex, thread unsafety, one fiber mutex can only be used in the
* same thread, otherwise the result is unpredictable
*/
typedef struct ACL_FIBER_MUTEX ACL_FIBER_MUTEX;
/**
* fiber read/write mutex, thread unsafety, can only be used in the sampe thread
* Fiber read/write mutex, thread unsafety, can only be used in the sampe thread
*/
typedef struct ACL_FIBER_RWLOCK ACL_FIBER_RWLOCK;
/**
* create one fiber mutex, can only be used in the same thread
* Create one fiber mutex, can only be used in the same thread
* @return {ACL_FIBER_MUTEX*} fiber mutex returned
*/
FIBER_API ACL_FIBER_MUTEX* acl_fiber_mutex_create(void);
/**
* free fiber mutex created by acl_fiber_mutex_create
* Free fiber mutex created by acl_fiber_mutex_create
* @param l {ACL_FIBER_MUTEX*} created by acl_fiber_mutex_create
*/
FIBER_API void acl_fiber_mutex_free(ACL_FIBER_MUTEX* l);
/**
* lock the specified fiber mutex, return immediately when locked, or will
* Lock the specified fiber mutex, return immediately when locked, or will
* wait until the mutex can be used
* @param l {ACL_FIBER_MUTEX*} created by acl_fiber_mutex_create
*/
FIBER_API void acl_fiber_mutex_lock(ACL_FIBER_MUTEX* l);
/**
* try lock the specified fiber mutex, return immediately no matter the mutex
* Try lock the specified fiber mutex, return immediately no matter the mutex
* can be locked.
* @param l {ACL_FIBER_MUTEX*} created by acl_fiber_mutex_create
* @return {int} 0 returned when locking successfully, -1 when locking failed
@ -48,7 +48,7 @@ FIBER_API void acl_fiber_mutex_lock(ACL_FIBER_MUTEX* l);
FIBER_API int acl_fiber_mutex_trylock(ACL_FIBER_MUTEX* l);
/**
* the fiber mutex be unlock by its owner fiber, fatal will happen when others
* The fiber mutex be unlock by its owner fiber, fatal will happen when others
* release the fiber mutex
* @param l {ACL_FIBER_MUTEX*} created by acl_fiber_mutex_create
*/
@ -57,19 +57,19 @@ FIBER_API void acl_fiber_mutex_unlock(ACL_FIBER_MUTEX* l);
/****************************************************************************/
/**
* create one fiber rwlock, can only be operated in the sampe thread
* Create one fiber rwlock, can only be operated in the sampe thread
* @return {ACL_FIBER_RWLOCK*}
*/
FIBER_API ACL_FIBER_RWLOCK* acl_fiber_rwlock_create(void);
/**
* free rw mutex created by acl_fiber_rwlock_create
* Free rw mutex created by acl_fiber_rwlock_create
* @param l {ACL_FIBER_RWLOCK*} created by acl_fiber_rwlock_create
*/
FIBER_API void acl_fiber_rwlock_free(ACL_FIBER_RWLOCK* l);
/**
* lock the rwlock, if there is no any write locking on it, the
* Lock the rwlock, if there is no any write locking on it, the
* function will return immediately; otherwise, the caller will wait for all
* write locking be released. Read lock on it will successful when returning
* @param l {ACL_FIBER_RWLOCK*} created by acl_fiber_rwlock_create
@ -77,7 +77,7 @@ FIBER_API void acl_fiber_rwlock_free(ACL_FIBER_RWLOCK* l);
FIBER_API void acl_fiber_rwlock_rlock(ACL_FIBER_RWLOCK* l);
/**
* try to locking the Readonly lock, return immediately no matter locking
* Try to locking the Readonly lock, return immediately no matter locking
* is successful.
* @param l {ACL_FIBER_RWLOCK*} crated by acl_fiber_rwlock_create
* @retur {int} 1 returned when successfully locked, or 0 returned if locking
@ -86,13 +86,13 @@ FIBER_API void acl_fiber_rwlock_rlock(ACL_FIBER_RWLOCK* l);
FIBER_API int acl_fiber_rwlock_tryrlock(ACL_FIBER_RWLOCK* l);
/**
* lock the rwlock in Write Lock mode, return until no any one locking it
* Lock the rwlock in Write Lock mode, return until no any one locking it
* @param l {ACL_FIBER_RWLOCK*} created by acl_fiber_rwlock_create
*/
FIBER_API void acl_fiber_rwlock_wlock(ACL_FIBER_RWLOCK* l);
/**
* try to lock the rwlock in Write Lock mode. return immediately no matter
* Try to lock the rwlock in Write Lock mode. return immediately no matter
* locking is successful.
* @param l {ACL_FIBER_RWLOCK*} created by acl_fiber_rwlock_create
* @return {int} 1 returned when locking successfully, or 0 returned when
@ -101,13 +101,13 @@ FIBER_API void acl_fiber_rwlock_wlock(ACL_FIBER_RWLOCK* l);
FIBER_API int acl_fiber_rwlock_trywlock(ACL_FIBER_RWLOCK* l);
/**
* the rwlock's Read-Lock owner unlock the rwlock
* The rwlock's Read-Lock owner unlock the rwlock
* @param l {ACL_FIBER_RWLOCK*} crated by acl_fiber_rwlock_create
*/
FIBER_API void acl_fiber_rwlock_runlock(ACL_FIBER_RWLOCK* l);
/**
* the rwlock's Write-Lock owner unlock the rwlock
* The rwlock's Write-Lock owner unlock the rwlock
* @param l {ACL_FIBER_RWLOCK*} created by acl_fiber_rwlock_create
*/
FIBER_API void acl_fiber_rwlock_wunlock(ACL_FIBER_RWLOCK* l);

View File

@ -7,26 +7,26 @@
extern "C" {
#endif
/* fiber semaphore, thread unsafety, one semaphore can only be used in one
/* Fiber semaphore, thread unsafety, one semaphore can only be used in one
* thread, if used in different threads, result is unpredictable */
typedef struct ACL_FIBER_SEM ACL_FIBER_SEM;
/**
* create one fiber semaphore, and binding it with the current thread
* Create one fiber semaphore, and binding it with the current thread
* @param num {int} the initial value of the semaphore, must >= 0
* @return {ACL_FIBER_SEM *}
*/
FIBER_API ACL_FIBER_SEM* acl_fiber_sem_create(int num);
/**
* free fiber semaphore
* Free fiber semaphore
* @param {ACL_FIBER_SEM *}
*/
FIBER_API void acl_fiber_sem_free(ACL_FIBER_SEM* sem);
/**
* get the thread binding the specificed fiber sem
* Get the thread binding the specificed fiber sem
* @param sem {ACL_FIBER_SEM*} created by acl_fiber_sem_create
* @return {unsigned long} thread ID of the thread binding the semaphore
*/
@ -35,7 +35,7 @@ FIBER_API unsigned long acl_fiber_sem_get_tid(ACL_FIBER_SEM* sem);
#endif
/**
* set the thread ID the semaphore belongs to, changing the owner of the fiber
* Set the thread ID the semaphore belongs to, changing the owner of the fiber
* semaphore, when this function was called, the value of the semaphore must
* be zero, otherwise fatal will happen.
* @param sem {ACL_FIBER_SEM*} created by acl_fiber_sem_create
@ -44,7 +44,7 @@ FIBER_API unsigned long acl_fiber_sem_get_tid(ACL_FIBER_SEM* sem);
FIBER_API void acl_fiber_sem_set_tid(ACL_FIBER_SEM* sem, unsigned long tid);
/**
* wait for semaphore until > 0, semaphore will be -1 when returned
* Wait for semaphore until > 0, semaphore will be -1 when returned
* @param sem {ACL_FIBER_SEM *} created by acl_fiber_sem_create
* @return {int} the semaphore value returned, if the caller's thread isn't
* same as the semaphore owner's thread, -1 will be returned
@ -52,7 +52,7 @@ FIBER_API void acl_fiber_sem_set_tid(ACL_FIBER_SEM* sem, unsigned long tid);
FIBER_API int acl_fiber_sem_wait(ACL_FIBER_SEM* sem);
/**
* try to wait semaphore until > 0, if semaphore is 0, -1 returned immediately,
* Try to wait semaphore until > 0, if semaphore is 0, -1 returned immediately,
* otherwise semaphore will be decreased 1 and the semaphore's value is returned
* @param sem {ACL_FIBER_SEM *} created by acl_fiber_sem_create
* @return {int} value(>=0) returned when waiting ok, otherwise -1 will be
@ -62,7 +62,7 @@ FIBER_API int acl_fiber_sem_wait(ACL_FIBER_SEM* sem);
FIBER_API int acl_fiber_sem_trywait(ACL_FIBER_SEM* sem);
/**
* add 1 to the semaphore, if there are other fibers waiting for semaphore,
* Add 1 to the semaphore, if there are other fibers waiting for semaphore,
* one waiter will be wakeuped
* @param sem {ACL_FIBER_SEM *} created by acl_fiber_sem_create
* @return {int} the current semaphore value returned, -1 returned if the
@ -71,7 +71,7 @@ FIBER_API int acl_fiber_sem_trywait(ACL_FIBER_SEM* sem);
FIBER_API int acl_fiber_sem_post(ACL_FIBER_SEM* sem);
/**
* get the specificed semaphore's value
* Get the specificed semaphore's value
* @param sem {ACL_FIBER_SEM*} created by acl_fiber_sem_create
* @retur {int} current semaphore's value returned
*/

View File

@ -49,19 +49,23 @@ void msg_info(const char *fmt,...)
va_start (ap, fmt);
if (__pre_write_fn) {
__pre_write_fn(__pre_write_ctx, fmt, ap);
va_list ap_tmp;
va_copy(ap_tmp, ap);
__pre_write_fn(__pre_write_ctx, fmt, ap_tmp);
}
if (__stdout_enable) {
va_list ap_tmp;
va_copy(ap_tmp, ap);
printf("msg_info->pid(%d), ", GETPID());
vprintf(fmt, ap_tmp);
printf("\r\n");
}
if (__write_fn != NULL) {
__write_fn(__msg_ctx, fmt, ap);
}
if (__stdout_enable) {
printf("msg_info->pid(%d), ", GETPID());
vprintf(fmt, ap);
printf("\r\n");
}
va_end (ap);
}
@ -72,18 +76,22 @@ void msg_warn(const char *fmt,...)
va_start (ap, fmt);
if (__pre_write_fn) {
__pre_write_fn(__pre_write_ctx, fmt, ap);
va_list ap_tmp;
va_copy(ap_tmp, ap);
__pre_write_fn(__pre_write_ctx, fmt, ap_tmp);
}
if (__stdout_enable) {
va_list ap_tmp;
va_copy(ap_tmp, ap);
printf("msg_warn->pid(%d), ", GETPID());
vprintf(fmt, ap_tmp);
printf("\r\n");
}
if (__write_fn != NULL) {
__write_fn(__msg_ctx, fmt, ap);
}
if (__stdout_enable) {
printf("msg_warn->pid(%d), ", GETPID());
vprintf(fmt, ap);
printf("\r\n");
}
va_end (ap);
}
@ -95,18 +103,22 @@ void msg_error(const char *fmt,...)
va_start (ap, fmt);
if (__pre_write_fn) {
__pre_write_fn(__pre_write_ctx, fmt, ap);
va_list ap_tmp;
va_copy(ap_tmp, ap);
__pre_write_fn(__pre_write_ctx, fmt, ap_tmp);
}
if (__stdout_enable) {
va_list ap_tmp;
va_copy(ap_tmp, ap);
printf("msg_error->pid(%d), ", GETPID());
vprintf(fmt, ap_tmp);
printf("\r\n");
}
if (__write_fn != NULL) {
__write_fn(__msg_ctx, fmt, ap);
}
if (__stdout_enable) {
printf("msg_error->pid(%d), ", GETPID());
vprintf(fmt, ap);
printf("\r\n");
}
va_end (ap);
}
@ -118,19 +130,23 @@ void msg_fatal(const char *fmt,...)
va_start (ap, fmt);
if (__pre_write_fn) {
__pre_write_fn(__pre_write_ctx, fmt, ap);
va_list ap_tmp;
va_copy(ap_tmp, ap);
__pre_write_fn(__pre_write_ctx, fmt, ap_tmp);
}
if (__stdout_enable) {
va_list ap_tmp;
va_copy(ap_tmp, ap);
printf("msg_fatal->pid(%d), ", GETPID());
printf("fatal:");
vprintf(fmt, ap_tmp);
printf("\r\n");
}
if (__write_fn != NULL) {
__write_fn(__msg_ctx, fmt, ap);
}
if (__stdout_enable) {
printf("msg_fatal->pid(%d), ", GETPID());
printf("fatal:");
vprintf(fmt, ap);
printf("\r\n");
}
va_end (ap);
abort();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -74,7 +74,8 @@ EVENT *event_create(int size)
#endif
#ifdef HAS_EPOLL
ring_init(&ev->epoll_list);
ev->epoll_list = timer_cache_create();
ring_init(&ev->epoll_ready);
#endif
return ev;
}
@ -89,14 +90,13 @@ acl_handle_t event_handle(EVENT *ev)
return ev->handle(ev);
}
ssize_t event_size(EVENT *ev)
{
return ev->setsize;
}
void event_free(EVENT *ev)
{
timer_cache_free(ev->poll_list);
#ifdef HAS_EPOLL
timer_cache_free(ev->epoll_list);
#endif
ev->free(ev);
}
@ -253,7 +253,8 @@ int event_add_read(EVENT *ev, FILE_EVENT *fe, event_proc *proc)
}
if (fe->fd >= (socket_t) ev->setsize) {
msg_error("fd: %d >= setsize: %d", fe->fd, (int) ev->setsize);
msg_error("%s(%d): fd=%d >= setsize=%d", __FUNCTION__,
__LINE__, fe->fd, (int) ev->setsize);
acl_fiber_set_error(ERANGE);
return 0;
}
@ -296,7 +297,8 @@ int event_add_write(EVENT *ev, FILE_EVENT *fe, event_proc *proc)
}
if (fe->fd >= (socket_t) ev->setsize) {
msg_error("fd: %d >= setsize: %d", fe->fd, (int) ev->setsize);
msg_error("%s(%d): fd=%d >= setsize=%d", __FUNCTION__,
__LINE__, fe->fd, (int) ev->setsize);
acl_fiber_set_error(ERANGE);
return 0;
}
@ -410,7 +412,7 @@ static void event_process_poll(EVENT *ev)
RING_ITER iter;
RING *head;
POLL_EVENT *pe;
long long now = event_get_stamp(ev);
long long now = event_get_stamp(ev);
TIMER_CACHE_NODE *node = avl_first(&ev->poll_list->tree), *next;
/* Check and call all the pe's callback which was timeout except the
@ -442,35 +444,29 @@ static void event_process_poll(EVENT *ev)
#ifdef HAS_EPOLL
static void event_process_epoll(EVENT *ev)
{
#if 0
while (1) {
EPOLL_EVENT *ee;
RING *head = ring_pop_head(&ev->epoll_list);
if (head == NULL) {
break;
RING_ITER iter;
RING *head;
EPOLL_EVENT *ee;
long long now = event_get_stamp(ev);
TIMER_CACHE_NODE *node = avl_first(&ev->epoll_list->tree), *next;
while (node && node->expire >= 0 && node->expire <= now) {
next = AVL_NEXT(&ev->epoll_list->tree, node);
ring_foreach(iter, &node->ring) {
ee = TO_APPL(iter.ptr, EPOLL_EVENT, me);
ee->proc(ev, ee);
}
node = next;
}
while ((head = ring_pop_head(&ev->epoll_ready)) != NULL) {
ee = TO_APPL(head, EPOLL_EVENT, me);
ee->proc(ev, ee);
}
#else
EPOLL_EVENT *ee;
RING *next, *curr;
long long now;
now = event_get_stamp(ev);
for (next = ring_succ(&ev->epoll_list); next != &ev->epoll_list;) {
ee = ring_to_appl(next, EPOLL_EVENT, me);
if (ee->nready != 0 || (ee->expire >= 0 && now >= ee->expire)) {
curr = next;
next = ring_succ(next);
ring_detach(curr);
ee->proc(ev, ee);
} else {
next = ring_succ(next);
}
}
#endif
ring_init(&ev->epoll_ready);
}
#endif

View File

@ -150,12 +150,6 @@ struct FILE_EVENT {
};
#ifdef HAS_POLL
struct POLLFD {
FILE_EVENT *fe;
POLL_EVENT *pe;
struct pollfd *pfd;
};
struct POLL_EVENT {
RING me;
@ -169,24 +163,16 @@ struct POLL_EVENT {
#endif
#ifdef HAS_EPOLL
struct EPOLL_CTX {
int fd;
int op;
int mask;
int rmask;
FILE_EVENT *fe;
EPOLL_EVENT *ee;
epoll_data_t data;
};
typedef struct EPOLL EPOLL;
struct EPOLL_EVENT {
RING me;
ACL_FIBER *fiber;
EPOLL *epoll;
epoll_proc *proc;
size_t nfds;
long long expire;
EPOLL_CTX **fds;
int epfd;
struct epoll_event *events;
int maxevents;
@ -212,7 +198,8 @@ struct EVENT {
#endif
#ifdef HAS_EPOLL
RING epoll_list;
TIMER_CACHE *epoll_list;
RING epoll_ready;
#endif
unsigned waiter;
@ -242,7 +229,6 @@ void event_set(int event_mode);
EVENT *event_create(int size);
const char *event_name(EVENT *ev);
acl_handle_t event_handle(EVENT *ev);
ssize_t event_size(EVENT *ev);
void event_free(EVENT *ev);
void event_close(EVENT *ev, FILE_EVENT *fe);
long long event_set_stamp(EVENT *ev);

View File

@ -316,6 +316,14 @@ EVENT *event_epoll_create(int size)
hook_init();
}
// Limit the max events buff maybe a good idea to impromve performance
// for handling large fds. Because epoll uses robin round to handle
// all the ready fds, so we needn't worry about the starvation of the
// left ready fds.
if (size <= 0 || size > 100) {
size = 100;
}
ep->events = (struct epoll_event *)
mem_malloc(sizeof(struct epoll_event) * size);
ep->size = size;
@ -325,7 +333,7 @@ EVENT *event_epoll_create(int size)
ep->w_ready = array_create(100);
#endif
ep->epfd = __sys_epoll_create(1024);
ep->epfd = __sys_epoll_create(size);
assert(ep->epfd >= 0);
ep->event.name = epoll_name;

View File

@ -36,7 +36,14 @@ typedef struct THREAD {
unsigned idgen;
int count;
size_t switched;
size_t switched_old;
int nlocal;
#ifdef SHARE_STACK
char *stack_buff;
size_t stack_size;
size_t stack_dlen;
#endif
} THREAD;
static THREAD *__main_fiber = NULL;
@ -45,6 +52,10 @@ static __thread int __scheduled = 0;
static __thread int __schedule_auto = 0;
__thread int var_hook_sys_api = 0;
#ifdef SHARE_STACK
static size_t __shared_stack_size = 1024000;
#endif
#ifdef SYS_UNIX
static FIBER_ALLOC_FN __fiber_alloc_fn = fiber_unix_alloc;
static FIBER_ORIGIN_FN __fiber_origin_fn = fiber_unix_origin;
@ -52,8 +63,8 @@ static FIBER_ORIGIN_FN __fiber_origin_fn = fiber_unix_origin;
static FIBER_ALLOC_FN __fiber_alloc_fn = fiber_win_alloc;
static FIBER_ORIGIN_FN __fiber_origin_fn = fiber_win_origin;
#else
static ACL_FIBER *fiber_dummy_alloc(void(*start_fn)(ACL_FIBER*) fiber_unused,
size_t size fiber_unused)
static ACL_FIBER *fiber_dummy_alloc(ACL_FIBER_ATTR *attr fiber_unused,
void(*start_fn)(ACL_FIBER*) fiber_unused, size_t size fiber_unused)
{
msg_fatal("unknown OS");
return NULL;
@ -98,13 +109,13 @@ static void thread_free(void *ctx)
return;
}
/* free fiber object in the dead fibers link */
/* Free fiber object in the dead fibers link */
while ((head = ring_pop_head(&__thread_fiber->dead))) {
fiber = RING_TO_APPL(head, ACL_FIBER, me);
fiber_free(fiber);
}
/* free all possible aliving fiber object */
/* Free all possible aliving fiber object */
for (i = 0; i < __thread_fiber->slot; i++) {
fiber_free(__thread_fiber->fibers[i]);
}
@ -113,6 +124,10 @@ static void thread_free(void *ctx)
mem_free(tf->fibers);
}
#ifdef SHARE_STACK
mem_free(tf->stack_buff);
#endif
tf->original->free_fn(tf->original);
mem_free(tf);
@ -165,6 +180,12 @@ static void fiber_check(void)
__thread_fiber->count = 0;
__thread_fiber->nlocal = 0;
#ifdef SHARE_STACK
__thread_fiber->stack_size = __shared_stack_size;
__thread_fiber->stack_buff = mem_malloc(__thread_fiber->stack_size);
__thread_fiber->stack_dlen = 0;
#endif
ring_init(&__thread_fiber->ready);
ring_init(&__thread_fiber->dead);
@ -176,6 +197,40 @@ static void fiber_check(void)
}
}
ACL_FIBER *fiber_origin(void)
{
return __thread_fiber->original;
}
#ifdef SHARE_STACK
char *fiber_share_stack_addr(void)
{
return __thread_fiber->stack_buff;
}
char *fiber_share_stack_bottom(void)
{
return __thread_fiber->stack_buff + __thread_fiber->stack_size;
}
size_t fiber_share_stack_size(void)
{
return __thread_fiber->stack_size;
}
size_t fiber_share_stack_dlen(void)
{
return __thread_fiber->stack_dlen;
}
void fiber_share_stack_set_dlen(size_t dlen)
{
__thread_fiber->stack_dlen = dlen;
}
#endif
#ifdef HOOK_ERRNO
static void fiber_init(void)
@ -205,7 +260,7 @@ static void fiber_init(void)
#endif
}
/* see /usr/include/bits/errno.h for __errno_location */
/* See /usr/include/bits/errno.h for __errno_location */
#ifdef ANDROID
volatile int* __errno(void)
#else
@ -356,7 +411,7 @@ static void fiber_swap(ACL_FIBER *from, ACL_FIBER *to)
size_t slot = from->slot;
int n = ring_size(&__thread_fiber->dead);
/* if the cached dead fibers reached the limit,
/* If the cached dead fibers reached the limit,
* some will be freed
*/
if (n > MAX_CACHE) {
@ -474,14 +529,14 @@ void acl_fiber_signal(ACL_FIBER *fiber, int signum)
fiber->signum = signum;
if (fiber == curr) { // just return if kill myself
if (fiber == curr) { // Just return if kill myself
return;
}
ring_detach(&curr->me);
ring_detach(&fiber->me);
/* add the current fiber and signed fiber in the head of the ready */
/* Add the current fiber and signed fiber in the head of the ready */
#if 0
fiber_ready(fiber);
fiber_yield();
@ -537,25 +592,32 @@ void acl_fiber_ready(ACL_FIBER *fiber)
int acl_fiber_yield(void)
{
size_t n;
if (ring_size(&__thread_fiber->ready) == 0) {
return 0;
}
n = __thread_fiber->switched;
__thread_fiber->switched_old = __thread_fiber->switched;
__thread_fiber->running->status = FIBER_STATUS_NONE;
acl_fiber_ready(__thread_fiber->running);
acl_fiber_switch();
// when switched overflows, it will be set to 0, then n saved last
// When switched overflows, it will be set to 0, then n saved last
// switched's value will larger than switched, so we need to use
// abs function to avoiding this problem
if (__thread_fiber->switched == 0) {
return (int) (__thread_fiber->switched -
__thread_fiber->switched_old - 1);
} else {
return (int) (__thread_fiber->switched_old -
__thread_fiber->switched - 1);
}
/*
#if defined(__APPLE__) || defined(SYS_WIN) || defined(ANDROID)
return (int) (__thread_fiber->switched - n - 1);
return (int) (__thread_fiber->switched - __thread_fiber->switched_old - 1);
#else
return (int) abs(__thread_fiber->switched - n - 1);
return (int) abs(__thread_fiber->switched - __thread_fiber->switched_old - 1);
#endif
*/
}
unsigned acl_fiber_ndead(void)
@ -647,7 +709,7 @@ ACL_FIBER *acl_fiber_alloc(size_t size, void **pptr)
}
static ACL_FIBER *fiber_alloc(void (*fn)(ACL_FIBER *, void *),
void *arg, size_t size)
void *arg, const ACL_FIBER_ATTR *attr)
{
ACL_FIBER *fiber = NULL;
RING *head;
@ -656,17 +718,17 @@ static ACL_FIBER *fiber_alloc(void (*fn)(ACL_FIBER *, void *),
#define APPL RING_TO_APPL
/* try to reuse the fiber memory in dead queue */
/* Try to reuse the fiber memory in dead queue */
head = ring_pop_head(&__thread_fiber->dead);
if (head == NULL) {
fiber = __fiber_alloc_fn(fiber_start, size);
fiber = __fiber_alloc_fn(fiber_start, attr);
fbase_init(&fiber->base, FBASE_F_FIBER);
} else {
fiber = APPL(head, ACL_FIBER, me);
}
__thread_fiber->idgen++;
if (__thread_fiber->idgen == 0) { /* overflow ? */
if (__thread_fiber->idgen == 0) { /* Overflow ? */
__thread_fiber->idgen++;
}
@ -675,12 +737,13 @@ static ACL_FIBER *fiber_alloc(void (*fn)(ACL_FIBER *, void *),
fiber->signum = 0;
fiber->fn = fn;
fiber->arg = arg;
fiber->oflag = attr ? attr->oflag : 0;
fiber->flag = 0;
fiber->status = FIBER_STATUS_NONE;
fiber->waiting = NULL;
ring_init(&fiber->holding);
fiber->init_fn(fiber, size);
fiber->init_fn(fiber, attr ? attr->stack_size : 128000);
return fiber;
}
@ -690,10 +753,40 @@ void acl_fiber_schedule_init(int on)
__schedule_auto = on;
}
void acl_fiber_attr_init(ACL_FIBER_ATTR *attr)
{
attr->oflag = 0;
attr->stack_size = 128000;
}
void acl_fiber_attr_setstacksize(ACL_FIBER_ATTR *attr, size_t size)
{
attr->stack_size = size;
}
void acl_fiber_attr_setsharestack(ACL_FIBER_ATTR *attr, int on)
{
if (on) {
attr->oflag |= ACL_FIBER_ATTR_SHARE_STACK;
} else {
attr->oflag &= ~ACL_FIBER_ATTR_SHARE_STACK;
}
}
ACL_FIBER *acl_fiber_create(void (*fn)(ACL_FIBER *, void *),
void *arg, size_t size)
{
ACL_FIBER *fiber = fiber_alloc(fn, arg, size);
ACL_FIBER_ATTR attr;
acl_fiber_attr_init(&attr);
attr.stack_size = size;
return acl_fiber_create2(&attr, fn, arg);
}
ACL_FIBER *acl_fiber_create2(const ACL_FIBER_ATTR *attr,
void (*fn)(ACL_FIBER *, void *), void *arg)
{
ACL_FIBER *fiber = fiber_alloc(fn, arg, attr);
__thread_fiber->count++;
@ -714,6 +807,11 @@ ACL_FIBER *acl_fiber_create(void (*fn)(ACL_FIBER *, void *),
return fiber;
}
int acl_fiber_use_share_stack(const ACL_FIBER *fiber)
{
return fiber->oflag & ACL_FIBER_ATTR_SHARE_STACK ? 1 : 0;
}
unsigned int acl_fiber_id(const ACL_FIBER *fiber)
{
return fiber ? fiber->id : 0;
@ -733,6 +831,25 @@ int acl_fiber_status(const ACL_FIBER *fiber)
return fiber ? fiber->status : 0;
}
void acl_fiber_set_shared_stack_size(size_t size)
{
if (size >= 1024) {
#ifdef SHARE_STACK
__shared_stack_size = size;
#endif
}
}
size_t acl_fiber_get_shared_stack_size(void)
{
#if defined(SHARE_STACK)
return __shared_stack_size;
#else
return 0;
#endif
}
void acl_fiber_schedule_set_event(int event_mode)
{
event_set(event_mode);
@ -778,7 +895,7 @@ void acl_fiber_schedule(void)
__thread_fiber->running = NULL;
}
/* release dead fiber */
/* Release dead fiber */
while ((head = ring_pop_head(&__thread_fiber->dead)) != NULL) {
fiber = RING_TO_APPL(head, ACL_FIBER, me);
fiber_free(fiber);

View File

@ -50,17 +50,18 @@ struct ACL_FIBER {
int errnum;
int sys;
int signum;
unsigned int oflag;
unsigned int flag;
RING holding;
ACL_FIBER_MUTEX *waiting;
#define FIBER_F_SAVE_ERRNO (unsigned) 1 << 0
#define FIBER_F_KILLED (unsigned) 1 << 1
#define FIBER_F_CLOSED (unsigned) 1 << 2
#define FIBER_F_SIGNALED (unsigned) 1 << 3
#define FIBER_F_CANCELED (FIBER_F_KILLED | FIBER_F_CLOSED | FIBER_F_SIGNALED)
RING holding;
ACL_FIBER_MUTEX *waiting;
FIBER_LOCAL **locals;
int nlocal;
@ -76,9 +77,19 @@ struct ACL_FIBER {
/* in fiber.c */
extern __thread int var_hook_sys_api;
FIBER_BASE *fbase_alloc(void);
void fbase_free(FIBER_BASE *fbase);
void fiber_free(ACL_FIBER *fiber);
ACL_FIBER *fiber_origin(void);
#ifdef SHARE_STACK
char *fiber_share_stack_addr(void);
char *fiber_share_stack_bottom(void);
size_t fiber_share_stack_size(void);
size_t fiber_share_stack_dlen(void);
void fiber_share_stack_set_dlen(size_t dlen);
#endif
/* in fbase.c */
void fbase_event_open(FIBER_BASE *fbase);
@ -124,13 +135,15 @@ int epoll_event_close(int epfd);
/* in fiber/fiber_unix.c */
#ifdef SYS_UNIX
ACL_FIBER *fiber_unix_origin(void);
ACL_FIBER *fiber_unix_alloc(void (*start_fn)(ACL_FIBER *), size_t size);
ACL_FIBER *fiber_unix_alloc(void (*start_fn)(ACL_FIBER *),
const ACL_FIBER_ATTR *attr);
#endif
/* in fiber/fiber_win.c */
#ifdef SYS_WIN
ACL_FIBER *fiber_win_origin(void);
ACL_FIBER *fiber_win_alloc(void (*start_fn)(ACL_FIBER *), size_t size);
ACL_FIBER *fiber_win_alloc(void (*start_fn)(ACL_FIBER *),
const ACL_FIBER_ATTR *attr);
#endif
#endif

View File

@ -45,9 +45,14 @@ typedef struct FIBER_UNIX {
# endif
size_t size;
char *buff;
size_t dlen;
} FIBER_UNIX;
#if defined(USE_BOOST_JMP)
# if defined(SHARE_STACK)
# error "Not support shared stack when using boost jmp!"
# endif
typedef struct {
FIBER_UNIX *from;
FIBER_UNIX *to;
@ -64,18 +69,64 @@ static void swap_fcontext(FIBER_UNIX *from, FIBER_UNIX *to)
jmp = (s_jump_t*) trans.data;
jmp->from->fcontext = trans.fctx;
}
#endif
#if defined(SHARE_STACK)
static void fiber_stack_save(FIBER_UNIX *curr, const char *stack_top)
{
curr->dlen = fiber_share_stack_bottom() - stack_top;
if (curr->dlen > curr->size) {
stack_free(curr->buff);
curr->buff = (char *) stack_alloc(curr->dlen);
curr->size = curr->dlen;
}
memcpy(curr->buff, stack_top, curr->dlen);
}
static void fiber_stack_restore(FIBER_UNIX *curr)
{
// After coming back, the current fiber's stack should be
// restored and copied from its private memory to the shared
// stack running memory.
if (curr->dlen > 0) {
char *bottom = fiber_share_stack_bottom();
memcpy(bottom - curr->dlen, curr->buff, curr->dlen);
fiber_share_stack_set_dlen(curr->dlen);
}
// else if from->dlen == 0, the fiber must be the origin fiber
// that its fiber id should be 0.
}
#endif
static void fiber_unix_swap(FIBER_UNIX *from, FIBER_UNIX *to)
{
// The shared stack mode isn't supported in USE_BOOST_JMP current,
// which may be supported in future.
// If the fiber isn't in exiting status, and not the origin fiber,
// the fiber's running stack should be copied from the shared running
// stack to the fiber's private memory.
#if defined(SHARE_STACK)
if (from->fiber.oflag & ACL_FIBER_ATTR_SHARE_STACK
&& from->fiber.status != FIBER_STATUS_EXITING
&& from->fiber.id > 0) {
char stack_top = 0;
fiber_stack_save(from, &stack_top);
}
#endif
#if defined(USE_BOOST_JMP)
swap_fcontext(from, to);
#elif defined(USE_JMP)
/* use setcontext() for the initial jump, as it allows us to set up
/* Use setcontext() for the initial jump, as it allows us to set up
* a stack, but continue with longjmp() as it's much faster.
*/
if (SETJMP(&from->env) == 0) {
/* context just be used once for set up a stack, which will
/* Context just be used once for set up a stack, which will
* be freed in fiber_start. The context in __thread_fiber
* was set NULL.
*/
@ -85,12 +136,24 @@ static void fiber_unix_swap(FIBER_UNIX *from, FIBER_UNIX *to)
LONGJMP(&to->env);
}
}
#else
#else // Use the default context swap API
if (swapcontext(from->context, to->context) < 0) {
msg_fatal("%s(%d), %s: swapcontext error %s",
__FILE__, __LINE__, __FUNCTION__, last_serror());
}
#endif
#if defined(SHARE_STACK)
{
FIBER_UNIX *curr = (FIBER_UNIX *) acl_fiber_running();
if (curr->fiber.oflag & ACL_FIBER_ATTR_SHARE_STACK
&& curr->fiber.status != FIBER_STATUS_EXITING) {
fiber_stack_restore(curr);
}
}
#endif
}
static void fiber_unix_free(ACL_FIBER *fiber)
@ -111,13 +174,16 @@ static void fiber_unix_free(ACL_FIBER *fiber)
}
#if defined(USE_BOOST_JMP)
static void fiber_unix_start(transfer_t arg)
{
s_jump_t *jmp = (s_jump_t*) arg.data;
jmp->from->fcontext = arg.fctx;
jmp->to->fiber.start_fn(&jmp->to->fiber);
}
#else
union cc_arg
{
void *p;
@ -135,7 +201,7 @@ static void fiber_unix_start(unsigned int x, unsigned int y)
fb = (FIBER_UNIX *)arg.p;
#ifdef USE_JMP
/* when using setjmp/longjmp, the context just be used only once */
/* When using setjmp/longjmp, the context just be used only once */
if (fb->context != NULL) {
stack_free(fb->context);
fb->context = NULL;
@ -143,18 +209,20 @@ static void fiber_unix_start(unsigned int x, unsigned int y)
#endif
fb->fiber.start_fn(&fb->fiber);
}
#endif // USE_BOOST_JMP
#endif // !USE_BOOST_JMP
static void fiber_unix_init(ACL_FIBER *fiber, size_t size)
{
FIBER_UNIX *fb = (FIBER_UNIX *) fiber;
#if !defined(USE_BOOST_JMP)
FIBER_UNIX *origin;
union cc_arg carg;
sigset_t zero;
#endif
if (fb->size < size) {
/* if using realloc, real memory will be used, when we first
/* If using realloc, real memory will be used, when we first
* free and malloc again, then we'll just use virtual memory,
* because memcpy will be called in realloc.
*/
@ -164,9 +232,22 @@ static void fiber_unix_init(ACL_FIBER *fiber, size_t size)
}
#if defined(USE_BOOST_JMP)
# if defined(SHARE_STACK)
if (fb->fiber.oflag & ACL_FIBER_ATTR_SHARE_STACK) {
fb->stack = fiber_share_stack_bottom();
fb->fcontext = make_fcontext(fb->stack,
fiber_share_stack_size(),
(void(*)(transfer_t)) fiber_unix_start);
} else {
fb->stack = fb->buff + fb->size;
fb->fcontext = make_fcontext(fb->stack, fb->size,
(void(*)(transfer_t)) fiber_unix_start);
}
# else
fb->stack = fb->buff + fb->size;
fb->fcontext = make_fcontext(fb->stack, fb->size,
(void(*)(transfer_t)) fiber_unix_start);
# endif
#else
carg.p = fiber;
@ -189,15 +270,28 @@ static void fiber_unix_init(ACL_FIBER *fiber, size_t size)
__FILE__, __LINE__, __FUNCTION__, last_serror());
}
fb->context->uc_stack.ss_sp = fb->buff + 8;
fb->context->uc_stack.ss_size = fb->size - 64;
fb->context->uc_link = NULL;
#if defined(SHARE_STACK)
if (fb->fiber.oflag & ACL_FIBER_ATTR_SHARE_STACK) {
fb->context->uc_stack.ss_sp = fiber_share_stack_addr();
fb->context->uc_stack.ss_size = fiber_share_stack_size();
} else {
fb->context->uc_stack.ss_sp = fb->buff;
fb->context->uc_stack.ss_size = fb->size;
}
#else
fb->context->uc_stack.ss_sp = fb->buff;
fb->context->uc_stack.ss_size = fb->size;
#endif
origin = (FIBER_UNIX*) fiber_origin();
fb->context->uc_link = origin->context;
makecontext(fb->context, (void(*)(void)) fiber_unix_start,
2, carg.i[0], carg.i[1]);
#endif
#ifdef USE_VALGRIND
/* avoid the valgrind warning */
/* Avoid the valgrind warning */
# if defined(USE_BOOST_JMP)
fb->vid = VALGRIND_STACK_REGISTER(fb->buff, fb->stack);
# else
@ -208,13 +302,16 @@ static void fiber_unix_init(ACL_FIBER *fiber, size_t size)
#endif
}
ACL_FIBER *fiber_unix_alloc(void (*start_fn)(ACL_FIBER *), size_t size)
ACL_FIBER *fiber_unix_alloc(void (*start_fn)(ACL_FIBER *),
const ACL_FIBER_ATTR *attr)
{
FIBER_UNIX *fb = (FIBER_UNIX *) mem_calloc(1, sizeof(*fb));
size_t size = attr ? attr->stack_size : 128000;
/* no using calloc just avoiding using real memory */
/* No using calloc just avoiding using real memory */
fb->buff = (char *) stack_alloc(size);
fb->size = size;
fb->fiber.oflag = attr ? attr->oflag : 0;
fb->fiber.init_fn = fiber_unix_init;
fb->fiber.free_fn = fiber_unix_free;
fb->fiber.swap_fn = (void (*)(ACL_FIBER*, ACL_FIBER*))fiber_unix_swap;
@ -236,12 +333,12 @@ ACL_FIBER *fiber_unix_origin(void)
fb->fiber.start_fn = NULL;
#elif defined(USE_JMP)
/* set context NULL when using setjmp that setcontext will not be
/* Set context NULL when using setjmp that setcontext will not be
* called in fiber_swap.
*/
fb->context = NULL;
#else
fb->context = (ucontext_t *) stack_calloc(sizeof(ucontext_t));
fb->context = (ucontext_t *) stack_alloc(sizeof(ucontext_t));
#endif
fb->fiber.free_fn = fiber_unix_free;
fb->fiber.swap_fn = (void (*)(ACL_FIBER*, ACL_FIBER*)) fiber_unix_swap;

View File

@ -62,9 +62,11 @@ static void fiber_win_init(FIBER_WIN *fb, size_t size)
}
}
ACL_FIBER *fiber_win_alloc(void (*start_fn)(ACL_FIBER *), size_t size)
ACL_FIBER *fiber_win_alloc(void (*start_fn)(ACL_FIBER *),
const ACL_FIBER_ATTR *attr)
{
FIBER_WIN *fb = (FIBER_WIN *) mem_calloc(1, sizeof(*fb));
size_t size = attr ? attr->stack_size : 128000;
fb->fiber.init_fn = (void (*)(ACL_FIBER*, size_t)) fiber_win_init;
fb->fiber.free_fn = fiber_win_free;

View File

@ -94,6 +94,8 @@ static void thread_init(void)
static pthread_once_t __once_control = PTHREAD_ONCE_INIT;
// Notice: don't write log here to avoid recursive calling when user call
// acl_fiber_msg_register() to hook the log process.
void fiber_io_check(void)
{
if (__thread_fiber != NULL) {
@ -109,8 +111,9 @@ void fiber_io_check(void)
}
if (pthread_once(&__once_control, thread_init) != 0) {
msg_fatal("%s(%d), %s: pthread_once error %s",
printf("%s(%d), %s: pthread_once error %s\r\n",
__FILE__, __LINE__, __FUNCTION__, last_serror());
abort();
}
var_maxfd = open_limit(0);
@ -118,8 +121,6 @@ void fiber_io_check(void)
var_maxfd = MAXFD;
}
msg_info("%s(%d): maxfd=%d", __FUNCTION__, __LINE__, var_maxfd);
__thread_fiber = (FIBER_TLS *) mem_malloc(sizeof(FIBER_TLS));
__thread_fiber->event = event_create(var_maxfd);
__thread_fiber->ev_fiber = acl_fiber_create(fiber_io_loop,
@ -140,7 +141,8 @@ void fiber_io_check(void)
__main_fiber = __thread_fiber;
atexit(fiber_io_main_free);
} else if (pthread_setspecific(__fiber_key, __thread_fiber) != 0) {
msg_fatal("pthread_setspecific error!");
printf("pthread_setspecific error!\r\n");
abort();
}
}
@ -568,8 +570,12 @@ static int fiber_file_del(FILE_EVENT *fe)
void fiber_file_free(FILE_EVENT *fe)
{
fiber_file_del(fe);
file_event_free(fe);
if (fiber_file_del(fe) == 0) {
file_event_free(fe);
} else {
// xxx: What happened?
msg_error("Some error happened for fe=%p, fd=%d", fe, fe->fd);
}
}
void fiber_file_close(FILE_EVENT *fe)

View File

@ -1,70 +0,0 @@
#include "stdafx.h"
#include "dns/dns.h"
#include "common/pthread_patch.h"
#include "hook.h"
#ifdef SYS_UNIX
struct dns_resolv_conf *var_dns_conf = NULL;
struct dns_hosts *var_dns_hosts = NULL;
struct dns_hints *var_dns_hints = NULL;
void fiber_dns_set_read_wait(int timeout)
{
set_read_timeout(timeout);
}
static void dns_on_exit(void)
{
if (var_dns_conf) {
dns_resconf_close(var_dns_conf);
var_dns_conf = NULL;
}
if (var_dns_hosts) {
dns_hosts_close(var_dns_hosts);
var_dns_hosts = NULL;
}
if (var_dns_hints) {
dns_hints_close(var_dns_hints);
var_dns_hints = NULL;
}
}
void fiber_dns_init(void)
{
#ifdef SYS_WIN
static pthread_mutex_t __lock;
#elif defined(SYS_UNIX)
static pthread_mutex_t __lock = PTHREAD_MUTEX_INITIALIZER;
#endif
static int __called = 0;
int err;
(void) pthread_mutex_lock(&__lock);
if (__called) {
(void) pthread_mutex_unlock(&__lock);
return;
}
__called++;
err = 0;
var_dns_conf = dns_resconf_local(&err);
assert(var_dns_conf && err == 0);
var_dns_conf->options.timeout = 1000;
var_dns_hosts = dns_hosts_local(&err);
assert(var_dns_hosts && err == 0);
var_dns_hints = dns_hints_local(var_dns_conf, &err);
assert(var_dns_hints && err == 0);
atexit(dns_on_exit);
(void) pthread_mutex_unlock(&__lock);
}
#endif

View File

@ -10,32 +10,115 @@
/****************************************************************************/
static EPOLL_EVENT *epfd_alloc(void)
{
EPOLL_EVENT *ee = mem_calloc(1, sizeof(EPOLL_EVENT));
int maxfd = open_limit(0);
struct EPOLL_CTX {
int fd;
int op;
int mask;
int rmask;
FILE_EVENT *fe;
EPOLL_EVENT *ee;
epoll_data_t data;
};
if (maxfd <= 0) {
msg_fatal("%s(%d), %s: open_limit error %s",
__FILE__, __LINE__, __FUNCTION__, last_serror());
/**
* All EPOLL_EVENT owned by its fiber are assosiate with the same one epoll fd.
* one epoll fd -|- one EPOLL -|- fiber EPOLL_EVENT
* |- fiber EPOLL_EVENT
* |- ...
* |- fiber EPOLL_EVENT -|- socket EPOLL_CTX
* |- socket EPOLL_CTX
* |- socket EPOLL_CTX
* |- ...
*/
struct EPOLL {
int epfd;
EPOLL_CTX **fds;
size_t nfds;
// Store all EPOLL_EVENT, every fiber should use its own EPOLL_EVENT,
// Because in some case, one thread maybe have many fibers but it maybe
// use only one epoll fd to handle IO events, see acl_read_epoll_wait()
// in lib_acl/src/stdlib/iostuff/acl_read_wait.c.
HTABLE *ep_events;
};
/****************************************************************************/
#ifdef SYS_WIN
# define SNPRINTF _snprintf
#else
# define SNPRINTF snprintf
#endif
static void epoll_event_free(EPOLL_EVENT *ee)
{
mem_free(ee);
}
static void fiber_on_exit(void *ctx)
{
EPOLL_EVENT *ee = (EPOLL_EVENT*) ctx, *tmp;
ACL_FIBER *curr = acl_fiber_running();
char key[32];
assert(curr);
// If the epoll in ee has been set NULL in epoll_free(), the EPOLL
// must have been freed and the associated epoll fd must also have
// been closed, so we just only free the ee here.
if (ee->epoll == NULL) {
epoll_event_free(ee);
return;
}
++maxfd;
ee->fds = (EPOLL_CTX **) mem_malloc(maxfd * sizeof(EPOLL_CTX *));
ee->nfds = maxfd;
SNPRINTF(key, sizeof(key), "%u", curr->id);
tmp = (EPOLL_EVENT *) htable_find(ee->epoll->ep_events, key);
if (tmp == NULL) {
msg_fatal("%s(%d), %s: not found ee=%p, curr fiber=%d,"
" ee fiber=%d", __FILE__, __LINE__, __FUNCTION__,
ee, acl_fiber_id(curr), acl_fiber_id(ee->fiber));
}
assert(tmp == ee);
htable_delete(ee->epoll->ep_events, key, NULL);
epoll_event_free(ee);
}
static __thread int __local_key;
static EPOLL_EVENT *epoll_event_alloc(void)
{
// One EPOLL_EVENT can be owned by one fiber and be stored in the
// fiber's local store, so the EPOLL_EVENT can be used repeated by
// its owner fiber, and can be freed when the fiber is exiting.
EPOLL_EVENT *ee = (EPOLL_EVENT*) acl_fiber_get_specific(__local_key);
if (ee) {
return ee;
}
ee = mem_calloc(1, sizeof(EPOLL_EVENT));
acl_fiber_set_specific(&__local_key, ee, fiber_on_exit);
ring_init(&ee->me);
ee->fiber = acl_fiber_running();
return ee;
}
/****************************************************************************/
static ARRAY *__main_epfds = NULL;
static __thread ARRAY *__epfds = NULL;
static pthread_key_t __once_key;
static pthread_once_t __once_control = PTHREAD_ONCE_INIT;
static void epoll_free(EPOLL *ep);
static void thread_free(void *ctx fiber_unused)
{
size_t j;
ITER iter;
if (__epfds == NULL) {
@ -47,20 +130,13 @@ static void thread_free(void *ctx fiber_unused)
}
foreach(iter, __epfds) {
EPOLL_EVENT *ee = (EPOLL_EVENT *) iter.data;
EPOLL *ep = (EPOLL *) iter.data;
for (j = 0; j < ee->nfds; j++) {
if (ee->fds[j] != NULL) {
mem_free(ee->fds[j]);
}
}
if (ee->epfd >= 0 && (*sys_close)(ee->epfd) < 0) {
if (ep->epfd >= 0 && (*sys_close)(ep->epfd) < 0) {
fiber_save_errno(acl_fiber_last_error());
}
mem_free(ee->fds);
mem_free(ee);
epoll_free(ep);
}
array_free(__epfds, NULL);
@ -83,17 +159,21 @@ static void thread_init(void)
}
}
static EPOLL_EVENT *epoll_event_create(int epfd)
static EPOLL *epoll_alloc(int epfd)
{
EPOLL_EVENT *ee = NULL;
size_t i;
EPOLL *ep;
int maxfd = open_limit(0), i;
/* using thread specific to store the epoll handles for each thread*/
if (maxfd <= 0) {
msg_fatal("%s(%d), %s: open_limit error %s",
__FILE__, __LINE__, __FUNCTION__, last_serror());
}
/* Using thread local to store the epoll handles for each thread. */
if (__epfds == NULL) {
if (pthread_once(&__once_control, thread_init) != 0) {
msg_fatal("%s(%d), %s: pthread_once error %s",
__FILE__, __LINE__, __FUNCTION__,
last_serror());
__FILE__, __LINE__, __FUNCTION__, last_serror());
}
__epfds = array_create(5);
@ -105,25 +185,106 @@ static EPOLL_EVENT *epoll_event_create(int epfd)
}
}
ee = epfd_alloc();
array_append(__epfds, ee);
ep = mem_malloc(sizeof(EPOLL));
array_append(__epfds, ep);
/* duplicate the current thread's epoll fd, so we can assosiate the
/* Duplicate the current thread's epoll fd, so we can assosiate the
* connection handles with one epoll fd for the current thread, and
* use one epoll fd for each thread to handle all fds
* use one epoll fd for each thread to handle all fds.
*/
ee->epfd = dup(epfd);
ep->epfd = dup(epfd);
for (i = 0; i < ee->nfds; i++) {
ee->fds[i] = NULL;
ep->nfds = maxfd;
ep->fds = (EPOLL_CTX **) mem_malloc(maxfd * sizeof(EPOLL_CTX *));
for (i = 0; i < maxfd; i++) {
ep->fds[i] = NULL;
}
return ee;
ep->ep_events = htable_create(100);
return ep;
}
static EPOLL_EVENT *epoll_event_find(int epfd)
static void epoll_free(EPOLL *ep)
{
ITER iter;
size_t i;
// Walk through all EPOLL_EVENT stored in ep_events, and just set their
// epoll variable to NULL, because they will be freed in fiber_on_exit()
// when the fiber the EPOLL_EVENT belonging to is exiting.
foreach(iter, ep->ep_events) {
EPOLL_EVENT *ee = (EPOLL_EVENT *) iter.data;
ee->epoll = NULL;
}
htable_free(ep->ep_events, NULL);
for (i = 0; i < ep->nfds; i++) {
if (ep->fds[i] != NULL) {
mem_free(ep->fds[i]);
}
}
mem_free(ep->fds);
mem_free(ep);
}
int epoll_event_close(int epfd)
{
EVENT *ev;
int sys_epfd;
EPOLL *ep = NULL;
int pos = -1;
ITER iter;
if (__epfds == NULL || epfd < 0) {
return -1;
}
foreach(iter, __epfds) {
EPOLL *tmp = (EPOLL *) iter.data;
if (tmp->epfd == epfd) {
ep = tmp;
pos = iter.i;
break;
}
}
if (ep == NULL) {
return -1;
}
ev = fiber_io_event();
assert(ev);
sys_epfd = event_handle(ev);
assert(sys_epfd >= 0);
// We can't close the epfd same as the internal fiber event's fd.
// Because we've alloced a new fd as a duplication of internal epfd
// in epoll_alloc by calling sys API dup(), the epfd here shouldn't
// be same as the internal epfd.
if (epfd == sys_epfd) {
msg_error("%s(%d): can't close the event sys_epfd=%d",
__FUNCTION__, __LINE__, epfd);
return -1;
}
epoll_free(ep);
array_delete(__epfds, pos, NULL);
return (*sys_close)(epfd);
}
static EPOLL_EVENT *epoll_event_find(int epfd, int create)
{
ACL_FIBER *curr = acl_fiber_running();
EPOLL *ep = NULL;
EPOLL_EVENT *ee;
char key[32];
ITER iter;
if (__epfds == NULL) {
msg_error("%s(%d), %s: __epfds NULL",
@ -132,58 +293,43 @@ static EPOLL_EVENT *epoll_event_find(int epfd)
}
foreach(iter, __epfds) {
EPOLL_EVENT *ee = (EPOLL_EVENT *) iter.data;
if (ee->epfd == epfd) {
return ee;
}
}
return NULL;
}
int epoll_event_close(int epfd)
{
ITER iter;
EPOLL_EVENT *ee = NULL;
int pos = -1;
size_t i;
if (__epfds == NULL || epfd < 0) {
return -1;
}
foreach(iter, __epfds) {
EPOLL_EVENT *e = (EPOLL_EVENT *) iter.data;
if (e->epfd == epfd) {
ee = e;
pos = iter.i;
EPOLL *tmp = (EPOLL *) iter.data;
if (tmp->epfd == epfd) {
ep = tmp;
break;
}
}
if (ee == NULL) {
return -1;
if (ep == NULL) {
msg_error("%s(%d, %s: not found epfd=%d",
__FILE__, __LINE__, __FUNCTION__, epfd);
return NULL;
}
for (i = 0; i < ee->nfds; i++) {
if (ee->fds[i] != NULL) {
mem_free(ee->fds[i]);
}
SNPRINTF(key, sizeof(key), "%u", curr->id);
ee = (EPOLL_EVENT *) htable_find(ep->ep_events, key);
if (ee != NULL) {
ee->epoll = ep;
return ee;
}
mem_free(ee->fds);
mem_free(ee);
array_delete(__epfds, pos, NULL);
if (create) {
ee = epoll_event_alloc();
ee->epoll = ep;
htable_enter(ep->ep_events, key, ee);
return (*sys_close)(epfd);
return ee;
} else {
return NULL;
}
}
/****************************************************************************/
int epoll_create(int size fiber_unused)
{
EPOLL_EVENT *ee;
EVENT *ev;
EPOLL *ep;
int epfd;
if (sys_epoll_create == NULL) {
@ -195,9 +341,9 @@ int epoll_create(int size fiber_unused)
}
ev = fiber_io_event();
assert(ev);
/* get the current thread's epoll fd */
// Get the current thread's epoll fd.
epfd = event_handle(ev);
if (epfd < 0) {
msg_error("%s(%d), %s: invalid event_handle %d",
@ -205,8 +351,10 @@ int epoll_create(int size fiber_unused)
return epfd;
}
ee = epoll_event_create(epfd);
return ee->epfd;
// The epoll fd will be duplicated in the below function, and the new
// fd will be returned to the caller.
ep = epoll_alloc(epfd);
return ep->epfd;
}
#ifdef EPOLL_CLOEXEC
@ -224,104 +372,146 @@ int epoll_create1(int flags)
}
#endif
static void read_callback(EVENT *ev fiber_unused, FILE_EVENT *fe)
static void read_callback(EVENT *ev, FILE_EVENT *fe)
{
EPOLL_CTX *epx = fe->epx;
EPOLL_EVENT *ee = epx->ee;
EPOLL_CTX *epx = fe->epx;
EPOLL_EVENT *ee;
EPOLL *ep;
assert(ee);
assert(epx);
assert(epx->mask & EVENT_READ);
ee = epx->ee;
assert(ee);
ep = ee->epoll;
assert(ep);
// If the ready count exceeds the maxevents been set which limits the
// the buffer space to hold the the ready fds, we just return to let
// the left ready fds keeped in system buffer, and hope they'll be
// handled in the next epoll_wait().
if (ee->nready >= ee->maxevents) {
return;
}
ee->events[ee->nready].events |= EPOLLIN;
memcpy(&ee->events[ee->nready].data, &ee->fds[epx->fd]->data,
sizeof(ee->fds[epx->fd]->data));
memcpy(&ee->events[ee->nready].data, &ep->fds[epx->fd]->data,
sizeof(ep->fds[epx->fd]->data));
if (ee->nready == 0) {
timer_cache_remove(ev->epoll_list, ee->expire, &ee->me);
ring_prepend(&ev->epoll_ready, &ee->me);
}
if (!(ee->events[ee->nready].events & EPOLLOUT)) {
ee->nready++;
}
SET_READABLE(fe);
}
static void write_callback(EVENT *ev fiber_unused, FILE_EVENT *fe)
{
EPOLL_CTX *epx = fe->epx;
EPOLL_EVENT *ee = epx->ee;
EPOLL_CTX *epx = fe->epx;
EPOLL_EVENT *ee;
EPOLL *ep;
assert(ee);
assert(epx);
assert(epx->mask & EVENT_WRITE);
ee = epx->ee;
assert(ee);
ep = ee->epoll;
assert(ep);
if (ee->nready >= ee->maxevents) {
return;
}
ee->events[ee->nready].events |= EPOLLOUT;
memcpy(&ee->events[ee->nready].data, &ee->fds[epx->fd]->data,
sizeof(ee->fds[epx->fd]->data));
memcpy(&ee->events[ee->nready].data, &ep->fds[epx->fd]->data,
sizeof(ep->fds[epx->fd]->data));
if (ee->nready == 0) {
timer_cache_remove(ev->epoll_list, ee->expire, &ee->me);
ring_prepend(&ev->epoll_ready, &ee->me);
}
if (!(ee->events[ee->nready].events & EPOLLIN)) {
ee->nready++;
}
SET_WRITABLE(fe);
}
static void epoll_ctl_add(EVENT *ev, EPOLL_EVENT *ee,
struct epoll_event *event, int fd, int op)
{
if (ee->fds[fd] == NULL) {
ee->fds[fd] = (EPOLL_CTX *) mem_malloc(sizeof(EPOLL_CTX));
EPOLL *ep = ee->epoll;
if (ep->fds[fd] == NULL) {
ep->fds[fd] = (EPOLL_CTX *) mem_malloc(sizeof(EPOLL_CTX));
}
ee->fds[fd]->fd = fd;
ee->fds[fd]->op = op;
ee->fds[fd]->mask = EVENT_NONE;
ee->fds[fd]->rmask = EVENT_NONE;
ee->fds[fd]->ee = ee;
ee->fds[fd]->fe->epx = ee->fds[fd];
ep->fds[fd]->fd = fd;
ep->fds[fd]->op = op;
ep->fds[fd]->mask = EVENT_NONE;
ep->fds[fd]->rmask = EVENT_NONE;
ep->fds[fd]->ee = ee;
memcpy(&ee->fds[fd]->data, &event->data, sizeof(event->data));
memcpy(&ep->fds[fd]->data, &event->data, sizeof(event->data));
if (event->events & EPOLLIN) {
ee->fds[fd]->mask |= EVENT_READ;
ee->fds[fd]->fe = fiber_file_open_read(fd);
event_add_read(ev, ee->fds[fd]->fe, read_callback);
SET_READWAIT(ee->fds[fd]->fe);
ep->fds[fd]->mask |= EVENT_READ;
ep->fds[fd]->fe = fiber_file_open_read(fd);
ep->fds[fd]->fe->epx = ep->fds[fd];
event_add_read(ev, ep->fds[fd]->fe, read_callback);
SET_READWAIT(ep->fds[fd]->fe);
}
if (event->events & EPOLLOUT) {
ee->fds[fd]->mask |= EVENT_WRITE;
ee->fds[fd]->fe = fiber_file_open_write(fd);
event_add_write(ev, ee->fds[fd]->fe, write_callback);
SET_WRITEWAIT(ee->fds[fd]->fe);
ep->fds[fd]->mask |= EVENT_WRITE;
ep->fds[fd]->fe = fiber_file_open_write(fd);
ep->fds[fd]->fe->epx = ep->fds[fd];
event_add_write(ev, ep->fds[fd]->fe, write_callback);
SET_WRITEWAIT(ep->fds[fd]->fe);
}
}
static void epoll_ctl_del(EVENT *ev, EPOLL_EVENT *ee, int fd)
{
if (ee->fds[fd]->mask & EVENT_READ) {
event_del_read(ev, ee->fds[fd]->fe);
CLR_READWAIT(ee->fds[fd]->fe);
}
if (ee->fds[fd]->mask & EVENT_WRITE) {
event_del_write(ev, ee->fds[fd]->fe);
CLR_WRITEWAIT(ee->fds[fd]->fe);
EPOLL *ep = ee->epoll;
if (ep->fds[fd]->mask & EVENT_READ) {
event_del_read(ev, ep->fds[fd]->fe);
CLR_READWAIT(ep->fds[fd]->fe);
}
ee->fds[fd]->fd = -1;
ee->fds[fd]->op = 0;
ee->fds[fd]->mask = EVENT_NONE;
ee->fds[fd]->rmask = EVENT_NONE;
ee->fds[fd]->fe->epx = NULL;
ee->fds[fd]->fe = NULL;
memset(&ee->fds[fd]->data, 0, sizeof(ee->fds[fd]->data));
if (ep->fds[fd]->mask & EVENT_WRITE) {
event_del_write(ev, ep->fds[fd]->fe);
CLR_WRITEWAIT(ep->fds[fd]->fe);
}
mem_free(ee->fds[fd]);
ee->fds[fd] = NULL;
ep->fds[fd]->fd = -1;
ep->fds[fd]->op = 0;
ep->fds[fd]->mask = EVENT_NONE;
ep->fds[fd]->rmask = EVENT_NONE;
ep->fds[fd]->fe->epx = NULL;
ep->fds[fd]->fe = NULL;
memset(&ep->fds[fd]->data, 0, sizeof(ep->fds[fd]->data));
mem_free(ep->fds[fd]);
ep->fds[fd] = NULL;
}
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
{
EPOLL_EVENT *ee;
EVENT *ev;
EPOLL_EVENT *ee;
if (sys_epoll_ctl == NULL) {
hook_once();
@ -331,13 +521,15 @@ int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
return sys_epoll_ctl ? (*sys_epoll_ctl)(epfd, op, fd, event) : -1;
}
ee = epoll_event_find(epfd);
ee = epoll_event_find(epfd, 1);
if (ee == NULL) {
msg_error("%s(%d), %s: not exist epfd=%d",
__FILE__, __LINE__, __FUNCTION__, epfd);
return -1;
}
assert(ee->epoll);
ev = fiber_io_event();
if (op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD) {
@ -346,10 +538,8 @@ int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
msg_error("%s(%d), %s: invalid op %d, fd %d",
__FILE__, __LINE__, __FUNCTION__, op, fd);
return -1;
} else if (ee->fds[fd] != NULL) {
} else if (ee->epoll->fds[fd] != NULL) {
epoll_ctl_del(ev, ee, fd);
CLR_READWAIT(ee->fds[fd]->fe);
CLR_WRITEWAIT(ee->fds[fd]->fe);
} else {
msg_error("%s(%d), %s: invalid fd=%d",
__FILE__, __LINE__, __FUNCTION__, fd);
@ -398,7 +588,8 @@ int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
}
if (!var_hook_sys_api) {
return sys_epoll_wait ? (*sys_epoll_wait)(epfd, events, maxevents, timeout) : -1;
return sys_epoll_wait ? (*sys_epoll_wait)
(epfd, events, maxevents, timeout) : -1;
}
ev = fiber_io_event();
@ -408,7 +599,7 @@ int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
return -1;
}
ee = epoll_event_find(epfd);
ee = epoll_event_find(epfd, 0);
if (ee == NULL) {
msg_error("%s(%d), %s: not exist epfd %d",
__FILE__, __LINE__, __FUNCTION__, epfd);
@ -417,37 +608,51 @@ int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
ee->events = events;
ee->maxevents = maxevents;
ee->nready = 0;
ee->fiber = acl_fiber_running();
ee->proc = epoll_callback;
ee->nready = 0;
old_timeout = ev->timeout;
event_epoll_set(ev, ee, timeout);
ev->waiter++;
while (1) {
ring_prepend(&ev->epoll_list, &ee->me);
timer_cache_add(ev->epoll_list, ee->expire, &ee->me);
fiber_io_inc();
ee->fiber->status = FIBER_STATUS_EPOLL_WAIT;
acl_fiber_switch();
if (ee->nready == 0) {
timer_cache_remove(ev->epoll_list, ee->expire, &ee->me);
}
ev->timeout = old_timeout;
ev->timeout = -1;
if (acl_fiber_killed(ee->fiber)) {
ring_detach(&ee->me);
acl_fiber_set_error(ee->fiber->errnum);
if (ee->nready == 0) {
ee->nready = -1;
}
msg_info("%s(%d), %s: fiber-%u was killed",
__FILE__, __LINE__, __FUNCTION__,
acl_fiber_id(ee->fiber));
break;
}
if (timer_cache_size(ev->epoll_list) == 0) {
ev->timeout = -1;
}
if (ee->nready != 0 || timeout == 0) {
break;
}
now = event_get_stamp(ev);
if (ee->expire > 0 && now >= ee->expire) {
acl_fiber_set_error(FIBER_ETIMEDOUT);
break;
}
}

View File

@ -7,6 +7,12 @@
#ifdef HAS_POLL
struct POLLFD {
FILE_EVENT *fe;
POLL_EVENT *pe;
struct pollfd *pfd;
};
/****************************************************************************/
#define TO_APPL ring_to_appl
@ -49,8 +55,6 @@ static void read_callback(EVENT *ev, FILE_EVENT *fe)
pfd->fe = NULL;
}
assert(timer_cache_size(ev->poll_list) > 0);
/*
* If any fe has been ready, the pe holding fe should be removed from
* ev->poll_list to avoid to be called in timeout process.
@ -63,6 +67,7 @@ static void read_callback(EVENT *ev, FILE_EVENT *fe)
timer_cache_remove(ev->poll_list, pfd->pe->expire, &pfd->pe->me);
ring_prepend(&ev->poll_ready, &pfd->pe->me);
}
pfd->pe->nready++;
SET_READABLE(fe);
}
@ -99,12 +104,11 @@ static void write_callback(EVENT *ev, FILE_EVENT *fe)
pfd->fe = NULL;
}
assert(timer_cache_size(ev->poll_list) > 0);
if (pfd->pe->nready == 0) {
timer_cache_remove(ev->poll_list, pfd->pe->expire, &pfd->pe->me);
ring_prepend(&ev->poll_ready, &pfd->pe->me);
}
pfd->pe->nready++;
SET_WRITABLE(fe);
}
@ -201,6 +205,7 @@ static POLLFD *pollfd_alloc(POLL_EVENT *pe, struct pollfd *fds, nfds_t nfds)
#endif
pfds[i].pe = pe;
pfds[i].pfd = &fds[i];
pfds[i].pfd->revents = 0;
SET_POLLING(pfds[i].fe);
}
@ -212,14 +217,74 @@ static void pollfd_free(POLLFD *pfds)
mem_free(pfds);
}
#ifdef SHARE_STACK
typedef struct pollfds {
struct pollfd *fds;
nfds_t nfds;
size_t size;
} pollfds;
static void fiber_on_exit(void *ctx)
{
pollfds *pfds = (pollfds *) ctx;
mem_free(pfds->fds);
mem_free(pfds);
}
static __thread int __local_key;
static pollfds *pollfds_save(const struct pollfd *fds, nfds_t nfds)
{
pollfds *pfds = (pollfds *) acl_fiber_get_specific(__local_key);
if (pfds == NULL) {
pfds = (pollfds *) mem_malloc(sizeof(pollfds));
pfds->size = nfds + 1;
pfds->fds = mem_malloc(sizeof(struct pollfds) * pfds->size);
acl_fiber_set_specific(&__local_key, pfds, fiber_on_exit);
} else if (pfds->size < (size_t) nfds) {
mem_free(pfds->fds);
pfds->size = nfds + 1;
pfds->fds = mem_malloc(sizeof(struct pollfd) * pfds->size);
} else {
pfds->nfds = nfds;
}
pfds->nfds = nfds;
memcpy(pfds->fds, fds, sizeof(struct pollfd) * nfds);
return pfds;
}
static void pollfds_copy(const pollfds *pfds, struct pollfd *fds)
{
memcpy(fds, pfds->fds, sizeof(struct pollfd) * pfds->nfds);
}
#endif // SHARE_STACK
#define MAX_TIMEOUT 200000000
int WINAPI acl_fiber_poll(struct pollfd *fds, nfds_t nfds, int timeout)
{
long long now;
POLL_EVENT pe;
EVENT *ev;
int old_timeout;
int old_timeout, nready;
ACL_FIBER *curr;
#ifdef SHARE_STACK
// In shared stack mode, we should use heap memory for pe to hold
// all the fds, because the pe will be operated by the event fiber,
// but the shared stack can be used by only one fiber, the stack
// memory of the current fiber will be occupied by the other fiber
// after switching the other fiber. So, we use heap memory to hold
// pe to avoid stack memory collision.
pollfds *pfds;
POLL_EVENT pevent, *pe;
#else
POLL_EVENT pevent, *pe;
#endif
if (sys_poll == NULL) {
hook_once();
@ -229,65 +294,93 @@ int WINAPI acl_fiber_poll(struct pollfd *fds, nfds_t nfds, int timeout)
return sys_poll ? (*sys_poll)(fds, nfds, timeout) : -1;
}
curr = acl_fiber_running();
if (timeout < 0) {
timeout = MAX_TIMEOUT;
}
ev = fiber_io_event();
pe.fds = pollfd_alloc(&pe, fds, nfds);
pe.nfds = nfds;
pe.fiber = acl_fiber_running();
pe.proc = poll_callback;
pe.nready = 0;
ev = fiber_io_event();
old_timeout = ev->timeout;
poll_event_set(ev, &pe, timeout);
#ifdef SHARE_STACK
if (curr->oflag & ACL_FIBER_ATTR_SHARE_STACK) {
pfds = pollfds_save(fds, nfds);
pe = (POLL_EVENT *) mem_malloc(sizeof(POLL_EVENT));
pe->fds = pollfd_alloc(pe, pfds->fds, nfds);
} else {
pfds = NULL;
pe = &pevent;
pe->fds = pollfd_alloc(pe, fds, nfds);
}
#else
pe = &pevent;
pe->fds = pollfd_alloc(pe, fds, nfds);
#endif
pe->nfds = nfds;
pe->fiber = curr;
pe->proc = poll_callback;
poll_event_set(ev, pe, timeout);
ev->waiter++;
while (1) {
timer_cache_add(ev->poll_list, pe.expire, &pe.me);
pe.nready = 0;
timer_cache_add(ev->poll_list, pe->expire, &pe->me);
pe->nready = 0;
fiber_io_inc();
pe.fiber->status = FIBER_STATUS_POLL_WAIT;
pe->fiber->status = FIBER_STATUS_POLL_WAIT;
acl_fiber_switch();
if (pe.nready == 0) {
timer_cache_remove(ev->poll_list, pe.expire, &pe.me);
if (pe->nready == 0) {
timer_cache_remove(ev->poll_list, pe->expire, &pe->me);
}
ev->timeout = old_timeout;
if (acl_fiber_killed(pe.fiber)) {
acl_fiber_set_error(pe.fiber->errnum);
pe.nready = -1;
if (acl_fiber_killed(pe->fiber)) {
acl_fiber_set_error(pe->fiber->errnum);
if (pe->nready == 0) {
pe->nready = -1;
}
msg_info("%s(%d), %s: fiber-%u was killed, %s, timeout=%d",
__FILE__, __LINE__, __FUNCTION__,
acl_fiber_id(pe.fiber), last_serror(), timeout);
acl_fiber_id(pe->fiber), last_serror(), timeout);
break;
}
if (timer_cache_size(ev->poll_list) == 0) {
ev->timeout = -1;
}
if (pe.nready != 0 || timeout == 0) {
if (pe->nready != 0 || timeout == 0) {
break;
}
now = event_get_stamp(ev);
if (pe.expire > 0 && now >= pe.expire) {
if (pe->expire > 0 && now >= pe->expire) {
acl_fiber_set_error(FIBER_ETIMEDOUT);
break;
}
}
poll_event_clean(ev, &pe);
pollfd_free(pe.fds);
poll_event_clean(ev, pe);
pollfd_free(pe->fds);
ev->waiter--;
return pe.nready;
nready = pe->nready;
#ifdef SHARE_STACK
if (curr->oflag & ACL_FIBER_ATTR_SHARE_STACK) {
mem_free(pe);
pollfds_copy(pfds, fds);
}
#endif
return nready;
}
#ifdef SYS_UNIX

View File

@ -35,8 +35,10 @@ public:
* run running true
* start
* @param stack_size {size_t}
* @param ( libfiber.a
* SHARE_STACK )
*/
void start(size_t stack_size = 320000);
void start(size_t stack_size = 320000, bool share_stack = false);
/**
* 退
@ -194,6 +196,18 @@ public:
*/
static void set_non_blocking(bool yes);
/**
* , 1024000
* @param size {size_t}
*/
static void set_shared_stack_size(size_t size);
/**
*
* @return {size_t} 0
*/
static size_t get_shared_stack_size(void);
/**
* 使 acl IO UNIX
* HOOK IO API
@ -238,6 +252,7 @@ public:
*/
static void fiber_create(void (*fn)(ACL_FIBER*, void*),
void* ctx, size_t size);
protected:
/**
* start

View File

@ -102,6 +102,16 @@ void fiber::set_non_blocking(bool yes)
acl_fiber_set_non_blocking(yes ? 1 : 0);
}
void fiber::set_shared_stack_size(size_t size)
{
acl_fiber_set_shared_stack_size(size);
}
size_t fiber::get_shared_stack_size(void)
{
return acl_fiber_get_shared_stack_size();
}
ACL_FIBER *fiber::get_fiber(void) const
{
return f_;
@ -150,13 +160,18 @@ void fiber::run(void)
__FILE__, __LINE__, __FUNCTION__);
}
void fiber::start(size_t stack_size /* = 64000 */)
void fiber::start(size_t stack_size /* 64000 */, bool share_stack /* false */)
{
if (f_ != NULL) {
acl_msg_fatal("%s(%d), %s: fiber-%u, already running!",
__FILE__, __LINE__, __FUNCTION__, self());
}
acl_fiber_create(fiber_callback, this, stack_size);
ACL_FIBER_ATTR attr;
acl_fiber_attr_init(&attr);
acl_fiber_attr_setstacksize(&attr, stack_size);
acl_fiber_attr_setsharestack(&attr, share_stack ? 1 : 0);
acl_fiber_create2(&attr, fiber_callback, this);
}
void fiber::fiber_callback(ACL_FIBER *f, void *ctx)

View File

@ -67,8 +67,10 @@ static ACL_CONFIG_STR_TABLE __conf_str_tab[] = {
};
static int acl_var_fiber_quick_abort;
static int acl_var_fiber_share_stack;
static ACL_CONFIG_BOOL_TABLE __conf_bool_tab[] = {
{ "fiber_quick_abort", 1, &acl_var_fiber_quick_abort },
{ "fiber_share_stack", 0, &acl_var_fiber_share_stack },
{ 0, 0, 0 },
};
@ -141,6 +143,11 @@ static void thread_fiber_accept(ACL_FIBER *fiber, void *ctx)
static socket_t __max_fd = 0, __last_fd = 0;
ACL_VSTREAM *sstream = (ACL_VSTREAM *) ctx, *cstream;
char ip[64];
ACL_FIBER_ATTR attr;
acl_fiber_attr_init(&attr);
acl_fiber_attr_setstacksize(&attr, acl_var_fiber_stack_size);
acl_fiber_attr_setsharestack(&attr, acl_var_fiber_share_stack ? 1 : 0);
while (1) {
cstream = acl_vstream_accept(sstream, ip, sizeof(ip));
@ -150,8 +157,7 @@ static void thread_fiber_accept(ACL_FIBER *fiber, void *ctx)
__max_fd = __last_fd;
}
acl_fiber_create(fiber_client, cstream,
acl_var_fiber_stack_size);
acl_fiber_create2(&attr, fiber_client, cstream);
continue;
}
@ -401,6 +407,11 @@ static int main_dispatch_receive(int dispatch_fd)
char buf[256], remote[256], local[256];
int fd = -1, ret;
ACL_VSTREAM *cstream;
ACL_FIBER_ATTR attr;
acl_fiber_attr_init(&attr);
acl_fiber_attr_setstacksize(&attr, acl_var_fiber_stack_size);
acl_fiber_attr_setsharestack(&attr, acl_var_fiber_share_stack ? 1 : 0);
ret = acl_read_fd(dispatch_fd, buf, sizeof(buf) - 1, &fd);
if (ret < 0 || fd < 0) {
@ -422,7 +433,7 @@ static int main_dispatch_receive(int dispatch_fd)
acl_vstream_set_peer(cstream, remote);
}
acl_fiber_create(fiber_client, cstream, acl_var_fiber_stack_size);
acl_fiber_create2(&attr, fiber_client, cstream);
return 0;
}

View File

@ -108,14 +108,16 @@ void master_fiber::service_on_accept(void* ctx, ACL_VSTREAM *client)
master_fiber* mf = (master_fiber *) ctx;
acl_assert(mf != NULL);
socket_stream stream;
if (!stream.open(client)) {
socket_stream* stream = new socket_stream;
if (!stream->open(client)) {
logger_error("open stream error(%s)", acl_last_serror());
delete stream;
return;
}
mf->on_accept(stream);
stream.unbind();
mf->on_accept(*stream);
stream->unbind();
delete stream;
}
void master_fiber::thread_init(void* ctx)

View File

@ -100,6 +100,7 @@ static void usage(const char* procname)
int main(int argc, char *argv[])
{
int ch, n = 10;
size_t shared_size;
acl::acl_cpp_init();
acl::log::stdout_open(true);
@ -118,8 +119,14 @@ int main(int argc, char *argv[])
}
go fiber1;
go fiber_wait4thread;
go fiber_wait4fiber;
shared_size = acl::fiber::get_shared_stack_size();
if (shared_size == 0) {
// These two fibers can't running in shared stack mode.
go fiber_wait4thread;
go fiber_wait4fiber;
}
go[=] {
fiber2(n, "hello world");

View File

@ -0,0 +1,4 @@
#!/bin/sh
#valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes --max-stackframe=3426305034400000 -v ./fiber -n 10 -m 20
valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes -v ./fiber

View File

@ -0,0 +1,3 @@
include ../Makefile_cpp.in
CFLAGS += -std=c++11
PROG = fiber_tbox

View File

@ -0,0 +1,249 @@
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <thread>
#include "../stamp.h"
static void box_wakeup(acl::fiber_tbox<bool>& box)
{
box.push(NULL);
}
static void box_wait(acl::fiber_tbox<bool>& box)
{
box.pop();
}
static void test_in_shared_stack(size_t cocurrent, size_t n, size_t& count,
bool interactive)
{
go[&] {
size_t total = cocurrent * n;
acl::fiber_tbox<bool>* box = new acl::fiber_tbox<bool>;
acl::fiber_tbox<bool>* box1;
if (interactive) {
box1 = new acl::fiber_tbox<bool>;
} else {
box1 = NULL;
}
for (size_t j = 0; j < cocurrent; j++) {
go[=] {
for (size_t i = 0; i < n; i++) {
if (box1) {
box_wait(*box1);
}
box_wakeup(*box);
}
};
}
for (size_t i = 0; i < total; i++) {
if (box1) {
box_wakeup(*box1);
}
box_wait(*box);
count++;
}
delete box;
delete box1;
printf(">>> wait over, count=%zd\r\n", count);
};
}
static void test_in_shared_stack_thread(size_t cocurrent, size_t n,
size_t& count, bool interactive)
{
go[&] {
size_t total = cocurrent * n;
acl::fiber_tbox<bool>* box = new acl::fiber_tbox<bool>;
acl::fiber_tbox<bool>* box1;
if (interactive) {
box1 = new acl::fiber_tbox<bool>;
} else {
box1 = NULL;
}
for (size_t j = 0; j < cocurrent; j++) {
std::thread thread([=] {
for (size_t i = 0; i < n; i++) {
if (box1) {
box_wait(*box1);
}
box_wakeup(*box);
}
});
thread.detach();
}
for (size_t i = 0; i < total; i++) {
if (box1) {
box_wakeup(*box1);
}
box_wait(*box);
count++;
}
delete box;
delete box1;
printf(">>> wait over, count=%zd\r\n", count);
};
}
static void test_in_private_stack(size_t cocurrent, size_t n, size_t& count,
bool interactive)
{
size_t total = cocurrent * n;
go[&] {
acl::fiber_tbox<bool> box;
acl::fiber_tbox<bool> box1;
for (size_t j = 0; j < cocurrent; j++) {
go[&] {
for (size_t i = 0; i < n; i++) {
if (interactive) {
box_wait(box1);
}
box_wakeup(box);
}
};
}
for (size_t i = 0; i < total; i++) {
if (interactive) {
box_wakeup(box1);
}
box_wait(box);
count++;
}
printf(">>> wait over, count=%zd\r\n", count);
};
}
static void test_in_private_stack_thread(size_t cocurrent, size_t n,
size_t& count, bool interactive)
{
go[&] {
size_t total = cocurrent * n;
acl::fiber_tbox<bool> box;
acl::fiber_tbox<bool> box1;
for (size_t j = 0; j < cocurrent; j++) {
std::thread thread([&] {
for (size_t i = 0; i < n; i++) {
if (interactive) {
box_wait(box1);
}
box_wakeup(box);
}
});
thread.detach();
}
for (size_t i = 0; i < total; i++) {
if (interactive) {
box_wakeup(box1);
}
box_wait(box);
count++;
}
printf(">>> wait over, count=%zd\r\n", count);
};
}
static void usage(const char* procname)
{
printf("usage: %s -h [help]\r\n"
" -c cocurrent\r\n"
" -n loop_count\r\n"
" -T [if use_thread]\r\n"
" -B [if interactive]\r\n"
, procname);
}
int main(int argc, char *argv[])
{
int ch, n = 1, cocurrent = 1;
bool use_shared_stack = false, use_thread = false, interactive = false;
acl::acl_cpp_init();
acl::log::stdout_open(true);
while ((ch = getopt(argc, argv, "hc:n:STB")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
return 0;
case 'c':
cocurrent = atoi(optarg);
break;
case 'n':
n = atoi(optarg);
break;
case 'S':
use_shared_stack = true;
break;
case 'T':
use_thread = true;
break;
case 'B':
interactive = true;
break;
default:
break;
}
}
size_t shared_stack_size = acl::fiber::get_shared_stack_size();
printf(">>> shared_stack_size: %zd\r\n", shared_stack_size);
struct timeval begin;
gettimeofday(&begin, NULL);
size_t count = 0;
if (use_shared_stack > 0) {
if (use_thread) {
test_in_shared_stack_thread(cocurrent, n, count,
interactive);
} else {
test_in_shared_stack(cocurrent, n, count, interactive);
}
} else {
if (shared_stack_size > 0) {
printf(">>> This will be crashed in shared stack!\r\n");
}
if (use_thread) {
test_in_private_stack_thread(cocurrent, n, count,
interactive);
} else {
test_in_private_stack(cocurrent, n, count, interactive);
}
}
acl::fiber::schedule();
struct timeval end;
gettimeofday(&end, NULL);
double cost = stamp_sub(&end, &begin);
double speed = (count * 1000) / (cost > 0 ? cost : 0.1);
printf(">>> Total count=%zd, cost=%.2f ms, speed=%.2f qps\r\n",
count, cost, speed);
return 0;
}

View File

@ -0,0 +1 @@
#include "stdafx.h"

View File

@ -0,0 +1,19 @@
// stdafx.h : 标准系统包含文件的包含文件,
// 或是常用但不常更改的项目特定的包含文件
//
#pragma once
// TODO: 在此处引用程序要求的附加头文件
#include "lib_acl.h"
#include "acl_cpp/lib_acl.hpp"
#include "fiber/fiber.hpp"
#include "fiber/go_fiber.hpp"
#ifdef WIN32
#define snprintf _snprintf
#endif

View File

@ -0,0 +1,4 @@
#!/bin/sh
#valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes --max-stackframe=3426305034400000 -v ./fiber -n 10 -m 20
valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes -v ./fiber_tbox -S -c 100 -n 100

View File

@ -0,0 +1,3 @@
include ../Makefile_cpp.in
CFLAGS += -std=c++11
PROG = go_fiber

View File

@ -0,0 +1,75 @@
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
static void fiber1(void)
{
printf("in fiber: %d\r\n", acl::fiber::self());
}
static void fiber2(int n, const char* s)
{
printf("in fiber: %d, n: %d, s: %s\r\n", acl::fiber::self(), n, s);
}
static void fiber3(acl::string& buf)
{
printf("in fiber: %d, buf: %s\r\n", acl::fiber::self(), buf.c_str());
buf = "world";
}
static void fiber4(const acl::string& buf)
{
printf("in fiber: %d, buf: %s\r\n", acl::fiber::self(), buf.c_str());
}
//////////////////////////////////////////////////////////////////////////////
static void usage(const char* procname)
{
printf("usage: %s -h [help] -n fibers_count\r\n", procname);
}
int main(int argc, char *argv[])
{
int ch, n = 10;
acl::acl_cpp_init();
acl::log::stdout_open(true);
while ((ch = getopt(argc, argv, "hn:")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
return 0;
case 'n':
n = atoi(optarg);
break;
default:
break;
}
}
go fiber1;
go[=] {
fiber2(n, "hello world");
};
acl::string buf("hello");
go[&] {
fiber3(buf);
};
go[&] {
fiber4(buf);
};
go[=] {
fiber4(buf);
};
acl::fiber::schedule();
return 0;
}

View File

@ -0,0 +1 @@
#include "stdafx.h"

View File

@ -0,0 +1,19 @@
// stdafx.h : 标准系统包含文件的包含文件,
// 或是常用但不常更改的项目特定的包含文件
//
#pragma once
// TODO: 在此处引用程序要求的附加头文件
#include "lib_acl.h"
#include "acl_cpp/lib_acl.hpp"
#include "fiber/fiber.hpp"
#include "fiber/go_fiber.hpp"
#ifdef WIN32
#define snprintf _snprintf
#endif

View File

@ -0,0 +1,4 @@
#!/bin/sh
#valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes --max-stackframe=3426305034400000 -v ./fiber -n 10 -m 20
valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes -v ./go_fiber

View File

@ -0,0 +1,28 @@
#ifndef __STAMP_INCLUDE_H__
#define __STAMP_INCLUDE_H__
#ifdef __cplusplus
extern "C" {
#endif
static double stamp_sub(const struct timeval *from, const struct timeval *sub)
{
struct timeval res;
memcpy(&res, from, sizeof(struct timeval));
res.tv_usec -= sub->tv_usec;
if (res.tv_usec < 0) {
--res.tv_sec;
res.tv_usec += 1000000;
}
res.tv_sec -= sub->tv_sec;
return (res.tv_sec * 1000.0 + res.tv_usec/1000.0);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -11,14 +11,15 @@
static int __max_loop = 1000;
static int __max_fiber = 1000;
static int __display = 0;
static int __stack_size = 64000;
static __thread struct timeval __begin;
static __thread int __left_fiber = 1000;
static __thread long long __count = 0;
#define DUMMY_SIZE 512000
static void stack_dummy(ACL_FIBER *fiber acl_unused)
{
char buf[81920];
char buf[DUMMY_SIZE];
memset(buf, 0, sizeof(buf));
}
@ -26,51 +27,63 @@ static void stack_dummy(ACL_FIBER *fiber acl_unused)
static void fiber_main(ACL_FIBER *fiber, void *ctx acl_unused)
{
int i;
size_t shared_stack_size = acl_fiber_get_shared_stack_size();
if (0)
printf("\r\nshared_stack_size=%zd\r\n\r\n", shared_stack_size);
if (acl_fiber_use_share_stack(fiber) && shared_stack_size > DUMMY_SIZE) {
stack_dummy(fiber);
}
errno = acl_fiber_errno(fiber);
for (i = 0; i < __max_loop; i++) {
if (__count < 10) {
printf("fiber-%d, run, begin to yield\r\n",
acl_fiber_id(fiber));
}
acl_fiber_yield();
if (!__display)
continue;
if (i <= 2)
printf("fiber-%d, errno: %d\r\n",
if (__count++ < 10) {
printf("fiber-%d, wakeup errno: %d\r\n",
acl_fiber_id(fiber), errno);
printf("---------------------------------------\r\n");
}
}
if (--__left_fiber == 0) {
long long count = __max_fiber * __max_loop;
struct timeval end;
double spent;
gettimeofday(&end, NULL);
spent = stamp_sub(&end, &__begin);
printf("fibers: %d, count: %lld, spent: %.2f, speed: %.2f\r\n",
__max_fiber, count, spent,
(count * 1000) / (spent > 0 ? spent : 1));
}
printf("%s: fiber-%d exiting, count=%lld ...\r\n",
__FUNCTION__, acl_fiber_id(fiber), __count);
}
static void *thread_main(void *ctx acl_unused)
static void *thread_main(void *ctx)
{
ACL_FIBER_ATTR *attr = (ACL_FIBER_ATTR *) ctx;
int i;
gettimeofday(&__begin, NULL);
__left_fiber = __max_fiber;
for (i = 0; i < __max_fiber; i++)
acl_fiber_create(fiber_main, NULL, __stack_size);
for (i = 0; i < __max_fiber; i++) {
acl_fiber_create2(attr, fiber_main, NULL);
}
acl_fiber_schedule();
printf("thread: %lu\r\n", (unsigned long) acl_pthread_self());
return NULL;
}
static void calc_speed(void)
{
long long count = __max_fiber * __max_loop;
struct timeval end;
double spent, speed;
gettimeofday(&end, NULL);
spent = stamp_sub(&end, &__begin);
speed = (count * 1000) / (spent > 0 ? spent : 1);
printf("\r\nfibers: %d, count: %lld, spent: %.2f, speed: %.2f\r\n",
__max_fiber, count, spent, speed);
}
static void usage(const char *procname)
{
printf("usage: %s -h [help]\r\n"
@ -78,7 +91,9 @@ static void usage(const char *procname)
" -c max_fiber\r\n"
" -t max_threads\r\n"
" -d stack_size\r\n"
" -e [if display]\r\n", procname);
" -e [if display]\r\n"
" -S [if use shared stack]\r\n"
, procname);
}
int main(int argc, char *argv[])
@ -86,8 +101,12 @@ int main(int argc, char *argv[])
int ch, i, nthreads = 1;
acl_pthread_attr_t attr;
acl_pthread_t *tids;
ACL_FIBER_ATTR fiber_attr;
size_t stack_size = 64000;
while ((ch = getopt(argc, argv, "hn:c:t:d:e")) > 0) {
acl_fiber_attr_init(&fiber_attr);
while ((ch = getopt(argc, argv, "hn:c:t:ed:S")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
@ -104,7 +123,11 @@ int main(int argc, char *argv[])
nthreads = 1;
break;
case 'd':
__stack_size = atoi(optarg);
stack_size = (size_t) atoi(optarg);
acl_fiber_attr_setstacksize(&fiber_attr, stack_size);
break;
case 'S':
acl_fiber_attr_setsharestack(&fiber_attr, 1);
break;
case 'e':
__display = 1;
@ -114,14 +137,23 @@ int main(int argc, char *argv[])
}
}
acl_fiber_set_shared_stack_size(8000000);
acl_pthread_attr_init(&attr);
tids = (acl_pthread_t *) acl_mycalloc(nthreads, sizeof(acl_pthread_t));
for (i = 0; i < nthreads; i++)
acl_pthread_create(&tids[i], &attr, thread_main, NULL);
gettimeofday(&__begin, NULL);
for (i = 0; i < nthreads; i++)
for (i = 0; i < nthreads; i++) {
acl_pthread_create(&tids[i], &attr, thread_main, &fiber_attr);
}
for (i = 0; i < nthreads; i++) {
acl_pthread_join(tids[i], NULL);
}
calc_speed();
printf("All fiber threads exited now ...\r\n");
acl_myfree(tids);

View File

@ -1,4 +1,4 @@
#!/bin/sh
#valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes --max-stackframe=3426305034400000 -v ./fiber -n 10 -m 20
valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes -v ./fiber -n 1 -m 2
valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes -v ./fiber -c 100 -n 100 -S

View File

@ -3,7 +3,7 @@
#include <stdio.h>
#include "http_servlet.h"
#define STACK_SIZE 320000
static int STACK_SIZE = 128000;
static int __rw_timeout = 0;
static int __schedule_event = FIBER_EVENT_KERNEL;
@ -11,31 +11,31 @@ static void http_server(ACL_FIBER *, void *ctx)
{
acl::socket_stream *conn = (acl::socket_stream *) ctx;
acl::memcache_session *session = new acl::memcache_session("127.0.0.1:11211");
http_servlet *servlet = new http_servlet(conn, session);
servlet->setLocalCharset("gb2312");
//printf("start one http_server\r\n");
acl::memcache_session session("127.0.0.1:11211");
http_servlet servlet(conn, &session);
servlet.setLocalCharset("gb2312");
while (true)
{
if (servlet.doRun() == false)
while (true) {
if (servlet->doRun() == false) {
break;
}
}
printf("close one connection: %d, %s\r\n", conn->sock_handle(),
acl::last_serror());
delete session;
delete servlet;
delete conn;
}
static void fiber_accept(ACL_FIBER *, void *ctx)
{
acl::server_socket* server = (acl::server_socket *) ctx;
while (true)
{
while (true) {
acl::socket_stream* client = server->accept();
if (client == NULL)
{
if (client == NULL) {
printf("accept failed: %s\r\n", acl::last_serror());
break;
}
@ -59,11 +59,10 @@ public:
thread_server(const char* addr)
{
server_inner_ = new acl::server_socket(acl::OPEN_FLAG_REUSEPORT);
if (server_inner_->open(addr) == false)
{
printf("open %s error %s\r\n",
addr, acl::last_serror());
server_inner_ = new acl::server_socket(acl::OPEN_FLAG_REUSEPORT, 128);
if (server_inner_->open(addr) == false) {
printf("%s(%d): open %s error %s\r\n", __FUNCTION__,
__LINE__, addr, acl::last_serror());
exit (1);
}
@ -91,6 +90,7 @@ static void usage(const char* procname)
" -e event\r\n"
" -R reuse_port\r\n"
" -t threads\r\n"
" -z stack_size[default: 128000]\r\n"
" -r rw_timeout\r\n", procname);
}
@ -100,10 +100,8 @@ int main(int argc, char *argv[])
int ch, nthreads = 2;
bool reuse_port = false;
while ((ch = getopt(argc, argv, "hs:r:t:Re:")) > 0)
{
switch (ch)
{
while ((ch = getopt(argc, argv, "hs:r:t:Re:z:")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
return 0;
@ -120,12 +118,17 @@ int main(int argc, char *argv[])
reuse_port = true;
break;
case 'e':
if (strcasecmp(optarg, "kernel") == 0)
if (strcasecmp(optarg, "kernel") == 0) {
__schedule_event = FIBER_EVENT_KERNEL;
else if (strcasecmp(optarg, "poll") == 0)
__schedule_event = FIBER_EVENT_SELECT;
else if (strcasecmp(optarg, "select") == 0)
} else if (strcasecmp(optarg, "poll") == 0) {
__schedule_event = FIBER_EVENT_POLL;
} else if (strcasecmp(optarg, "select") == 0) {
__schedule_event = FIBER_EVENT_SELECT;
}
break;
case 'z':
STACK_SIZE = atoi(optarg);
break;
default:
break;
}
@ -136,26 +139,25 @@ int main(int argc, char *argv[])
acl::server_socket server;
if (!reuse_port)
{
if (server.open(addr) == false)
{
printf("open %s error\r\n", addr.c_str());
if (!reuse_port) {
if (server.open(addr) == false) {
printf("%s(%d): open %s error %s\r\n", __FUNCTION__,
__LINE__, addr.c_str(), acl::last_serror());
exit (1);
}
else
} else {
printf("open %s ok\r\n", addr.c_str());
}
}
std::vector<acl::thread*> threads;
for (int i = 0; i < nthreads; i++)
{
for (int i = 0; i < nthreads; i++) {
acl::thread* thr;
if (reuse_port)
if (reuse_port) {
thr = new thread_server(addr);
else
} else {
thr = new thread_server(server);
}
threads.push_back(thr);
thr->set_detachable(false);
thr->start();
@ -163,8 +165,7 @@ int main(int argc, char *argv[])
}
for (std::vector<acl::thread*>::iterator it = threads.begin();
it != threads.end(); ++it)
{
it != threads.end(); ++it) {
(*it)->wait();
delete *it;
}

View File

@ -9,26 +9,46 @@
#define STACK_SIZE 320000
static void client_callback(int type, ACL_EVENT *event,
ACL_VSTREAM *cstream, void *ctx);
ACL_VSTREAM *conn, void *ctx);
static int __rw_timeout = 0;
static int __stop = 0;
static int __real_http = 0;
static int __use_kernel = 0;
static int __rw_timeout = 0;
static int __stop = 0;
static int __real_http = 0;
static int __use_kernel = 0;
static int __accept_alone = 0;
static int http_demo(ACL_VSTREAM *cstream, const char* res, size_t len)
static int http_demo(ACL_VSTREAM *conn, const char* res, size_t len)
{
char buf[8192];
int ret;
cstream->rw_timeout = __rw_timeout;
conn->rw_timeout = __rw_timeout;
while (1) {
ret = acl_vstream_gets_nonl(cstream, buf, sizeof(buf) - 1);
ret = acl_vstream_gets_nonl(conn, buf, sizeof(buf) -1);
if (ret == ACL_VSTREAM_EOF) {
printf("gets error: %s\r\n", acl_last_serror());
return -1;
}
if (ret > 0) {
buf[ret] = 0;
if (strcasecmp(buf, "stop") == 0) {
__stop = 1;
}
break;
}
}
while (1) {
ret = acl_vstream_gets_nonl(conn, buf, sizeof(buf) - 1);
if (ret == ACL_VSTREAM_EOF) {
printf("gets error: %s\r\n", acl_last_serror());
return -1;
}
if (ret == 0) {
break;
}
buf[ret] = 0;
if (strcasecmp(buf, "stop") == 0) {
@ -36,12 +56,9 @@ static int http_demo(ACL_VSTREAM *cstream, const char* res, size_t len)
printf("----stop now----\r\n");
break;
}
if (ret == 0)
break;
}
if (acl_vstream_writen(cstream, res, len) == ACL_VSTREAM_EOF) {
if (acl_vstream_writen(conn, res, len) == ACL_VSTREAM_EOF) {
printf("write error\r\n");
return -1;
}
@ -51,8 +68,8 @@ static int http_demo(ACL_VSTREAM *cstream, const char* res, size_t len)
static void echo_client(ACL_FIBER *fiber acl_unused, void *ctx)
{
ACL_VSTREAM *cstream = (ACL_VSTREAM *) ctx;
ACL_EVENT *event = (ACL_EVENT *) cstream->context;
ACL_VSTREAM *conn = (ACL_VSTREAM *) ctx;
ACL_EVENT *event = (ACL_EVENT *) conn->context;
const char* res = "HTTP/1.1 200 OK\r\n"
"Date: Tue, 31 May 2016 14:20:28 GMT\r\n"
"Server: acl\r\n"
@ -63,23 +80,23 @@ static void echo_client(ACL_FIBER *fiber acl_unused, void *ctx)
"hello world!";
size_t len = strlen(res);
if (http_demo(cstream, res, len) < 0 || __stop) {
acl_vstream_close(cstream);
if (http_demo(conn, res, len) < 0 || __stop) {
acl_vstream_close(conn);
return;
}
//printf("%s: %d: call acl_event_enable_read again, fd: %d\r\n",
// __FUNCTION__, __LINE__, ACL_VSTREAM_SOCK(cstream));
acl_event_enable_read(event, cstream, 120, client_callback, NULL);
// __FUNCTION__, __LINE__, ACL_VSTREAM_SOCK(conn));
acl_event_enable_read(event, conn, 120, client_callback, NULL);
}
static void http_server(ACL_FIBER *, void *ctx)
{
ACL_VSTREAM *cstream = (ACL_VSTREAM *) ctx;
ACL_EVENT *event = (ACL_EVENT *) cstream->context;
ACL_VSTREAM *client = (ACL_VSTREAM *) ctx;
ACL_EVENT *event = (ACL_EVENT *) client->context;
acl::socket_stream conn;
conn.open(cstream);
conn.open(client);
acl::memcache_session session("127.0.0.1:11211");
http_servlet servlet(&conn, &session);
servlet.setLocalCharset("gb2312");
@ -89,35 +106,56 @@ static void http_server(ACL_FIBER *, void *ctx)
}
conn.unbind();
acl_event_enable_read(event, cstream, 120, client_callback, NULL);
acl_event_enable_read(event, client, 120, client_callback, NULL);
}
static void client_callback(int type acl_unused, ACL_EVENT *event,
ACL_VSTREAM *cstream, void *ctx acl_unused)
ACL_VSTREAM *conn, void *ctx acl_unused)
{
cstream->context = event;
acl_event_disable_readwrite(event, cstream);
conn->context = event;
acl_event_disable_readwrite(event, conn);
if (__real_http)
acl_fiber_create(http_server, cstream, 320000);
else
acl_fiber_create(echo_client, cstream, 160000);
if (__real_http) {
acl_fiber_create(http_server, conn, 128000);
} else {
acl_fiber_create(echo_client, conn, 64000);
}
}
static void fiber_accept(ACL_FIBER *fiber acl_unused, void *ctx)
{
ACL_VSTREAM *sstream = (ACL_VSTREAM *) ctx;
ACL_EVENT *event = (ACL_EVENT *) sstream->context;
while (true) {
char ip[64];
ACL_VSTREAM *conn = acl_vstream_accept(sstream, ip, sizeof(ip));
if (conn == NULL) {
printf("accept error %s\r\n", acl::last_serror());
break;
}
printf(">>>%s: accept one, fd: %d\r\n",
__FUNCTION__, ACL_VSTREAM_SOCK(conn));
acl_event_enable_read(event, conn, 120, client_callback, NULL);
}
acl_fiber_schedule_stop();
}
static void listen_callback(int type acl_unused, ACL_EVENT *event,
ACL_VSTREAM *sstream, void *ctx acl_unused)
{
char ip[64];
ACL_VSTREAM *cstream = acl_vstream_accept(sstream, ip, sizeof(ip));
ACL_VSTREAM *conn = acl_vstream_accept(sstream, ip, sizeof(ip));
if (cstream == NULL) {
if (conn== NULL) {
printf("accept error %s\r\n", acl_last_serror());
return;
}
printf(">>>accept one, fd: %d\r\n", ACL_VSTREAM_SOCK(cstream));
acl_event_enable_read(event, cstream, 120, client_callback, NULL);
printf(">>>accept one, fd: %d\r\n", ACL_VSTREAM_SOCK(conn));
acl_event_enable_read(event, conn, 120, client_callback, NULL);
}
static void fiber_event(ACL_FIBER *fiber acl_unused, void *ctx)
@ -125,13 +163,18 @@ static void fiber_event(ACL_FIBER *fiber acl_unused, void *ctx)
ACL_VSTREAM *sstream = (ACL_VSTREAM *) ctx;
ACL_EVENT *event;
if (__use_kernel)
if (__use_kernel) {
event = acl_event_new(ACL_EVENT_KERNEL, 0, 1, 0);
else
} else {
event = acl_event_new(ACL_EVENT_POLL, 0, 1, 0);
}
printf(">>>enable read fd: %d\r\n", ACL_VSTREAM_SOCK(sstream));
acl_event_enable_listen(event, sstream, 0, listen_callback, NULL);
if (__accept_alone) {
sstream->context = event;
acl_fiber_create(fiber_accept, sstream, STACK_SIZE);
} else {
acl_event_enable_listen(event, sstream, 0, listen_callback, NULL);
}
while (!__stop) {
acl_event_loop(event);
@ -146,8 +189,10 @@ static void fiber_event(ACL_FIBER *fiber acl_unused, void *ctx)
static void usage(const char *procname)
{
printf("usage: %s -h [help] -s listen_addr\r\n"
" -e fiber_event_type[kernel|poll|select]\r\n"
" -r rw_timeout\r\n"
" -R [use real http]\r\n"
" -A [use fiber to accept]\r\n"
" -k [use kernel event]\r\n", procname);
}
@ -155,12 +200,14 @@ int main(int argc, char *argv[])
{
char addr[64];
ACL_VSTREAM *sstream;
int ch;
int ch, fiber_event_type = FIBER_EVENT_KERNEL;
acl::log::stdout_open(true);
acl_fiber_msg_stdout_enable(1);
snprintf(addr, sizeof(addr), "%s", "127.0.0.1:9001");
while ((ch = getopt(argc, argv, "hs:r:Rk")) > 0) {
while ((ch = getopt(argc, argv, "hs:r:RAke:")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
@ -174,14 +221,29 @@ int main(int argc, char *argv[])
case 'R':
__real_http = 1;
break;
case 'A':
__accept_alone = 1;
break;
case 'k':
__use_kernel = 1;
break;
case 'e':
if (strcasecmp(optarg, "kernel") == 0) {
fiber_event_type = FIBER_EVENT_KERNEL;
} else if (strcasecmp(optarg, "poll") == 0) {
fiber_event_type = FIBER_EVENT_POLL;
} else if (strcasecmp(optarg, "select") == 0) {
fiber_event_type = FIBER_EVENT_SELECT;
}
default:
break;
}
}
if (fiber_event_type != FIBER_EVENT_KERNEL) {
__use_kernel = 0;
}
sstream = acl_vstream_listen(addr, 128);
if (sstream == NULL) {
printf("acl_vstream_listen error %s\r\n", acl_last_serror());
@ -194,7 +256,7 @@ int main(int argc, char *argv[])
acl_fiber_create(fiber_event, sstream, STACK_SIZE);
printf("call fiber_schedule\r\n");
acl_fiber_schedule();
acl_fiber_schedule_with(fiber_event_type);
return 0;
}

View File

@ -147,10 +147,7 @@ protected:
void run(void)
{
bool ret;
acl::redis_key cmd_key;
cmd_key.set_pipeline(&conns_);
acl::redis_string cmd_string;
cmd_string.set_pipeline(&conns_);
for (int i = 0; i < n_; i++) {
@ -208,6 +205,9 @@ private:
acl::redis_client_pipeline& conns_;
acl::string cmd_;
int n_;
acl::redis_key cmd_key;
acl::redis_string cmd_string;
};
class test_thread : public acl::thread
@ -370,6 +370,8 @@ int main(int argc, char* argv[])
// stop pipeline thread
pipeline.stop_thread();
printf("The pipeline thread has stopped!\r\n");
#ifdef WIN32
printf("enter any key to exit\r\n");
getchar();

View File

@ -69,12 +69,26 @@ static void fiber_accept(ACL_FIBER *fiber acl_unused, void *ctx)
for (;;) {
ACL_VSTREAM *cstream = acl_vstream_accept(sstream, NULL, 0);
char buf[1024];
int ret;
if (cstream == NULL) {
printf("acl_vstream_accept error %s\r\n",
acl_last_serror());
break;
}
ret = acl_vstream_gets(cstream, buf, sizeof(buf) - 1);
if (ret == ACL_VSTREAM_EOF) {
printf("get first line error\r\n");
acl_vstream_close(cstream);
continue;
} else if (acl_vstream_writen(cstream, buf, ret) != ret) {
printf("write error\r\n");
acl_vstream_close(cstream);
continue;
}
//printf("accept one, fd: %d\r\n", ACL_VSTREAM_SOCK(cstream));
acl_fiber_create(echo_client, cstream, __stack_size);
//printf("continue to accept\r\n");

View File

@ -34,7 +34,6 @@ static int __listen_port = 9001;
static int __listen_qlen = 64;
static int __rw_timeout = 0;
static int __echo_data = 1;
static int __stack_size = 320000;
static int check_read(int fd, int timeout)
{
@ -51,12 +50,15 @@ static int check_read(int fd, int timeout)
return -1;
}
if (n == 0)
if (n == 0) {
return 0;
if (pfd.revents & POLLIN)
}
if (pfd.revents & POLLIN) {
return 1;
else
} else {
printf(">>>poll return n=%d read no ready,fd=%d, pfd=%p\n", n, fd, &pfd);
return 0;
}
}
static void echo_client(ACL_FIBER *fiber acl_unused, void *ctx)
@ -129,12 +131,15 @@ static void echo_client(ACL_FIBER *fiber acl_unused, void *ctx)
}
}
static void fiber_accept(ACL_FIBER *fiber acl_unused, void *ctx acl_unused)
static void fiber_accept(ACL_FIBER *fiber acl_unused, void *ctx)
{
ACL_FIBER_ATTR *attr = (ACL_FIBER_ATTR*) ctx;
SOCKET lfd;
int on = 1;
struct sockaddr_in sa;
assert(attr);
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(__listen_port);
@ -181,7 +186,7 @@ static void fiber_accept(ACL_FIBER *fiber acl_unused, void *ctx acl_unused)
__nconnect++;
printf("accept one, fd: %u, %p\r\n", cfd, pfd);
acl_fiber_create(echo_client, pfd, __stack_size);
acl_fiber_create2(attr, echo_client, pfd);
}
CLOSE(lfd);
@ -214,16 +219,20 @@ static void usage(const char *procname)
" -r rw_timeout\r\n"
" -q listen_queue\r\n"
" -z stack_size\r\n"
" -Z [if use shared stack]\r\n"
" -S [if using single IO, default: no]\r\n", procname);
}
int main(int argc, char *argv[])
{
int ch, event_mode = FIBER_EVENT_KERNEL;
ACL_FIBER_ATTR fiber_attr;
int stack_size = 320000;
acl_fiber_attr_init(&fiber_attr);
snprintf(__listen_ip, sizeof(__listen_ip), "%s", "127.0.0.1");
while ((ch = getopt(argc, argv, "hs:p:r:q:Sz:e:")) > 0) {
while ((ch = getopt(argc, argv, "hs:p:r:q:Sz:Ze:")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
@ -244,7 +253,11 @@ int main(int argc, char *argv[])
__echo_data = 0;
break;
case 'z':
__stack_size = atoi(optarg);
stack_size = atoi(optarg);
acl_fiber_attr_setstacksize(&fiber_attr, stack_size);
break;
case 'Z':
acl_fiber_attr_setsharestack(&fiber_attr, 1);
break;
case 'e':
if (strcasecmp(optarg, "select") == 0)
@ -270,7 +283,7 @@ int main(int argc, char *argv[])
#endif
printf("%s: call fiber_creater\r\n", __FUNCTION__);
acl_fiber_create(fiber_accept, NULL, 327680);
acl_fiber_create(fiber_accept, &fiber_attr, 327680);
#ifndef SCHEDULE_AUTO
acl_fiber_create(fiber_memcheck, NULL, 640000);

View File

@ -2,4 +2,4 @@
#valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes --max-stackframe=3426305034400000 -v ./fiber -n 10 -m 20
#valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes -v ./server -e poll
valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes -v ./server
valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes -v ./server -r 10

View File

@ -1,31 +1,76 @@
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static bool stop = false;
static void echo_client(acl::socket_stream* conn, acl::fiber_tbox<bool> *box)
{
printf("fiber-%d running, sock fd=%d\r\n",
acl::fiber::self(), conn->sock_handle());
char buf[8192];
while (true) {
int ret = conn->read(buf, sizeof(buf), false);
if (ret == -1) {
break;
}
buf[ret] = 0;
if (strncasecmp(buf, "stop", 4) == 0) {
stop = true;
break;
}
if (conn->write(buf, ret) == -1) {
break;
}
if (strncasecmp(buf, "bye", 3) == 0) {
break;
}
}
box->push(NULL);
}
static void fiber_client(acl::socket_stream* conn)
{
printf("fiber-%d running\r\n", acl::fiber::self());
acl::fiber_tbox<bool>* box = new acl::fiber_tbox<bool>;
char buf[8192];
while (true)
{
int ret = conn->read(buf, sizeof(buf), false);
if (ret == -1)
break;
if (conn->write(buf, ret) == -1)
break;
int ret = conn->read(buf, sizeof(buf), false);
if (ret == -1) {
printf("read from fd=%d error\r\n", conn->sock_handle());
delete conn;
return;
}
if (conn->write(buf, ret) == -1) {
printf("write to fd=%d error\r\n", conn->sock_handle());
delete conn;
return;
}
go[&] {
echo_client(conn, box);
};
box->pop();
delete box;
printf("%s: delete fd=%d\r\n", __FUNCTION__, conn->sock_handle());
delete conn;
if (stop) {
printf("Stop fiber schedule now\r\n");
acl::fiber::schedule_stop();
}
}
static void fiber_server(acl::server_socket& ss)
{
while (true)
{
while (true) {
acl::socket_stream* conn = ss.accept();
if (conn == NULL)
{
if (conn == NULL) {
printf("accept error %s\r\n", acl::last_serror());
break;
}
@ -51,10 +96,8 @@ int main(int argc, char *argv[])
acl::string addr("127.0.0.1:9006");
acl::log::stdout_open(true);
while ((ch = getopt(argc, argv, "hs:")) > 0)
{
switch (ch)
{
while ((ch = getopt(argc, argv, "hs:")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
return 0;
@ -67,8 +110,7 @@ int main(int argc, char *argv[])
}
acl::server_socket ss;
if (ss.open(addr) == false)
{
if (ss.open(addr) == false) {
printf("listen %s error %s\r\n", addr.c_str(), acl::last_serror());
return 1;
}

View File

@ -1,6 +1,9 @@
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int __event_type = ACL_EVENT_KERNEL;
static bool echo(acl::socket_stream& conn)
{
@ -71,7 +74,7 @@ static void fiber_client(acl::socket_stream* conn)
printf("fiber-%d running\r\n", acl::fiber::self());
bool stop = false;
ACL_EVENT *event = acl_event_new(ACL_EVENT_POLL, 0, 1, 0);
ACL_EVENT *event = acl_event_new(__event_type, 0, 1, 0);
ACL_VSTREAM *cstream = conn->get_vstream();
cstream->context = conn;
conn->set_ctx(&stop);
@ -105,7 +108,7 @@ static void fiber_server(acl::server_socket& ss)
static void usage(const char* procname)
{
printf("usage: %s -h [help] -s listen_addr\r\n", procname);
printf("usage: %s -h [help] -s listen_addr -e event_type[kernel|poll|select]\r\n", procname);
}
int main(int argc, char *argv[])
@ -116,7 +119,7 @@ int main(int argc, char *argv[])
acl::string addr("127.0.0.1:9006");
acl::log::stdout_open(true);
while ((ch = getopt(argc, argv, "hs:")) > 0) {
while ((ch = getopt(argc, argv, "hs:e:")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
@ -124,6 +127,14 @@ int main(int argc, char *argv[])
case 's':
addr = optarg;
break;
case 'e':
if (strcasecmp(optarg, "poll") == 0) {
__event_type = ACL_EVENT_POLL;
} else if (strcasecmp(optarg, "select") == 0) {
__event_type = ACL_EVENT_SELECT;
} else {
__event_type = ACL_EVENT_KERNEL;
}
default:
break;
}

View File

@ -13,6 +13,7 @@
#include "lib_acl.h"
#include "acl_cpp/lib_acl.hpp"
#include "fiber/lib_fiber.hpp"
#include "fiber/go_fiber.hpp"
#ifdef WIN32
#define snprintf _snprintf

View File

@ -0,0 +1,2 @@
include ../Makefile_cpp.in
PROG = server

View File

@ -0,0 +1,149 @@
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
static bool tried = false, is_sleeping = false;
static acl::socket_stream* first = NULL, *second = NULL;
static void fiber_client(acl::socket_stream* conn)
{
conn->set_rw_timeout(20);
int fd = conn->sock_handle();
printf("fiber-%d running, fiber=%p\r\n", acl::fiber::self(), acl_fiber_running());
char buf[8192];
while (true) {
printf(">>>%s: fiber=%p, begin read, fd=%d, %d\n",
__FUNCTION__, acl_fiber_running(),
conn->sock_handle(), fd);
int ret = conn->read(buf, sizeof(buf), false);
printf(">>>%s: fiber=%p, read=%d, fd=%d, %d\n",
__FUNCTION__, acl_fiber_running(), ret,
conn->sock_handle(), fd);
if (ret == -1) {
printf("fiber-%d, read error %s from fd %d, %d, fiber=%p\r\n",
acl::fiber::self(), acl::last_serror(),
conn->sock_handle(), fd, acl_fiber_running());
break;
}
if (conn->write(buf, ret) == -1) {
printf("fiber-%d, write error %s to fd %d\r\n",
acl::fiber::self(), acl::last_serror(),
conn->sock_handle());
break;
}
if (conn == first) {
if (second) {
printf("---close another fd=%d, me fiber=%p\n",
second->sock_handle(), acl_fiber_running());
int sock = second->sock_handle();
if (is_sleeping) {
second->unbind_sock();
}
close(sock);
//second->close();
printf("---close another fd=%d ok, fiber=%p\n",
sock, acl_fiber_running());
second = NULL;
} else {
printf("---another fd closed\r\n");
}
}
//continue;
if (conn == second) {
time_t begin = time(NULL);
printf("second fiber-%d, %p, fd=%d sleep\n",
acl::fiber::self(), acl_fiber_running(),
conn->sock_handle());
is_sleeping = true;
sleep(15);
is_sleeping = false;
printf("second fiber-%d, %p, fd=%d wakeup, diff=%ld second\n",
acl::fiber::self(), acl_fiber_running(),
conn->sock_handle(), time(NULL) - begin);
}
}
printf("\r\n>>fiber=%p, delete conn, fd=%d\n",
acl_fiber_running(), conn->sock_handle());
delete conn;
printf(">>fiber=%p, delete conn ok: %s\n\n",
acl_fiber_running(), acl::last_serror());
}
static void fiber_server(acl::server_socket& ss)
{
while (true) {
acl::socket_stream* conn = ss.accept();
if (conn == NULL) {
printf("accept error %s\r\n", acl::last_serror());
break;
}
printf("accept ok, fd: %d\r\n", conn->sock_handle());
if (first == NULL) {
first = conn;
} else if (second == NULL) {
if (!tried) {
second = conn;
tried = true;
}
}
go[=] {
fiber_client(conn);
};
}
}
static void usage(const char* procname)
{
printf("usage: %s -h [help] -s listen_addr\r\n", procname);
}
int main(int argc, char *argv[])
{
int ch;
acl::acl_cpp_init();
acl::string addr("127.0.0.1:9006");
acl::log::stdout_open(true);
acl::fiber::stdout_open(true);
while ((ch = getopt(argc, argv, "hs:")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
return 0;
case 's':
addr = optarg;
break;
default:
break;
}
}
acl::server_socket ss;
if (!ss.open(addr)) {
printf("listen %s error %s\r\n", addr.c_str(), acl::last_serror());
return 1;
}
printf("listen %s ok\r\n", addr.c_str());
go[&] {
fiber_server(ss);
};
acl::fiber::schedule(); // start fiber schedule
return 0;
}

View File

@ -0,0 +1 @@
#include "stdafx.h"

View File

@ -0,0 +1,22 @@
// stdafx.h : 标准系统包含文件的包含文件,
// 或是常用但不常更改的项目特定的包含文件
//
#pragma once
//#include <iostream>
//#include <tchar.h>
// TODO: 在此处引用程序要求的附加头文件
#include "lib_acl.h"
#include "acl_cpp/lib_acl.hpp"
#include "fiber/fiber.hpp"
#include "fiber/libfiber.h"
#include "fiber/go_fiber.hpp"
#ifdef WIN32
#define snprintf _snprintf
#endif

1
lib_fiber/samples/server6/t.sh Executable file
View File

@ -0,0 +1 @@
valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes -v ./server