mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-11-29 18:37:41 +08:00
Merge remote-tracking branch 'origin/master' into dev_mac_support_cross_compilation
This commit is contained in:
commit
5ef96d62fe
187
.ycm_extra_conf.py
Normal file
187
.ycm_extra_conf.py
Normal 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 {}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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_) {
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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_;
|
||||
|
@ -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_;
|
||||
|
@ -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_;
|
||||
|
@ -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_);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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]);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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_);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -57,6 +57,7 @@ add_definitions(
|
||||
"-Wno-long-long"
|
||||
"-Wuninitialized"
|
||||
# "-DUSE_JMP"
|
||||
# "-DSHARE_STACK"
|
||||
"-DUSE_FAST_RING"
|
||||
"-D_POSIX_PTHREAD_SEMANTICS"
|
||||
"-DACL_PREPARE_COMPILE"
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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}
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 方法启动协程后,本
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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");
|
||||
|
4
lib_fiber/samples-c++1x/fiber/valgrind.sh
Executable file
4
lib_fiber/samples-c++1x/fiber/valgrind.sh
Executable 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
|
3
lib_fiber/samples-c++1x/fiber_tbox/Makefile
Normal file
3
lib_fiber/samples-c++1x/fiber_tbox/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
include ../Makefile_cpp.in
|
||||
CFLAGS += -std=c++11
|
||||
PROG = fiber_tbox
|
249
lib_fiber/samples-c++1x/fiber_tbox/main.cpp
Normal file
249
lib_fiber/samples-c++1x/fiber_tbox/main.cpp
Normal 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;
|
||||
}
|
1
lib_fiber/samples-c++1x/fiber_tbox/stdafx.cpp
Normal file
1
lib_fiber/samples-c++1x/fiber_tbox/stdafx.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "stdafx.h"
|
19
lib_fiber/samples-c++1x/fiber_tbox/stdafx.h
Normal file
19
lib_fiber/samples-c++1x/fiber_tbox/stdafx.h
Normal 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
|
||||
|
4
lib_fiber/samples-c++1x/fiber_tbox/valgrind.sh
Executable file
4
lib_fiber/samples-c++1x/fiber_tbox/valgrind.sh
Executable 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
|
3
lib_fiber/samples-c++1x/go_fiber/Makefile
Normal file
3
lib_fiber/samples-c++1x/go_fiber/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
include ../Makefile_cpp.in
|
||||
CFLAGS += -std=c++11
|
||||
PROG = go_fiber
|
75
lib_fiber/samples-c++1x/go_fiber/main.cpp
Normal file
75
lib_fiber/samples-c++1x/go_fiber/main.cpp
Normal 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;
|
||||
}
|
1
lib_fiber/samples-c++1x/go_fiber/stdafx.cpp
Normal file
1
lib_fiber/samples-c++1x/go_fiber/stdafx.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "stdafx.h"
|
19
lib_fiber/samples-c++1x/go_fiber/stdafx.h
Normal file
19
lib_fiber/samples-c++1x/go_fiber/stdafx.h
Normal 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
|
||||
|
4
lib_fiber/samples-c++1x/go_fiber/valgrind.sh
Executable file
4
lib_fiber/samples-c++1x/go_fiber/valgrind.sh
Executable 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
|
28
lib_fiber/samples-c++1x/stamp.h
Normal file
28
lib_fiber/samples-c++1x/stamp.h
Normal 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
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
2
lib_fiber/samples/server6/Makefile
Normal file
2
lib_fiber/samples/server6/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
include ../Makefile_cpp.in
|
||||
PROG = server
|
149
lib_fiber/samples/server6/main.cpp
Normal file
149
lib_fiber/samples/server6/main.cpp
Normal 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;
|
||||
}
|
1
lib_fiber/samples/server6/stdafx.cpp
Normal file
1
lib_fiber/samples/server6/stdafx.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "stdafx.h"
|
22
lib_fiber/samples/server6/stdafx.h
Normal file
22
lib_fiber/samples/server6/stdafx.h
Normal 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
1
lib_fiber/samples/server6/t.sh
Executable file
@ -0,0 +1 @@
|
||||
valgrind --tool=memcheck --leak-check=yes --leak-check=full --show-reachable=yes -v ./server
|
Loading…
Reference in New Issue
Block a user