test_fcontext.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. // Copyright Oliver Kowalke 2009.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <cmath>
  8. #include <cstdint>
  9. #include <iostream>
  10. #include <sstream>
  11. #include <stdexcept>
  12. #include <string>
  13. #include <utility>
  14. #include <boost/array.hpp>
  15. #include <boost/assert.hpp>
  16. #include <boost/test/unit_test.hpp>
  17. #include <boost/utility.hpp>
  18. #include <boost/context/detail/config.hpp>
  19. #include <boost/context/detail/fcontext.hpp>
  20. template< std::size_t Max, std::size_t Default, std::size_t Min >
  21. class simple_stack_allocator
  22. {
  23. public:
  24. static std::size_t maximum_stacksize()
  25. { return Max; }
  26. static std::size_t default_stacksize()
  27. { return Default; }
  28. static std::size_t minimum_stacksize()
  29. { return Min; }
  30. void * allocate( std::size_t size) const
  31. {
  32. BOOST_ASSERT( minimum_stacksize() <= size);
  33. BOOST_ASSERT( maximum_stacksize() >= size);
  34. void * limit = malloc( size);
  35. if ( ! limit) throw std::bad_alloc();
  36. return static_cast< char * >( limit) + size;
  37. }
  38. void deallocate( void * vp, std::size_t size) const
  39. {
  40. BOOST_ASSERT( vp);
  41. BOOST_ASSERT( minimum_stacksize() <= size);
  42. BOOST_ASSERT( maximum_stacksize() >= size);
  43. void * limit = static_cast< char * >( vp) - size;
  44. free( limit);
  45. }
  46. };
  47. typedef simple_stack_allocator<
  48. 8 * 1024 * 1024, 64 * 1024, 8 * 1024
  49. > stack_allocator;
  50. namespace ctx = boost::context::detail;
  51. typedef simple_stack_allocator<
  52. 8 * 1024 * 1024, // 8MB
  53. 64 * 1024, // 64kB
  54. 8 * 1024 // 8kB
  55. > stack_allocator;
  56. int value1 = 0;
  57. std::string value2;
  58. double value3 = 0.;
  59. void * value4 = 0;
  60. void f1( ctx::transfer_t t) {
  61. ++value1;
  62. ctx::jump_fcontext( t.fctx, t.data);
  63. }
  64. void f3( ctx::transfer_t t_) {
  65. ++value1;
  66. ctx::transfer_t t = ctx::jump_fcontext( t_.fctx, 0);
  67. ++value1;
  68. ctx::jump_fcontext( t.fctx, t.data);
  69. }
  70. void f4( ctx::transfer_t t) {
  71. int i = 7;
  72. ctx::jump_fcontext( t.fctx, & i);
  73. }
  74. void f5( ctx::transfer_t t) {
  75. ctx::jump_fcontext( t.fctx, t.data);
  76. }
  77. void f6( ctx::transfer_t t_) {
  78. std::pair< int, int > data = * ( std::pair< int, int > * ) t_.data;
  79. int res = data.first + data.second;
  80. ctx::transfer_t t = ctx::jump_fcontext( t_.fctx, & res);
  81. data = * ( std::pair< int, int > *) t.data;
  82. res = data.first + data.second;
  83. ctx::jump_fcontext( t.fctx, & res);
  84. }
  85. void f7( ctx::transfer_t t) {
  86. try {
  87. throw std::runtime_error( * ( std::string *) t.data);
  88. } catch ( std::runtime_error const& e) {
  89. value2 = e.what();
  90. }
  91. ctx::jump_fcontext( t.fctx, t.data);
  92. }
  93. void f8( ctx::transfer_t t) {
  94. double d = * ( double *) t.data;
  95. d += 3.45;
  96. value3 = d;
  97. ctx::jump_fcontext( t.fctx, 0);
  98. }
  99. void f10( ctx::transfer_t t) {
  100. value1 = 3;
  101. ctx::jump_fcontext( t.fctx, 0);
  102. }
  103. void f9( ctx::transfer_t t) {
  104. std::cout << "f1: entered" << std::endl;
  105. stack_allocator alloc;
  106. void * sp = alloc.allocate( stack_allocator::default_stacksize());
  107. ctx::fcontext_t ctx = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f10);
  108. ctx::jump_fcontext( ctx, 0);
  109. ctx::jump_fcontext( t.fctx, 0);
  110. }
  111. ctx::transfer_t f11( ctx::transfer_t t_) {
  112. value4 = t_.data;
  113. ctx::transfer_t t = { t_.fctx, t_.data };
  114. return t;
  115. }
  116. void f12( ctx::transfer_t t_) {
  117. ctx::transfer_t t = ctx::jump_fcontext( t_.fctx, t_.data);
  118. value1 = * ( int *) t.data;
  119. ctx::jump_fcontext( t.fctx, t.data);
  120. }
  121. void f13( ctx::transfer_t t) {
  122. {
  123. double n1 = 0;
  124. double n2 = 0;
  125. sscanf("3.14 7.13", "%lf %lf", & n1, & n2);
  126. BOOST_CHECK( n1 == 3.14);
  127. BOOST_CHECK( n2 == 7.13);
  128. }
  129. {
  130. int n1=0;
  131. int n2=0;
  132. sscanf("1 23", "%d %d", & n1, & n2);
  133. BOOST_CHECK( n1 == 1);
  134. BOOST_CHECK( n2 == 23);
  135. }
  136. {
  137. int n1=0;
  138. int n2=0;
  139. sscanf("1 jjj 23", "%d %*[j] %d", & n1, & n2);
  140. BOOST_CHECK( n1 == 1);
  141. BOOST_CHECK( n2 == 23);
  142. }
  143. ctx::jump_fcontext( t.fctx, 0);
  144. }
  145. void f14( ctx::transfer_t t) {
  146. {
  147. const char *fmt = "sqrt(2) = %f";
  148. char buf[19];
  149. snprintf( buf, sizeof( buf), fmt, std::sqrt( 2) );
  150. BOOST_CHECK( 0 < sizeof( buf) );
  151. BOOST_CHECK_EQUAL( std::string("sqrt(2) = 1.41"), std::string( buf, 14) );
  152. }
  153. {
  154. std::uint64_t n = 0xbcdef1234567890;
  155. const char *fmt = "0x%016llX";
  156. char buf[100];
  157. snprintf( buf, sizeof( buf), fmt, n);
  158. BOOST_CHECK_EQUAL( std::string("0x0BCDEF1234567890"), std::string( buf, 18) );
  159. }
  160. ctx::jump_fcontext( t.fctx, 0);
  161. }
  162. void test_setup() {
  163. stack_allocator alloc;
  164. void * sp = alloc.allocate( stack_allocator::default_stacksize() );
  165. ctx::fcontext_t ctx = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f1);
  166. BOOST_CHECK( ctx);
  167. alloc.deallocate( sp, stack_allocator::default_stacksize() );
  168. }
  169. void test_start() {
  170. value1 = 0;
  171. stack_allocator alloc;
  172. void * sp = alloc.allocate( stack_allocator::default_stacksize() );
  173. ctx::fcontext_t ctx = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f1);
  174. BOOST_CHECK( ctx);
  175. BOOST_CHECK_EQUAL( 0, value1);
  176. ctx::jump_fcontext( ctx, 0);
  177. BOOST_CHECK_EQUAL( 1, value1);
  178. alloc.deallocate( sp, stack_allocator::default_stacksize() );
  179. }
  180. void test_jump() {
  181. value1 = 0;
  182. stack_allocator alloc;
  183. void * sp = alloc.allocate( stack_allocator::default_stacksize() );
  184. ctx::fcontext_t ctx = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f3);
  185. BOOST_CHECK( ctx);
  186. BOOST_CHECK_EQUAL( 0, value1);
  187. ctx::transfer_t t = ctx::jump_fcontext( ctx, 0);
  188. BOOST_CHECK_EQUAL( 1, value1);
  189. ctx::jump_fcontext( t.fctx, 0);
  190. BOOST_CHECK_EQUAL( 2, value1);
  191. alloc.deallocate( sp, stack_allocator::default_stacksize() );
  192. }
  193. void test_result() {
  194. stack_allocator alloc;
  195. void * sp = alloc.allocate( stack_allocator::default_stacksize() );
  196. ctx::fcontext_t ctx = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f4);
  197. BOOST_CHECK( ctx);
  198. ctx::transfer_t t = ctx::jump_fcontext( ctx, 0);
  199. int result = * ( int *) t.data;
  200. BOOST_CHECK_EQUAL( 7, result);
  201. alloc.deallocate( sp, stack_allocator::default_stacksize() );
  202. }
  203. void test_arg() {
  204. stack_allocator alloc;
  205. int i = 7;
  206. void * sp = alloc.allocate( stack_allocator::default_stacksize() );
  207. ctx::fcontext_t ctx = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f5);
  208. BOOST_CHECK( ctx);
  209. ctx::transfer_t t = ctx::jump_fcontext( ctx, & i);
  210. int result = * ( int *) t.data;
  211. BOOST_CHECK_EQUAL( i, result);
  212. alloc.deallocate( sp, stack_allocator::default_stacksize() );
  213. }
  214. void test_transfer() {
  215. stack_allocator alloc;
  216. std::pair< int, int > data = std::make_pair( 3, 7);
  217. void * sp = alloc.allocate( stack_allocator::default_stacksize() );
  218. ctx::fcontext_t ctx = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f6);
  219. BOOST_CHECK( ctx);
  220. ctx::transfer_t t = ctx::jump_fcontext( ctx, & data);
  221. int result = * ( int *) t.data;
  222. BOOST_CHECK_EQUAL( 10, result);
  223. data = std::make_pair( 7, 7);
  224. t = ctx::jump_fcontext( t.fctx, & data);
  225. result = * ( int *) t.data;
  226. BOOST_CHECK_EQUAL( 14, result);
  227. alloc.deallocate( sp, stack_allocator::default_stacksize() );
  228. }
  229. void test_exception() {
  230. stack_allocator alloc;
  231. std::string what("hello world");
  232. void * sp = alloc.allocate( stack_allocator::default_stacksize() );
  233. ctx::fcontext_t ctx = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f7);
  234. BOOST_CHECK( ctx);
  235. ctx::jump_fcontext( ctx, & what);
  236. BOOST_CHECK_EQUAL( std::string( what), value2);
  237. alloc.deallocate( sp, stack_allocator::default_stacksize() );
  238. }
  239. void test_fp() {
  240. stack_allocator alloc;
  241. double d = 7.13;
  242. void * sp = alloc.allocate( stack_allocator::default_stacksize() );
  243. ctx::fcontext_t ctx = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f8);
  244. BOOST_CHECK( ctx);
  245. ctx::jump_fcontext( ctx, & d);
  246. BOOST_CHECK_EQUAL( 10.58, value3);
  247. alloc.deallocate( sp, stack_allocator::default_stacksize() );
  248. }
  249. void test_stacked() {
  250. value1 = 0;
  251. stack_allocator alloc;
  252. void * sp = alloc.allocate( stack_allocator::default_stacksize());
  253. ctx::fcontext_t ctx = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f9);
  254. ctx::jump_fcontext( ctx, 0);
  255. BOOST_CHECK_EQUAL( 3, value1);
  256. alloc.deallocate( sp, stack_allocator::default_stacksize() );
  257. }
  258. void test_ontop() {
  259. value1 = 0;
  260. value4 = 0;
  261. stack_allocator alloc;
  262. void * sp = alloc.allocate( stack_allocator::default_stacksize() );
  263. ctx::fcontext_t ctx = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f12);
  264. BOOST_CHECK( ctx);
  265. ctx::transfer_t t = ctx::jump_fcontext( ctx, 0);
  266. BOOST_CHECK_EQUAL( 0, value1);
  267. BOOST_CHECK( 0 == value4);
  268. int i = -3;
  269. t = ctx::ontop_fcontext( t.fctx, & i, f11);
  270. BOOST_CHECK_EQUAL( -3, value1);
  271. BOOST_CHECK_EQUAL( & i, value4);
  272. BOOST_CHECK_EQUAL( -3, * ( int *) t.data);
  273. BOOST_CHECK_EQUAL( & i, ( int *) t.data);
  274. alloc.deallocate( sp, stack_allocator::default_stacksize() );
  275. }
  276. void test_sscanf() {
  277. stack_allocator alloc;
  278. void * sp = alloc.allocate( stack_allocator::default_stacksize() );
  279. ctx::fcontext_t ctx = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f13);
  280. BOOST_CHECK( ctx);
  281. ctx::jump_fcontext( ctx, 0);
  282. alloc.deallocate( sp, stack_allocator::default_stacksize() );
  283. }
  284. void test_snprintf() {
  285. stack_allocator alloc;
  286. void * sp = alloc.allocate( stack_allocator::default_stacksize() );
  287. ctx::fcontext_t ctx = ctx::make_fcontext( sp, stack_allocator::default_stacksize(), f14);
  288. ctx::jump_fcontext( ctx, 0);
  289. alloc.deallocate( sp, stack_allocator::default_stacksize() );
  290. }
  291. boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
  292. boost::unit_test::test_suite * test =
  293. BOOST_TEST_SUITE("Boost.Context: fcontext test suite");
  294. test->add( BOOST_TEST_CASE( & test_setup) );
  295. test->add( BOOST_TEST_CASE( & test_start) );
  296. test->add( BOOST_TEST_CASE( & test_jump) );
  297. test->add( BOOST_TEST_CASE( & test_result) );
  298. test->add( BOOST_TEST_CASE( & test_arg) );
  299. test->add( BOOST_TEST_CASE( & test_transfer) );
  300. test->add( BOOST_TEST_CASE( & test_exception) );
  301. test->add( BOOST_TEST_CASE( & test_fp) );
  302. test->add( BOOST_TEST_CASE( & test_stacked) );
  303. test->add( BOOST_TEST_CASE( & test_ontop) );
  304. test->add( BOOST_TEST_CASE( & test_sscanf) );
  305. test->add( BOOST_TEST_CASE( & test_snprintf) );
  306. return test;
  307. }