Skip to content

Commit

Permalink
add history and new sample
Browse files Browse the repository at this point in the history
  • Loading branch information
owent committed May 11, 2017
1 parent 3c0b596 commit 4bffc31
Show file tree
Hide file tree
Showing 3 changed files with 1,025 additions and 669 deletions.
186 changes: 183 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@ USAGE

> Just include headers and linking library file of your platform to use libcopp
Example
Get Start & Example
-------

### coroutine_context example
There is a simple example of using coroutine context below:

``` {.cpp}
```cpp
#include <cstdio>
#include <cstring>
#include <iostream>
Expand Down Expand Up @@ -157,7 +157,7 @@ And then, you can custom many function such as set your stack allocator, corouti
### coroutine task example
There is a simple example of using coroutine task below:

``` {.cpp}
```cpp
#include <iostream>

// include task header file
Expand Down Expand Up @@ -187,6 +187,178 @@ int main(int argc, char* argv[]) {
```
And then, you can custom many functions by set your macro type of coroutine and task to do some other function.
### using coroutine task manager
There is a simple example of using coroutine context below:
```cpp
#include <cstdio>
#include <cstring>
#include <iostream>
#include <inttypes.h>
#include <stdint.h>
#include <ctime>
// include context header file
#include <libcotask/task.h>
#include <libcotask/task_manager.h>
// create a task manager
typedef cotask::task_manager<cotask::task<>::id_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(NULL), 0);
}
int main() {
// type define
typedef std::shared_ptr<cotask::task<> > task_ptr_type;
// create two coroutine task
task_ptr_type co_task = cotask::task<>::create([](){
std::cout<< "task "<< cotask::this_task::get_task()->get_id()<< " started"<< std::endl;
cotask::this_task::get_task()->yield();
std::cout<< "task "<< cotask::this_task::get_task()->get_id()<< " resumed"<< std::endl;
return 0;
});
task_ptr_type co_another_task = cotask::task<>::create([](){
std::cout<< "task "<< cotask::this_task::get_task()->get_id()<< " started"<< std::endl;
cotask::this_task::get_task()->yield();
std::cout<< "task "<< cotask::this_task::get_task()->get_id()<< " resumed"<< 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); // 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;
}
res = task_mgr->kill(co_another_task->get_id());
if (res < 0) {
std::cerr<< "kill task "<< co_another_task->get_id()<< " failed, error code: "<< res<< std::endl;
} else {
std::cout<< "kill task "<< co_another_task->get_id()<< " finished."<< std::endl;
}
return 0;
}
```


### using stack pool
There is a simple example of using coroutine context below:

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

// include context header file
#include <libcopp/stack/stack_pool.h>
#include <libcotask/task.h>

// define the stack pool type
typedef copp::stack_pool<copp::allocator::default_statck_allocator> stack_pool_t;

// define how to create coroutine context
struct sample_macro_coroutine {
typedef copp::detail::coroutine_context_base coroutine_t;
typedef copp::allocator::stack_allocator_pool<stack_pool_t> stack_allocator_t;

typedef copp::detail::coroutine_context_container<coroutine_t, stack_allocator_t> coroutine_container_t;
};

// create a stack pool
static stack_pool_t::ptr_t global_stack_pool = stack_pool_t::create();

// define how to task allocator
struct sample_task_allocator : public cotask::macro_task::task_allocator_t {
public:
#if defined(COPP_MACRO_ENABLE_VARIADIC_TEMPLATE) && COPP_MACRO_ENABLE_VARIADIC_TEMPLATE
template <typename Ty, typename... TARGS>
static std::shared_ptr<Ty> allocate(Ty *t, TARGS COPP_MACRO_RV_REF... args) {
std::shared_ptr<Ty> ret = cotask::macro_task::task_allocator_t::allocate(t, COPP_MACRO_STD_FORWARD(TARGS, args)...);
ret->get_coroutine_context().get_allocator().attach(global_stack_pool);
return COPP_MACRO_STD_MOVE(ret);
}
#else
template <typename Ty>
static std::shared_ptr<Ty> allocate(Ty *t) {
std::shared_ptr<Ty> ret = cotask::macro_task::task_allocator_t::allocate(t);
ret->get_coroutine_context().get_allocator().attach(global_stack_pool);
return COPP_MACRO_STD_MOVE(ret);
}
#endif
};

// define how to create coroutine task
struct sample_macro_task {
typedef cotask::macro_task::id_t id_t;
typedef cotask::macro_task::id_allocator_t id_allocator_t;

typedef cotask::macro_task::action_allocator_t action_allocator_t;
typedef sample_task_allocator task_allocator_t;
};

typedef cotask::task<sample_macro_coroutine, sample_macro_task> sample_task_t;

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

if (!co_task) {
std::cerr<< "create coroutine task with stack pool failed"<< std::endl;
return 0;
}

if (!co_another_task) {
std::cerr<< "create coroutine task with stack pool failed"<< std::endl;
return 0;
}

// ..., then do anything you want to do with these tasks
return 0;
}
```

NOTICE
======
Expand All @@ -208,6 +380,14 @@ DEVELOPER

HISTORY
========
2017-05-10
------
1. [BOOST] merge boost.context 1.64.0
2. [OPTIMIZE] add stack pool manager and unit test
3. [OPTIMIZE] reduce memory fragment when allocate coroutine task and task action
4. [CI] benchmark and sample will always be run in [Travis CI](https://travis-ci.org/owt5008137/libcopp) and [Appveyor CI](https://ci.appveyor.com/project/owt5008137/libcopp)


2016-06-16
------
1. [BOOST] merge boost.context 1.61.0 and use the new jump progress(see https://owent.net/90QQw for detail)
Expand Down
Loading

0 comments on commit 4bffc31

Please sign in to comment.