Coder Social home page Coder Social logo

owent / libcopp Goto Github PK

View Code? Open in Web Editor NEW
801.0 40.0 103.0 2.65 MB

cross-platform coroutine library in c++

License: MIT License

CMake 3.02% C++ 62.34% C 1.10% Shell 1.30% Assembly 31.02% Batchfile 0.02% PowerShell 1.19%
boost coroutine cpp cross-platform performance c-plus-plus assembly await then timer

libcopp's Introduction

libcopp

Cross-platform coroutine library in C++ .

image

image

Release Code size Repo size CI build status Coveralls coverage Language grade: C/C++ Forks Stars

CI Job Matrix

Target System Toolchain Note
Linux GCC Static linking
Linux GCC Dynamic linking
Linux GCC-latest
Linux GCC-latest No Exception
Linux GCC-latest Thread Unsafe
Linux GCC 4.8 Legacy
Linux Clang-latest With libc++
MinGW64 GCC Dynamic linking
Windows Visual Studio 2019 Static linking
Windows Visual Studio 2019 Dynamic linking
Windows Visual Studio 2017 Legacy,Static linking
macOS AppleClang With libc++

LICENSE

License under the MIT LICENSE

Document

Documents can be found at https://libcopp.atframe.work , API references canbe found at https://libcopp.atframe.work/doxygen/html/ .(Generated by sphinx and doxygen with docs/sphinx and docs/libcopp.doxyfile.in).

UPGRADE FROM 1.3.X-1.4.X to 2.X

  • Add using value_type = int; into T when using cotask::task<T>.
  • Rename stack_allocator_t to stack_allocator_type in T when using cotask::task<T>.
  • Rename coroutine_t to coroutine_type in T when using cotask::task<T>.
  • Rename libcopp::util::* to copp::util::.
  • We are not allowed to use libcopp::util::intrusive_ptr<cotask::impl::task_impl> now, please use cotask::task<T>::ptr_type instead.

UPGRADE FROM 1.2.X to 1.3.X-1.4.X

  • Rename cotask::task::await into cotask::task::await_task
  • Replace cotask::task<TCO_MACRO, TTASK_MACRO> with cotask::task<TCO_MACRO> , we don't allow to custom id allocator now.
  • Replace cotask::core::standard_int_id_allocator<uint64_t> with copp::util::uint64_id_allocator , we don't allow to custom id allocator now.
  • Require gcc 4.8+, MSVC 15+(Visual Studio 2017)>)
  • Require cmake 3.12.0 or upper

INSTALL

libcopp use cmake to generate makefile and switch build tools.

Prerequisites

  • [required] GCC or Clang or MSVC or clang-cl support ISO C++ 11 and upper
  • [required] cmake 3.16.0 and upper
  • [optional] gtest 1.6.0 and upper (Better unit test supported)
  • [optional] Boost.Test (Boost.Test supported)

Unix

  • [required] ar, as, ld (binutils) or llvm
  • [optional] if using gtest , pthread is required.

Windows

  • [required] masm (in MSVC)
  • [optional] if using gtest, pthread is required.

Install with vcpkg

  1. Clone and setup vcpkg (See more detail on https://github.com/Microsoft/vcpkg)
    git clone https://github.com/Microsoft/vcpkg.git
    cd vcpkg
    PS> bootstrap-vcpkg.bootstrap
    Linux:~/$ ./bootstrap-vcpkg.sh
  2. Install libcopp
    PS> .\vcpkg install libcopp [--triplet x64-windows-static/x64-windows/x64-windows-static-md and etc...]
    Linux:~/$ ./vcpkg install libcopp
  3. See using with cmake <usage-using with-cmake> for cmake below.

Custom Build

  1. Clone and make a build directory
    git clone --single-branch --depth=1 -b master https://github.com/owent/libcopp.git 
    mkdir libcopp/build && cd libcopp/build
  2. Run cmake command
    # cmake <libcopp dir> [options...]
    cmake .. -DPROJECT_ENABLE_UNITTEST=YES -DPROJECT_ENABLE_SAMPLE=YES
  3. Make libcopp
    cmake --build . --config RelWithDebInfo # or make [options] when using Makefile
  4. Run test/sample/benchmark [optional]
    # Run test => Required: PROJECT_ENABLE_UNITTEST=YES
    ctest -VV . -C RelWithDebInfo -L libcopp.unit_test
    # Run sample => Required: PROJECT_ENABLE_SAMPLE=YES
    ctest -VV . -C RelWithDebInfo -L libcopp.sample
    # Run benchmark => Required: PROJECT_ENABLE_SAMPLE=YES
    ctest -VV . -C RelWithDebInfo -L libcopp.benchmark
  5. Install [optional]
    cmake --build . --config RelWithDebInfo --target install # or make install when using Makefile
  6. Then just include and link libcopp.*/libcotask.*, or see using with cmake <usage-using with-cmake> for cmake below.

CMake Options

Options can be cmake options. such as set compile toolchains, source directory or options of libcopp that control build actions. libcopp options are listed below:

Option Description
BUILD_SHARED_LIBS=YES|NO [default=NO] Build dynamic library.
LIBCOPP_ENABLE_SEGMENTED_STACKS=YES|NO [default=NO] Enable split stack supported context.(it's only availabe in linux and gcc 4.7.0 or upper)
LIBCOPP_ENABLE_VALGRIND=YES|NO [default=YES] Enable valgrind supported context.
PROJECT_ENABLE_UNITTEST=YES|NO [default=NO] Build unit test.
PROJECT_ENABLE_SAMPLE=YES|NO [default=NO] Build samples.
LIBCOPP_LOCK_DISABLE_THIS_MT=YES|NO [default=NO] Disable multi-thread support for copp::this_coroutine and cotask::this_task.
LIBCOPP_DISABLE_ATOMIC_LOCK=YES|NO [default=NO] Disable multi-thread support.
LIBCOTASK_ENABLE=YES|NO [default=YES] Enable build libcotask.
LIBCOPP_FCONTEXT_USE_TSX=YES|NO [default=YES] Enable Intel Transactional Synchronisation Extensions (TSX).
LIBCOPP_MACRO_TLS_STACK_PROTECTOR=YES|NO [default=NO] Users need set LIBCOPP_MACRO_TLS_STACK_PROTECTOR=ON when compiling with -fstack-protector. Because it changes the default context switching logic.
GTEST_ROOT=[path] set gtest library install prefix path
BOOST_ROOT=[path] set Boost.Test library install prefix path

USAGE

Using with cmake

  1. Using set(Libcopp_ROOT <where to find libcopp/INSTALL_PREFIX>)
  2. Just using find_package(Libcopp) to use libcopp module.
  3. Example:(we assume the target name is stored in ${CUSTOM_TARGET_NAME})
find_package(Libcopp CONFIG REQUIRED)
target_link_libraries(${CUSTOM_TARGET_NAME} libcopp::cotask)
# Or just using copp by target_link_libraries(${CUSTOM_TARGET_NAME} libcopp::copp)

If using MSVC and vcpkg, CRT must match the triplet of vcpkg, these codes below may be helpful:

if (MSVC AND VCPKG_TOOLCHAIN)
    if(DEFINED ENV{VCPKG_DEFAULT_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET)
        set(VCPKG_TARGET_TRIPLET "$ENV{VCPKG_DEFAULT_TRIPLET}" CACHE STRING "")
    endif()
    if (VCPKG_TARGET_TRIPLET MATCHES "^.*windows-static$")
        set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>" CACHE STRING "")
    else ()
        set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL" CACHE STRING "")
    endif ()
endif ()

See more detail on https://github.com/Microsoft/vcpkg/tree/master/ports/libcopp .

Directly use headers and libraries

Just include headers and linking library file of your platform to use libcopp.

LIBCOPP_PREFIX=<WHERE TO INSTALL libcopp>

# Example command for build sample with gcc 4.9 or upper on Linux
for source in sample_readme_*.cpp; do
    g++ -std=c++14 -O2 -g -ggdb -Wall -Werror -fPIC -rdynamic -fdiagnostics-color=auto -Wno-unused-local-typedefs \
        -I$LIBCOPP_PREFIX/include -L$LIBCOPP_PREFIX/lib64 -lcopp -lcotask $source -o $source.exe;
done

# Example command for build sample with clang 3.9 or upper and libc++ on Linux
for source in sample_readme_*.cpp; do
    clang++ -std=c++17 -stdlib=libc++ -O2 -g -ggdb -Wall -Werror -fPIC -rdynamic        \
        -I$LIBCOPP_PREFIX/include -L$LIBCOPP_PREFIX/lib64 -lcopp -lcotask -lc++ -lc++abi  \
        $source -o $source.exe;
done

# AppleClang on macOS just like those scripts upper.
# If you are using MinGW on Windows, it's better to add -static-libstdc++ -static-libgcc to 
#     use static linking and other scripts are just like those on Linux.
# Example command for build sample with MSVC 1914 or upper on Windows & powershell(Debug Mode /MDd)
foreach ($source in Get-ChildItem -File -Name .\sample_readme_*.cpp) {
    cl /nologo /MP /W4 /wd"4100" /wd"4125" /EHsc /std:c++17 /Zc:__cplusplus /O2 /MDd /I$LIBCOPP_PREFIX/include $LIBCOPP_PREFIX/lib64/copp.lib $LIBCOPP_PREFIX/lib64/cotask.lib $source
}

Get Start & Example

There serveral samples to use copp::coroutine_contextcopp::coroutine_context_fiber and cotask::task :

  1. Using coroutine context
  2. Using coroutine task
  3. Using coroutine task manager
  4. Using stack pool
  5. Using task::then or task::await_task
  6. Using copp::callable_promise of c++20 coroutine
  7. Using copp::generator_future for c++20 coroutine
  8. Custom error (timeout for example) when using c++20 coroutine
  9. Let c++20 coroutine work with cotask::task
  10. Using Windows fiber and SetUnhandledExceptionFilter on Windows with cotask::task

All sample codes can be found on EXAMPLES <examples_doc_anchor> and sample .

NOTICE

Split stack support: if in Linux and user gcc 4.7.0 or upper, add -DLIBCOPP_ENABLE_SEGMENTED_STACKS=YES to use split stack supported context.

It's recommanded to use stack pool instead of gcc splited stack.

BENCHMARK

Please see CI output for latest benchmark report. Click to visit Github Actions .

FAQ

Q: How to enable c++20 coroutine

ANS: Add /std:c++latest /await for MSVC 1932 and below or -std=c++20 -fcoroutines-ts -stdlib=libc++ for clang 13 and below or -std=c++20 -fcoroutines for gcc 10.

If you can just use -std=c++20 -stdlib=libc++ clang 14 or above, -astd=c++20 for gcc 11 or above, and /std:c++latest for MSVC 1932 or above.

Q: Will libcopp handle exception?

ANS: When using c++11 or above, libcopp will catch all unhandled exception and rethrow it after coroutine resumed.

Q: Why SetUnhandledExceptionFilter can not catch the unhandled exception in a coroutine?

ANS: SetUnhandledExceptionFilter only works with Windows Fiber, please see sample/sample_readme_11.cpp for details.

FEEDBACK

If you has any question, please create a issue and provide the information of your environments. For example:

  • OS: Windows 10 Pro 19041 (This can be see after running ``msinfo32``) / Manjaro(Arch) Linux Linux 5.4.39-1-MANJARO
  • Compiler: Visual Studio 2019 C++ 16.5.5 with VS 2019 C++ v14.25 or MSVC 1925/ gcc 9.3.0
  • CMake Commands: cmake .. -G "Visual Studio 16 2019" -A x64 -DLIBCOPP_FCONTEXT_USE_TSX=ON -DPROJECT_ENABLE_UNITTEST=ON -DPROJECT_ENABLE_SAMPLE=ON-DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=%cd%/install-prefix / cmake .. -G Ninja -DLIBCOPP_FCONTEXT_USE_TSX=ON -DPROJECT_ENABLE_UNITTEST=ON -DPROJECT_ENABLE_SAMPLE=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/opt/libcopp
  • Compile Commands: cmake --build . -j
  • Related Environment Variables: Please provide all the environment variables which will change the cmake toolchain, CCCXXAR and etc.

CONSTRIBUTORS

THANKS TO

libcopp's People

Contributors

owent avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libcopp's Issues

请教关于task超时的问题

在 sleep 6秒后调用tick函数,发现打印的协成状态并非超时状态。查看代码看到last_tick_time_初始化是0,
如果在启动任务前,没有调用过tick函数,就无法触发超时状态。想请教下这样是否有问题?

代码如下:

#include <inttypes.h>
#include <stdint.h>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <iostream>

// include context header file
#include <libcotask/task.h>
#include <libcotask/task_manager.h>

// create a task manager
typedef cotask::task<> my_task_t;
typedef my_task_t::ptr_t task_ptr_type;
typedef cotask::task_manager<my_task_t> mgr_t;
mgr_t::ptr_t task_mgr = mgr_t::create();

// If you task manager to manage timeout, it's important to call tick interval

void tick() {
  // the first parameter is second, and the second is nanosecond
  task_mgr->tick(time(nullptr), 0);
}

int main() {
  // create two coroutine task
  task_ptr_type co_task = my_task_t::create([]() {
    std::cout << "task " << cotask::this_task::get<my_task_t>()->get_id() << " started" << std::endl;
    cotask::this_task::get_task()->yield();
    std::cout << "task " << cotask::this_task::get<my_task_t>()->get_id() << " resumed" << std::endl;
    return 0;
  });
  task_ptr_type co_another_task = my_task_t::create([]() {
    std::cout << "task " << cotask::this_task::get<my_task_t>()->get_id() << " started" << std::endl;
    cotask::this_task::get_task()->yield();

    cotask::EN_TASK_STATUS status = cotask::this_task::get<my_task_t>()->get_status();

    std::cout << "task " << cotask::this_task::get<my_task_t>()->get_id() << " resumed" << " status: " << status << std::endl;
    return 0;
  });

  int res = task_mgr->add_task(co_task, 5, 0);  // add task and setup 5s for timeout
  if (res < 0) {
    std::cerr << "some error: " << res << std::endl;
    return res;
  }

  res = task_mgr->add_task(co_another_task, 5, 0);  // add task without timeout
  if (res < 0) {
    std::cerr << "some error: " << res << std::endl;
    return res;
  }

  res = task_mgr->start(co_task->get_id());
  if (res < 0) {
    std::cerr << "start task " << co_task->get_id() << " failed, error code: " << res << std::endl;
  }

  res = task_mgr->start(co_another_task->get_id());
  if (res < 0) {
    std::cerr << "start task " << co_another_task->get_id() << " failed, error code: " << res << std::endl;
  }

  res = task_mgr->resume(co_task->get_id());
  if (res < 0) {
    std::cerr << "resume task " << co_task->get_id() << " failed, error code: " << res << std::endl;
  }

  sleep(6);
  tick();

  return 0;
}

输出:

task 54892719658500096 started
task 54892719658500097 started
task 54892719658500096 resumed
task 54892719658500097 resumed status: 6

关于 copp::coroutine_context_default::ptr_t 的疑问

`
#include <libcopp/coroutine/coroutine_context_container.h>
typedef copp::coroutine_context_default coroutine_t;

void download_other_thread(copp::coroutine_context* ctx)
{
std::this_thread::sleep_for(std::chrone::second(6));
ctx->resume();
}

int co_download(void ){
copp::coroutine_context
ctx = copp::this_coroutine::get_coroutine();
thread_pool::add(download_other_thread, ctx); // 其他线程处理具体的逻辑
ctx->yield();

printf("done!\n");

}

int main () {
for (int i= 0;i< 5;++i){
coroutin_t::ptr_t context = coroutine_t::create(co_download);
context->start();
// context.detach();
}

for (;;){}
return 0 

}
`

我希望是co_download 时候抛给其他线程处理,yield, 然后其他线程处理后 resume
但是这样是会抛错的, 因为 context 已经析构了
我看到 copp::this_coroutine::get_coroutine() 其实就是 context.get()
所以 context.detach() 后是可以的

但是这样疑惑就是 这个 ptr 我怎么主动 delete ? 还是说不用管?

我觉得你的框架非常好用, 就是这个疑问我一直困扰着.
不知都是不是我的使用思路有问题, 如果是的话, 上面那个需求怎么实现 ?
谢谢

vcpkg安装的1.4.1版本,编译时报错

OS: ubuntu18.04
Compiler: gcc 11.1.0
安装方式: ./vcpkg install libcopp:x64-linux
项目Cmake配置
target_link_libraries(NFMasterServerPlugin libcopp.a)
target_link_libraries(NFMasterServerPlugin libcotask.a)
报错信息
err

error: ‘xx’ is not a member of ‘xxx {aka xxx}’

使用task action,写一个自定义的action 类
class ThenTaskAction1
{
public:
ThenTaskAction1(){}

int operator()(void*)
{
    return 0;
}

private:
};

然后调用copp_task的then方法:
using simple_task_t = cotask::task<>;
auto co_task = simple_task_t::create(
{
});
if (nullptr != co_task)
{
co_task->start();
//auto then_ptr1 = co_task->then(ThenTaskAction1()); // build OK

       ThenTaskAction1 tmp;
        auto then_ptr2 = co_task->then(tmp);                                 // 错误: ThenTaskAction1没有operator()成员 
    }
    else
        printf("error create coroutine %d\n", i);

我这边跟踪了一下原因是后面一种调用在模板参数类型是ThenTaskAction1&, 然而前者解释模板参数类型是ThenTaskAction1
于是我这边的解决方式是
在task_actions.h:91行改成
virtual int operator()(void *priv_data) {
return detail::task_action_functor_check::call(&std::remove_reference<value_type>::type::operator(), functor_, priv_data);
}
去掉了引用

看一下大神有什么好的解决方式或者有什么见解

couldn't complie on aarch64 platform

CMake Error at src/libcopp/CMakeLists.txt:14 (add_library):
Cannot find source file:

/root/test/libcopp-1.2.1/src/libcopp/fcontext/asm/jump_aarch64_sysv_elf_gas.S

请教关于开启协程的问题

Description of your problem.
作者你好,请教一下在开启协程执行一个函数的时候,如何向该函数传递参数呢,我只在example中看到参数为void *

Describe the solution you'd like
我想在一个while循环中开启协程执行std::size_t copy_buffer(boost::asio::ip::tcp::socket &write_dst, boost::asio::ip::tcp::socket &read_src)函数
我想实现的功能伪代码如下:

void relay(boost::asio::ip::tcp::socket &dst, boost::asio::ip::tcp::socket &src) {
    copp::coroutine_context_default::ptr_t co_obj_to = copp::coroutine_context_default::create(copy_buffer(dst, src));
    copp::coroutine_context_default::ptr_t co_obj_from = copp::coroutine_context_default::create(copy_buffer(src, dst));
    while (true){
        co_obj_to->start();
        co_obj_from->start();
    }
}

无效的开关PROJECT_DISABLE_MT说明

文档中说多线程支持的开关PROJECT_DISABLE_MT, 但是在构建脚本中没有看到
但是有个锁的开关LIBCOPP_DISABLE_ATOMIC_LOCK, 是不是一回事?

协程栈的大小的问题

你好,
OWenT, 协程栈的大小代码中使用最小的是64KB。这个看了代码发现这主要是跟min_stack size 和max_stack_size有关,而且对对齐了内存管理的page size. 这个大小有点大, 如果是10w个协程的话,需要6250Mb内存. 如果最小的栈大小过大的话, 很可能导致大量的内存浪费.

Windows CMake 编译报错:Unknown CMake command "echowithcolor"

Description of your problem.
在Windows上用CMake(3.27.1) 编译最新版本2.2.0报错:Unknown CMake command "echowithcolor"
构建命令:cmake .. -DPROJECT_ENABLE_UNITTEST=YES -DPROJECT_ENABLE_SAMPLE=YES

Describe the solution you'd like
A clear and concise description of what you want to happen.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.