• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2001-2003
2 // William E. Kempf
3 // Copyright (C) 2007 Anthony Williams
4 //
5 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
6 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 
8 #include <iostream>
9 #include <mutex>
10 
11 #include <boost/test/unit_test.hpp>
12 
13 #include <boost/fiber/all.hpp>
14 
15 boost::fibers::mutex check_mutex;
16 boost::fibers::mutex fss_mutex;
17 int fss_instances = 0;
18 int fss_total = 0;
19 
20 struct fss_value_t {
fss_value_tfss_value_t21     fss_value_t() {
22         std::unique_lock<boost::fibers::mutex> lock(fss_mutex);
23         ++fss_instances;
24         ++fss_total;
25         value = 0;
26     }
~fss_value_tfss_value_t27     ~fss_value_t() {
28         std::unique_lock<boost::fibers::mutex> lock(fss_mutex);
29         --fss_instances;
30     }
31     int value;
32 };
33 
34 boost::fibers::fiber_specific_ptr<fss_value_t> fss_value;
35 
fss_fiber()36 void fss_fiber() {
37     fss_value.reset(new fss_value_t());
38     for (int i=0; i<1000; ++i) {
39         int& n = fss_value->value;
40         if (n != i) {
41             std::unique_lock<boost::fibers::mutex> lock(check_mutex);
42             BOOST_CHECK_EQUAL(n, i);
43         }
44         ++n;
45     }
46 }
47 
fss()48 void fss() {
49     fss_instances = 0;
50     fss_total = 0;
51 
52     boost::fibers::fiber f1( boost::fibers::launch::dispatch, fss_fiber);
53     boost::fibers::fiber f2( boost::fibers::launch::dispatch, fss_fiber);
54     boost::fibers::fiber f3( boost::fibers::launch::dispatch, fss_fiber);
55     boost::fibers::fiber f4( boost::fibers::launch::dispatch, fss_fiber);
56     boost::fibers::fiber f5( boost::fibers::launch::dispatch, fss_fiber);
57     f1.join();
58     f2.join();
59     f3.join();
60     f4.join();
61     f5.join();
62 
63     std::cout
64         << "fss_instances = " << fss_instances
65         << "; fss_total = " << fss_total
66         << "\n";
67     std::cout.flush();
68 
69     BOOST_CHECK_EQUAL(fss_instances, 0);
70     BOOST_CHECK_EQUAL(fss_total, 5);
71 }
72 
test_fss()73 void test_fss() {
74     boost::fibers::fiber( boost::fibers::launch::dispatch, fss).join();
75 }
76 
77 bool fss_cleanup_called=false;
78 
79 struct Dummy {
80 };
81 
fss_custom_cleanup(Dummy * d)82 void fss_custom_cleanup(Dummy* d) {
83     delete d;
84     fss_cleanup_called=true;
85 }
86 
87 boost::fibers::fiber_specific_ptr<Dummy> fss_with_cleanup(fss_custom_cleanup);
88 
fss_fiber_with_custom_cleanup()89 void fss_fiber_with_custom_cleanup() {
90     fss_with_cleanup.reset(new Dummy);
91 }
92 
fss_with_custom_cleanup()93 void fss_with_custom_cleanup() {
94     boost::fibers::fiber f( boost::fibers::launch::dispatch, fss_fiber_with_custom_cleanup);
95     try {
96         f.join();
97     } catch(...) {
98         f.join();
99         throw;
100     }
101 
102     BOOST_CHECK(fss_cleanup_called);
103 }
104 
test_fss_with_custom_cleanup()105 void test_fss_with_custom_cleanup() {
106     boost::fibers::fiber( boost::fibers::launch::dispatch, fss_with_custom_cleanup).join();
107 }
108 
109 Dummy* fss_object=new Dummy;
110 
fss_fiber_with_custom_cleanup_and_release()111 void fss_fiber_with_custom_cleanup_and_release() {
112     fss_with_cleanup.reset(fss_object);
113     fss_with_cleanup.release();
114 }
115 
do_test_fss_does_no_cleanup_after_release()116 void do_test_fss_does_no_cleanup_after_release() {
117     fss_cleanup_called=false;
118     boost::fibers::fiber f( boost::fibers::launch::dispatch, fss_fiber_with_custom_cleanup_and_release);
119     try {
120         f.join();
121     } catch(...) {
122         f.join();
123         throw;
124     }
125 
126     BOOST_CHECK(!fss_cleanup_called);
127     if(!fss_cleanup_called) {
128         delete fss_object;
129     }
130 }
131 
132 struct dummy_class_tracks_deletions {
133     static unsigned deletions;
134 
~dummy_class_tracks_deletionsdummy_class_tracks_deletions135     ~dummy_class_tracks_deletions() {
136         ++deletions;
137     }
138 };
139 
140 unsigned dummy_class_tracks_deletions::deletions=0;
141 
142 boost::fibers::fiber_specific_ptr<dummy_class_tracks_deletions> fss_with_null_cleanup(NULL);
143 
fss_fiber_with_null_cleanup(dummy_class_tracks_deletions * delete_tracker)144 void fss_fiber_with_null_cleanup(dummy_class_tracks_deletions* delete_tracker) {
145     fss_with_null_cleanup.reset(delete_tracker);
146 }
147 
do_test_fss_does_no_cleanup_with_null_cleanup_function()148 void do_test_fss_does_no_cleanup_with_null_cleanup_function() {
149     dummy_class_tracks_deletions* delete_tracker=new dummy_class_tracks_deletions;
150     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&delete_tracker](){
151         fss_fiber_with_null_cleanup( delete_tracker); });
152     try {
153         f.join();
154     } catch(...) {
155         f.join();
156         throw;
157     }
158 
159     BOOST_CHECK(!dummy_class_tracks_deletions::deletions);
160     if(!dummy_class_tracks_deletions::deletions) {
161         delete delete_tracker;
162     }
163 }
164 
test_fss_does_no_cleanup_after_release()165 void test_fss_does_no_cleanup_after_release() {
166     boost::fibers::fiber( boost::fibers::launch::dispatch, do_test_fss_does_no_cleanup_after_release).join();
167 }
168 
test_fss_does_no_cleanup_with_null_cleanup_function()169 void test_fss_does_no_cleanup_with_null_cleanup_function() {
170     boost::fibers::fiber( boost::fibers::launch::dispatch, do_test_fss_does_no_cleanup_with_null_cleanup_function).join();
171 }
172 
173 
fiber_with_local_fss_ptr()174 void fiber_with_local_fss_ptr() {
175     {
176         boost::fibers::fiber_specific_ptr<Dummy> local_fss(fss_custom_cleanup);
177 
178         local_fss.reset(new Dummy);
179     }
180     BOOST_CHECK(fss_cleanup_called);
181     fss_cleanup_called=false;
182 }
183 
fss_does_not_call_cleanup_after_ptr_destroyed()184 void fss_does_not_call_cleanup_after_ptr_destroyed() {
185     boost::fibers::fiber( boost::fibers::launch::dispatch, fiber_with_local_fss_ptr).join();
186     BOOST_CHECK(!fss_cleanup_called);
187 }
188 
test_fss_does_not_call_cleanup_after_ptr_destroyed()189 void test_fss_does_not_call_cleanup_after_ptr_destroyed() {
190     boost::fibers::fiber( boost::fibers::launch::dispatch, fss_does_not_call_cleanup_after_ptr_destroyed).join();
191 }
192 
193 
fss_cleanup_not_called_for_null_pointer()194 void fss_cleanup_not_called_for_null_pointer() {
195     boost::fibers::fiber_specific_ptr<Dummy> local_fss(fss_custom_cleanup);
196     local_fss.reset(new Dummy);
197     fss_cleanup_called=false;
198     local_fss.reset(0);
199     BOOST_CHECK(fss_cleanup_called);
200     fss_cleanup_called=false;
201     local_fss.reset(new Dummy);
202     BOOST_CHECK(!fss_cleanup_called);
203 }
204 
test_fss_cleanup_not_called_for_null_pointer()205 void test_fss_cleanup_not_called_for_null_pointer() {
206     boost::fibers::fiber( boost::fibers::launch::dispatch, fss_cleanup_not_called_for_null_pointer).join();
207 }
208 
209 
fss_at_the_same_adress()210 void fss_at_the_same_adress() {
211   for(int i=0; i<2; i++) {
212     boost::fibers::fiber_specific_ptr<Dummy> local_fss(fss_custom_cleanup);
213     local_fss.reset(new Dummy);
214     fss_cleanup_called=false;
215     BOOST_CHECK(fss_cleanup_called);
216     fss_cleanup_called=false;
217     BOOST_CHECK(!fss_cleanup_called);
218   }
219 }
220 
test_fss_at_the_same_adress()221 void test_fss_at_the_same_adress() {
222     boost::fibers::fiber( boost::fibers::launch::dispatch, fss_at_the_same_adress).join();
223 }
224 
init_unit_test_suite(int,char * [])225 boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) {
226     boost::unit_test::test_suite* test =
227         BOOST_TEST_SUITE("Boost.Fiber: fss test suite");
228 
229     test->add(BOOST_TEST_CASE(test_fss));
230     test->add(BOOST_TEST_CASE(test_fss_with_custom_cleanup));
231     test->add(BOOST_TEST_CASE(test_fss_does_no_cleanup_after_release));
232     test->add(BOOST_TEST_CASE(test_fss_does_no_cleanup_with_null_cleanup_function));
233     test->add(BOOST_TEST_CASE(test_fss_does_not_call_cleanup_after_ptr_destroyed));
234     test->add(BOOST_TEST_CASE(test_fss_cleanup_not_called_for_null_pointer));
235 
236     return test;
237 }
238