libcopp  1.1.0
/home/travis/build/owt5008137/libcopp/README.md
Go to the documentation of this file.
1 libcopp
2 ================
3 
4 Cross-platform coroutine library in C++ .
5 
6 | | [Linux+OSX(Clang+GCC)][linux-link] | [Windows(VC+MinGW)][windows-link] | [Coveralls][coverage-link] |
7 |:---------------:|:----------------------------------:|:---------------------------------:|:-----------------------------------:|
8 Build & Unit Test | ![linux-badge] | ![windows-badge] | ![coverage-badge] |
9 | Compilers | linux-gcc-4.4 <br /> linux-gcc-4.6 <br /> linux-gcc-4.9 <br /> linux-gcc-8 <br /> macos-apple-clang-9.0 <br /> | MSVC 12(Visual Studio 2013) <br /> MSVC 14(Visual Studio 2015) <br /> MSVC 15(Visual Studio 2017) <br /> MinGW64-gcc | |
10 
11 [Gitter][gitter-link]: ![gitter-badge]
12 
13 [linux-badge]: https://travis-ci.org/owt5008137/libcopp.svg?branch=v2 "Travis build status"
14 [linux-link]: https://travis-ci.org/owt5008137/libcopp "Travis build status"
15 [windows-badge]: https://ci.appveyor.com/api/projects/status/7w6dfnpeahfmgaqj/branch/v2?svg=true "AppVeyor build status"
16 [windows-link]: https://ci.appveyor.com/project/owt5008137/libcopp "AppVeyor build status"
17 [coverage-badge]: https://coveralls.io/repos/github/owt5008137/libcopp/badge.svg?branch=v2 "Coveralls coverage"
18 [coverage-link]: https://coveralls.io/github/owt5008137/libcopp?branch=v2 "Coveralls coverage"
19 [gitter-badge]: https://badges.gitter.im/owt5008137/libcopp.svg "Gitter"
20 [gitter-link]: https://gitter.im/owt5008137/libcopp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge "Gitter"
21 
22 LICENSE
23 ----------------
24 
25 License under the MIT license
26 
27 Document
28 ----------------
29 
30 Documents can be found at https://libcopp.atframe.work (Generated by doxygen with *[docs/libcopp.doxyfile](docs/libcopp.doxyfile)*).
31 
32 INSTALL
33 ----------------
34 
35 > libcopp use cmake to generate makefile and switch build tools.
36 
37 ### Prerequisites
38 
39 - **[required]** GCC or Clang or VC support ISO C++ 03 and upper
40 - **[required]** [cmake](www.cmake.org) 3.7.0 and upper
41 - **[optional]** [gtest](https://code.google.com/p/googletest/) 1.6.0 and upper (Better unit test supported)
42 - **[optional]** [Boost.Test](http://www.boost.org/doc/libs/release/libs/test/) (Boost.Test supported)
43 
44 ### Unix
45 
46 - **[required]** ar, as, ld ([binutils](http://www.gnu.org/software/binutils/)) or [llvm](http://llvm.org/)
47 - **[optional]** if using [gtest](https://code.google.com/p/googletest/), pthread is required.
48 
49 ### Windows
50 
51 - **[required]** masm (in vc)
52 - **[optional]** if using [gtest](https://code.google.com/p/googletest/), pthread is required.
53 
54 ### Install with vcpkg
55 
56 **1. clone and setup vcpkg**(See more detail on https://github.com/Microsoft/vcpkg)
57 ~~~~~~~~~~bash
58 git clone https://github.com/Microsoft/vcpkg.git
59 cd vcpkg
60 
61 PS> .\bootstrap-vcpkg.bat
62 Linux:~/$ ./bootstrap-vcpkg.sh
63 ~~~~~~~~~~
64 
65 **2. install libcopp**
66 ~~~~~~~~~~bash
67 PS> .\vcpkg install libcopp
68 Linux:~/$ ./vcpkg install libcopp
69 ~~~~~~~~~~
70 
71 
72 ### Custom Build
73 
74 **1. clone and make a build directory**
75 ~~~~~~~~~~bash
76 git clone --single-branch --depth=1 -b master https://github.com/owt5008137/libcopp.git
77 mkdir libcopp/build && cd libcopp/build
78 ~~~~~~~~~~
79 
80 **2. run cmake command**
81 ~~~~~~~~~~bash
82 # cmake <libcopp dir> [options...]
83 cmake .. -DLIBCOPP_FCONTEXT_USE_TSX=YES -DPROJECT_ENABLE_UNITTEST=YES -DPROJECT_ENABLE_SAMPLE=YES
84 ~~~~~~~~~~
85 
86 **3. make libcopp**
87 ~~~~~~~~~~bash
88 cmake --build . --config RelWithDebInfo # or make [options] when using Makefile
89 ~~~~~~~~~~
90 
91 **4. run test/sample/benchmark** *[optional]*
92 ~~~~~~~~~~bash
93 # Run test => Required: PROJECT_ENABLE_UNITTEST=YES
94 cmake --build . --config RelWithDebInfo --target run_test # or make run_test when using Makefile
95 # Run sample => Required: PROJECT_ENABLE_SAMPLE=YES
96 cmake --build . --config RelWithDebInfo --target run_sample # or make run_sample when using Makefile
97 # Run benchmark => Required: PROJECT_ENABLE_SAMPLE=YES
98 cmake --build . --config RelWithDebInfo --target benchmark # or make benchmark when using Makefile
99 ~~~~~~~~~~
100 
101 **5. install** *[optional]*
102 ~~~~~~~~~~bash
103 cmake --build . --config RelWithDebInfo --target install # or make install when using Makefile
104 ~~~~~~~~~~
105 
106 > Or you can just copy include directory and libcopp.a in lib or lib64 into your project to use it.
107 
108 #### CMake Options
109 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:
110 
111 | Option | Description |
112 |---------|-------------|
113 BUILD\_SHARED\_LIBS=YES\|NO | [default=NO] Build dynamic library.
114 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)
115 LIBCOPP\_ENABLE\_VALGRIND=YES\|NO | [default=YES] Enable valgrind supported context.
116 PROJECT\_ENABLE\_UNITTEST=YES\|NO | [default=NO] Build unit test.
117 PROJECT\_ENABLE\_SAMPLE=YES\|NO | [default=NO] Build samples.
118 PROJECT\_DISABLE\_MT=YES\|NO | [default=NO] Disable multi-thread support.
119 LIBCOTASK\_ENABLE=YES\|NO | [default=YES] Enable build libcotask.
120 LIBCOPP\_FCONTEXT\_USE\_TSX=YES\|NO | [default=NO] Enable [Intel Transactional Synchronisation Extensions (TSX)](https://software.intel.com/en-us/node/695149).
121 GTEST\_ROOT=[path] | set gtest library install prefix path
122 BOOST\_ROOT=[path] | set Boost.Test library install prefix path
123 
124 USAGE
125 ----------------
126 
127 ### Using with cmake
128 
129 1. Add <WHERE TO INSTALL libcopp>/lib(64)/cmake to any of **CMAKE_PREFIX_PATH** 、 **CMAKE_FRAMEWORK_PATH** 、 **CMAKE_SYSTEM_PREFIX_PATH** 、 **CMAKE_SYSTEM_FRAMEWORK_PATH**
130 2. Just add [find_package(Libcopp)](https://cmake.org/cmake/help/latest/command/find_package.html) to use libcopp module.
131 ~~~~~~~~~~cmake
132 find_package(Libcopp CONFIG REQUIRED)
133 target_include_directories(main PRIVATE ${Libcopp_INCLUDE_DIRS})
134 target_link_libraries(main PRIVATE ${Libcotask_LIBRARIES} ${Libcopp_LIBRARIES})
135 ~~~~~~~~~~
136 
137 See more detail on https://github.com/Microsoft/vcpkg/tree/master/ports/libcopp .
138 
139 ### Directly use headers and libraries
140 
141 Just include headers and linking library file of your platform to use libcopp.
142 
143 ~~~~~~~~~~bash
144 LIBCOPP_PREFIX=<WHERE TO INSTALL libcopp>
145 
146 # Example command for build sample with gcc 4.9 or upper on Linux
147 for source in sample_readme_*.cpp; do
148  g++ -std=c++14 -O2 -g -ggdb -Wall -Werror -fPIC -rdynamic -fdiagnostics-color=auto -Wno-unused-local-typedefs \
149  -I$LIBCOPP_PREFIX/include -L$LIBCOPP_PREFIX/lib64 -lcopp -lcotask $source -o $source.exe;
150 done
151 
152 # Example command for build sample with clang 3.9 or upper and libc++ on Linux
153 for source in sample_readme_*.cpp; do
154  clang++ -std=c++17 -stdlib=libc++ -O2 -g -ggdb -Wall -Werror -fPIC -rdynamic \
155  -I$LIBCOPP_PREFIX/include -L$LIBCOPP_PREFIX/lib64 -lcopp -lcotask -lc++ -lc++abi \
156  $source -o $source.exe;
157 done
158 
159 # AppleClang on macOS just like those scripts upper.
160 # If you are using MinGW on Windows, it's better to add -static-libstdc++ -static-libgcc to
161 # use static linking and other scripts are just like those on Linux.
162 
163 ~~~~~~~~~~
164 
165 ~~~~~~~~~~powershell
166 # Example command for build sample with MSVC 1914 or upper on Windows & powershell(Debug Mode /MDd)
167 foreach ($source in Get-ChildItem -File -Name .\sample_readme_*.cpp) {
168  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
169 }
170 ~~~~~~~~~~
171 
172 ### Get Start & Example
173 
174 #### coroutine_context example
175 This is a simple example of using basic coroutine context below:
176 
177 ~~~~~~~~~~cpp
178 // see https://github.com/owt5008137/libcopp/blob/v2/sample/sample_readme_1.cpp
179 #include <cstdio>
180 #include <cstring>
181 #include <inttypes.h>
182 #include <iostream>
183 #include <stdint.h>
184 
185 // include context header file
186 #include <libcopp/coroutine/coroutine_context_container.h>
187 
188 // define a coroutine runner
189 int my_runner(void *) {
190  copp::coroutine_context *addr = copp::this_coroutine::get_coroutine();
191 
192  std::cout << "cortoutine " << addr << " is running." << std::endl;
193 
194  addr->yield();
195 
196  std::cout << "cortoutine " << addr << " is resumed." << std::endl;
197 
198  return 1;
199 }
200 
201 int main() {
202  typedef copp::coroutine_context_default coroutine_t;
203 
204  // create a coroutine
205  copp::coroutine_context_default::ptr_t co_obj = coroutine_t::create(my_runner);
206  std::cout << "cortoutine " << co_obj << " is created." << std::endl;
207 
208  // start a coroutine
209  co_obj->start();
210 
211  // yield from my_runner
212  std::cout << "cortoutine " << co_obj << " is yield." << std::endl;
213  co_obj->resume();
214 
215  std::cout << "cortoutine " << co_obj << " exit and return " << co_obj->get_ret_code() << "." << std::endl;
216  return 0;
217 }
218 ~~~~~~~~~~
219 
220 Also, you can use copp::coroutine_context_container<ALLOCATOR> instead of copp::coroutine_context_default to use a different stack allocator.
221 
222 #### coroutine task example
223 This is a simple example of using coroutine task with lambda expression:
224 
225 ~~~~~~~~~~cpp
226 // see https://github.com/owt5008137/libcopp/blob/v2/sample/sample_readme_2.cpp
227 #include <iostream>
228 
229 // include task header file
230 #include <libcotask/task.h>
231 
232 typedef cotask::task<> my_task_t;
233 
234 int main(int argc, char *argv[]) {
235 #if defined(UTIL_CONFIG_COMPILER_CXX_LAMBDAS) && UTIL_CONFIG_COMPILER_CXX_LAMBDAS
236  // create a task using factory function [with lambda expression]
237  my_task_t::ptr_t task = my_task_t::create([]() {
238  std::cout << "task " << cotask::this_task::get<my_task_t>()->get_id() << " started" << std::endl;
239  cotask::this_task::get_task()->yield();
240  std::cout << "task " << cotask::this_task::get<my_task_t>()->get_id() << " resumed" << std::endl;
241  return 0;
242  });
243 
244  std::cout << "task " << task->get_id() << " created" << std::endl;
245  // start a task
246  task->start();
247 
248  std::cout << "task " << task->get_id() << " yield" << std::endl;
249  task->resume();
250  std::cout << "task " << task->get_id() << " stoped, ready to be destroyed." << std::endl;
251 #else
252  std::cerr << "lambda not supported, this sample is not available." << std::endl;
253 #endif
254  return 0;
255 }
256 ~~~~~~~~~~
257 Also, you can your stack allocator or id allocator by setting different parameters in template class **cotask::task<TCO_MACRO, TTASK_MACRO>**
258 
259 #### using coroutine task manager
260 This is a simple example of using task manager:
261 
262 ~~~~~~~~~~cpp
263 // see https://github.com/owt5008137/libcopp/blob/v2/sample/sample_readme_3.cpp
264 #include <cstdio>
265 #include <cstring>
266 #include <ctime>
267 #include <inttypes.h>
268 #include <iostream>
269 #include <stdint.h>
270 
271 // include context header file
272 #include <libcotask/task.h>
273 #include <libcotask/task_manager.h>
274 
275 // create a task manager
276 typedef cotask::task<> my_task_t;
277 typedef my_task_t::ptr_t task_ptr_type;
278 typedef cotask::task_manager<my_task_t> mgr_t;
279 mgr_t::ptr_t task_mgr = mgr_t::create();
280 
281 // If you task manager to manage timeout, it's important to call tick interval
282 
283 void tick() {
284  // the first parameter is second, and the second is nanosecond
285  task_mgr->tick(time(NULL), 0);
286 }
287 
288 int main() {
289 #if defined(UTIL_CONFIG_COMPILER_CXX_LAMBDAS) && UTIL_CONFIG_COMPILER_CXX_LAMBDAS
290  // create two coroutine task
291  task_ptr_type co_task = my_task_t::create([]() {
292  std::cout << "task " << cotask::this_task::get<my_task_t>()->get_id() << " started" << std::endl;
293  cotask::this_task::get_task()->yield();
294  std::cout << "task " << cotask::this_task::get<my_task_t>()->get_id() << " resumed" << std::endl;
295  return 0;
296  });
297  task_ptr_type co_another_task = my_task_t::create([]() {
298  std::cout << "task " << cotask::this_task::get<my_task_t>()->get_id() << " started" << std::endl;
299  cotask::this_task::get_task()->yield();
300  std::cout << "task " << cotask::this_task::get<my_task_t>()->get_id() << " resumed" << std::endl;
301  return 0;
302  });
303 
304 
305  int res = task_mgr->add_task(co_task, 5, 0); // add task and setup 5s for timeout
306  if (res < 0) {
307  std::cerr << "some error: " << res << std::endl;
308  return res;
309  }
310 
311  res = task_mgr->add_task(co_another_task); // add task without timeout
312  if (res < 0) {
313  std::cerr << "some error: " << res << std::endl;
314  return res;
315  }
316 
317  res = task_mgr->start(co_task->get_id());
318  if (res < 0) {
319  std::cerr << "start task " << co_task->get_id() << " failed, error code: " << res << std::endl;
320  }
321 
322  res = task_mgr->start(co_another_task->get_id());
323  if (res < 0) {
324  std::cerr << "start task " << co_another_task->get_id() << " failed, error code: " << res << std::endl;
325  }
326 
327  res = task_mgr->resume(co_task->get_id());
328  if (res < 0) {
329  std::cerr << "resume task " << co_task->get_id() << " failed, error code: " << res << std::endl;
330  }
331 
332  res = task_mgr->kill(co_another_task->get_id());
333  if (res < 0) {
334  std::cerr << "kill task " << co_another_task->get_id() << " failed, error code: " << res << std::endl;
335  } else {
336  std::cout << "kill task " << co_another_task->get_id() << " finished." << std::endl;
337  }
338 
339 #else
340  std::cerr << "lambda not supported, this sample is not available." << std::endl;
341 #endif
342  return 0;
343 }
344 ~~~~~~~~~~
345 
346 #### using stack pool
347 This is a simple example of using stack pool for cotask:
348 
349 ~~~~~~~~~~cpp
350 // see https://github.com/owt5008137/libcopp/blob/v2/sample/sample_readme_4.cpp
351 #include <cstdio>
352 #include <cstring>
353 #include <ctime>
354 #include <inttypes.h>
355 #include <iostream>
356 #include <stdint.h>
357 
358 // include context header file
359 #include <libcopp/stack/stack_pool.h>
360 #include <libcotask/task.h>
361 
362 // define the stack pool type
363 typedef copp::stack_pool<copp::allocator::default_statck_allocator> stack_pool_t;
364 
365 // define how to create coroutine context
366 struct sample_macro_coroutine {
367  typedef copp::allocator::stack_allocator_pool<stack_pool_t> stack_allocator_t;
368  typedef copp::coroutine_context_container<stack_allocator_t> coroutine_t;
369 };
370 
371 // create a stack pool
372 static stack_pool_t::ptr_t global_stack_pool = stack_pool_t::create();
373 
374 typedef cotask::task<sample_macro_coroutine> sample_task_t;
375 
376 int main() {
377 #if defined(UTIL_CONFIG_COMPILER_CXX_LAMBDAS) && UTIL_CONFIG_COMPILER_CXX_LAMBDAS
378 
379  global_stack_pool->set_min_stack_number(4);
380  std::cout << "stack pool=> used stack number: " << global_stack_pool->get_limit().used_stack_number
381  << ", used stack size: " << global_stack_pool->get_limit().used_stack_size
382  << ", free stack number: " << global_stack_pool->get_limit().free_stack_number
383  << ", free stack size: " << global_stack_pool->get_limit().free_stack_size << std::endl;
384  // create two coroutine task
385  {
386  copp::allocator::stack_allocator_pool<stack_pool_t> alloc(global_stack_pool);
387  sample_task_t::ptr_t co_task = sample_task_t::create(
388  []() {
389  std::cout << "task " << cotask::this_task::get<sample_task_t>()->get_id() << " started" << std::endl;
390  cotask::this_task::get_task()->yield();
391  std::cout << "task " << cotask::this_task::get<sample_task_t>()->get_id() << " resumed" << std::endl;
392  return 0;
393  },
394  alloc);
395 
396  if (!co_task) {
397  std::cerr << "create coroutine task with stack pool failed" << std::endl;
398  return 0;
399  }
400 
401  std::cout << "stack pool=> used stack number: " << global_stack_pool->get_limit().used_stack_number
402  << ", used stack size: " << global_stack_pool->get_limit().used_stack_size
403  << ", free stack number: " << global_stack_pool->get_limit().free_stack_number
404  << ", free stack size: " << global_stack_pool->get_limit().free_stack_size << std::endl;
405 
406 
407  // ..., then do anything you want to do with these tasks
408  }
409 
410  std::cout << "stack pool=> used stack number: " << global_stack_pool->get_limit().used_stack_number
411  << ", used stack size: " << global_stack_pool->get_limit().used_stack_size
412  << ", free stack number: " << global_stack_pool->get_limit().free_stack_number
413  << ", free stack size: " << global_stack_pool->get_limit().free_stack_size << std::endl;
414 
415  {
416  copp::allocator::stack_allocator_pool<stack_pool_t> alloc(global_stack_pool);
417  sample_task_t::ptr_t co_another_task = sample_task_t::create(
418  []() {
419  std::cout << "task " << cotask::this_task::get<sample_task_t>()->get_id() << " started" << std::endl;
420  cotask::this_task::get_task()->yield();
421  std::cout << "task " << cotask::this_task::get<sample_task_t>()->get_id() << " resumed" << std::endl;
422  return 0;
423  },
424  alloc);
425 
426  if (!co_another_task) {
427  std::cerr << "create coroutine task with stack pool failed" << std::endl;
428  return 0;
429  }
430 
431  // ..., then do anything you want to do with these tasks
432  }
433 
434  std::cout << "stack pool=> used stack number: " << global_stack_pool->get_limit().used_stack_number
435  << ", used stack size: " << global_stack_pool->get_limit().used_stack_size
436  << ", free stack number: " << global_stack_pool->get_limit().free_stack_number
437  << ", free stack size: " << global_stack_pool->get_limit().free_stack_size << std::endl;
438 #else
439  std::cerr << "lambda not supported, this sample is not available." << std::endl;
440 #endif
441  return 0;
442 }
443 ~~~~~~~~~~
444 
445 #### using then or await
446 This is a simple example of using ```then``` and ```await``` for cotask:
447 
448 ~~~~~~~~~~cpp
449 #include <assert.h>
450 #include <cstdio>
451 #include <cstdlib>
452 #include <cstring>
453 #include <ctime>
454 #include <inttypes.h>
455 #include <stdint.h>
456 #include <vector>
457 
458 // include manager header file
459 #include <libcotask/task.h>
460 
461 #if defined(LIBCOTASK_MACRO_ENABLED) && defined(UTIL_CONFIG_COMPILER_CXX_LAMBDAS) && UTIL_CONFIG_COMPILER_CXX_LAMBDAS
462 
463 typedef cotask::task<> my_task_t;
464 
465 int main(int argc, char *argv[]) {
466  int test_code = 128;
467 
468  // create a task using lambda expression
469  my_task_t::ptr_t first_task = my_task_t::create([&]() {
470  puts("|first task running and will be yield ...");
471  cotask::this_task::get_task()->yield();
472  puts("|first task resumed ...");
473  printf("test code already reset => %d\n", ++test_code);
474  });
475 
476  // add many then task using lambda expression
477  first_task
478  ->then([=]() {
479  puts("|second task running...");
480  printf("test code should be inited 128 => %d\n", test_code);
481  })
482  ->then([&]() {
483  puts("|haha ... this is the third task.");
484  printf("test code is the same => %d\n", ++test_code);
485  return "return value will be ignored";
486  })
487  ->then(
488  [&](void *priv_data) {
489  puts("|it's boring");
490  printf("test code is %d\n", ++test_code);
491  assert(&test_code == priv_data);
492  return 0;
493  },
494  &test_code);
495 
496  test_code = 0;
497  // start a task
498  first_task->start();
499  first_task->resume();
500 
501  // these code below will failed.
502  first_task->then([]() {
503  puts("this will run immediately.");
504  return 0;
505  });
506 
507  my_task_t::ptr_t await_task = my_task_t::create([&]() {
508  puts("await for first_task.");
509  return 0;
510  });
511  await_task->await(first_task);
512 
513  printf("|task start twice will failed: %d\n", first_task->start());
514  printf("|test_code end with %d\n", test_code);
515  return 0;
516 }
517 #else
518 int main() {
519  puts("this sample require cotask enabled and compiler support c++11");
520  return 0;
521 }
522 #endif
523 ~~~~~~~~~~
524 
525 NOTICE
526 ----------------
527 
528 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.
529 
530 It's recommanded to use stack pool instead of gcc splited stack.
531 
532 BENCHMARK
533 ----------------
534 
535 Please see CI output for latest benchmark report. the [benchmark on Linux and macOS can be see here](https://travis-ci.org/owt5008137/libcopp) and the [benchmark on Windows can be see here](https://ci.appveyor.com/project/owt5008137/libcopp).
536 
537 DEVELOPER
538 ----------------
539 
540 Documents can be found at https://libcopp.atframe.work (Generated by doxygen with *[docs/libcopp.doxyfile](docs/libcopp.doxyfile)*).
541 
542 HISTORY
543 ----------------
544 
545 ### 2018-12-07
546 1. [OPTIMIZE] add adaptor for [vcpkg](https://github.com/Microsoft/vcpkg)
547 2. [OPTIMIZE] using [GNUInstallDirs](https://cmake.org/cmake/help/v3.13/module/GNUInstallDirs.html) for all directories
548 3. [BOOST] merge boost.context 1.67.0
549 4. [OPTIMIZE] add libcopp-config.cmake and libcopp-config-version.cmake for cmake module
550 5. [OPTIMIZE] add ***then*** and ***await*** API for easier usage
551 6. [OPTIMIZE] add ***/Zc:__cplusplus*** for MSVC to make __cplusplus to the standard value.
552 7. [OPTIMIZE] fix a guess to x86_64 environment
553 8. [OPTIMIZE] add more API for statistics
554 9. [FIX] fix the problem that calling compare_exchange_weak failed will lead the cotask to exit
555 10. [OPTIMIZE] merge the latest unit test framework, now we will support more readable output when test failed.
556 11. [CI] We use xenial to build in linux now.
557 
558 ### 2018-01-01
559 
560 1. [BOOST] merge boost.context 1.66.0
561 2. [OPTIMIZE] add support for [Intel Transactional Synchronisation Extensions (TSX)](https://software.intel.com/en-us/node/695149)
562 3. [OPTIMIZE] fix a warning reported by clang-analyzer.
563 4. [CI] update README.md and automatic documents.(published at https://libcopp.atframe.work)
564 5. [FIX] make sure all the allocated stacks are always greater than the configure value after reloaded when using stack pool.
565 6. [FIX] allow segmented stacks when using clang and llvm.
566 7. [OPTIMIZE] using the new script to run clang-analyzer.
567 8. [OPTIMIZE] optimize the doxygen output and fix some markdown synax not supported by doxygen.
568 
569 ### 2017-10-01
570 1. [OPTIMIZE] optimize cmake files for all target
571 2. [OPTIMIZE] update samples and readme(fix sample for stack pool in README.md)
572 3. [CI] add gcc 7
573 4. [OPTIMIZE] using -std=c++17 for gcc/clang and /std:c++17 for MSVC 15(2015) and upper
574 
575 ### 2017-06-11
576 1. [OPTIMIZE] V2 framework and APIs completed, all reports in clang-analysis and cppcheck are fixed.
577 2. [CI] benchmark and samples enabled in v2 branch
578 3. [CI] add sample code in README.md into CI
579 
580 ### 2017-05-10
581 1. [BOOST] merge boost.context 1.64.0
582 2. [OPTIMIZE] add stack pool manager and unit test
583 3. [OPTIMIZE] reduce memory fragment when allocate coroutine task and task action
584 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)
585 
586 
587 ### 2016-06-16
588 1. [BOOST] merge boost.context 1.61.0 and use the new jump progress(see https://owent.net/2016/1270.html for detail)
589 2. [BOOST] enable valgrind support if valgrind/valgrind.h exists
590 3. [CXX] use cmake to detect the function of compiler
591 4. [OPTIMIZE] using pthread key when c++11 TLS not available
592 5. [OPTIMIZE] remove coroutine_context_safe_base.coroutine_context_base is also thread safe now
593 6. [OPTIMIZE] remove all global variables of cotask
594 7. [OPTIMIZE] remove std/thread.h, add noexpect if available
595 8. [CI] CI use build matrix to test more compiler
596 9. [BUILD] use RelWithDebInfo for default
597 
598 ### 2016-02-27
599 1. v0.2.0, this version is used in our server for about one year.
600 
601 ### 2015-12-29
602 1. add support for valgrind
603 2. add ci configure
604 3. merge boost.context 1.60.0
605 4. add -fPIC, fix spin lock
606 5. some environment do not support TLS, make these environment can compile success
607 
608 ### 2014-07-25
609 v0.1.0
610 
611 CONSTRIBUTORS
612 ----------------
613 + [owent](https://github.com/owt5008137)
614 
615 THANKS TO
616 ----------------
617 
618 + [mutouyun](https://github.com/mutouyun)