21 #define BOOST_TEST_MODULE libjmmcg_tests
22 #include <boost/test/included/unit_test.hpp>
24 #include <boost/mpl/list.hpp>
25 #include <boost/shared_ptr.hpp>
26 #include <boost/smart_ptr/atomic_shared_ptr.hpp>
28 #include "core/ave_deviation_meter.hpp"
29 #include "core/shared_ptr.hpp"
30 #include "core/stats_output.hpp"
31 #include "core/thread_wrapper.hpp"
35 using namespace libjmmcg;
38 template<
template<
class>
class AtCtr>
39 struct obj
final :
public sp_counter_type<
long, api_lock_traits<platform_api, heavyweight_threading>, default_delete, AtCtr> {
47 ~
obj()
noexcept(
true) {}
51 struct boost_atomic_sp_compat
final :
public boost::atomic_shared_ptr<V> {
52 using base_t=
boost::atomic_shared_ptr<V>;
54 using boost::atomic_shared_ptr<V>::atomic_shared_ptr;
62 typedef boost::mpl::list<
63 boost::shared_ptr<obj<api_lock_traits<platform_api, heavyweight_threading>::atomic_counter_type>>,
64 boost_atomic_sp_compat<obj<api_lock_traits<platform_api, heavyweight_threading>::atomic_counter_type>>,
65 std::shared_ptr<obj<api_lock_traits<platform_api, heavyweight_threading>::atomic_counter_type>>,
66 shared_ptr<obj<api_lock_traits<platform_api, sequential_mode>::atomic_counter_type>, api_lock_traits<platform_api, sequential_mode>>,
67 shared_ptr<obj<api_lock_traits<platform_api, sequential_mode>::atomic_counter_type>, api_lock_traits<platform_api, heavyweight_threading>>,
68 shared_ptr<obj<api_lock_traits<platform_api, heavyweight_threading>::atomic_counter_type>, api_lock_traits<platform_api, sequential_mode>>,
69 shared_ptr<obj<api_lock_traits<platform_api, heavyweight_threading>::atomic_counter_type>, api_lock_traits<platform_api, heavyweight_threading>>
77 struct make_shared
final {
80 constexpr static ptr_t
result(
typename ptr_t::element_type p)
noexcept(
true) {
81 return ptr_t(
new typename ptr_t::element_type (p));
85 struct make_shared<
boost::shared_ptr<V>>
final {
86 using ptr_t=
boost::shared_ptr<V>;
88 static ptr_t
result(
typename ptr_t::element_type p)
noexcept(
true) {
89 return boost::make_shared<
typename ptr_t::element_type>(p);
93 struct make_shared<boost_atomic_sp_compat<V>>
final {
94 using ptr_t=boost_atomic_sp_compat<V>;
96 static ptr_t
result(
typename ptr_t::element_type p)
noexcept(
true) {
97 return ptr_t(
boost::make_shared<
typename ptr_t::element_type>(p));
101 struct make_shared<
std::shared_ptr<V>>
final {
102 using ptr_t=
std::shared_ptr<V>;
104 static ptr_t
result(
typename ptr_t::element_type p)
noexcept(
true) {
105 return std::make_shared<
typename ptr_t::element_type>(p);
113 struct copier
final {
116 constexpr static ptr_t
result(ptr_t &p)
noexcept(
true) {
121 struct copier<
boost::shared_ptr<V>>
final {
124 static ptr_t
result(ptr_t &p)
noexcept(
true) {
125 ptr_t ptr=
boost::atomic_load(&p);
130 struct copier<boost_atomic_sp_compat<V>>
final {
131 using ptr_t=boost_atomic_sp_compat<V>;
133 static ptr_t
result(ptr_t &p)
noexcept(
true) {
134 return ptr_t(p.load());
138 struct copier<
std::shared_ptr<V>>
final {
139 using ptr_t=
std::shared_ptr<V>;
141 static ptr_t
result(ptr_t &p)
noexcept(
true) {
142 ptr_t ptr=
std::atomic_load(&p);
147 template<
class Element>
148 struct cctor_thread
final :
public ppd::wrapper<ppd::platform_api, heavyweight_threading> {
157 return make_shared<
typename cont_t::value_type>::result(
typename cont_t::value_type::element_type(++i));
168 while (!
cont.empty()) {
169 const typename cont_t::value_type tmp(copier<
typename cont_t::value_type>::result(cont.back()));
172 assert(cont.empty());
181 struct resettor
final {
183 static void result(Cont &cont)
noexcept(
false) {
188 struct resettor<
boost::shared_ptr<V>>
final {
195 static void result(Cont &cont)
noexcept(
false) {
196 ptr_t ptr=
boost::atomic_load(&cont[cont.size()-1]);
201 struct resettor<boost_atomic_sp_compat<V>>
final {
202 using ptr_t=boost_atomic_sp_compat<V>;
208 static void result(Cont &cont)
noexcept(
false) {
209 boost::shared_ptr<V> ptr=cont[cont.size()-1].exchange(
boost::shared_ptr<V>());
214 struct resettor<
std::shared_ptr<V>>
final {
215 using ptr_t=
std::shared_ptr<V>;
221 static void result(Cont &cont)
noexcept(
false) {
222 ptr_t ptr=
std::atomic_load(&cont[cont.size()-1]);
227 template<
class Element>
228 struct dtor_thread
final :
public ppd::wrapper<ppd::platform_api, heavyweight_threading> {
237 return make_shared<
typename cont_t::value_type>::result(
typename cont_t::value_type::element_type(++i));
248 while (!
cont.empty()) {
249 resettor<
typename cont_t::value_type>::result(cont);
252 assert(cont.empty());
257 BOOST_AUTO_TEST_SUITE(shared_ptr_parallel_tests)
259 BOOST_AUTO_TEST_SUITE(performance_cctor, *stats_to_csv::make_fixture(
"shared_ptr_parallel_cctor.csv"))
287 BOOST_AUTO_TEST_CASE_TEMPLATE(parallel_cctor, ctr_t, ctr_types) {
288 typedef cctor_thread<ctr_t> thread_t;
289 #ifdef JMMCG_PERFORMANCE_TESTS
290 const std::size_t num_items=10000000;
292 const std::size_t num_items=100;
294 const unsigned short loops_for_conv=50;
295 const double perc_conv_estimate=5.0;
297 const std::pair<timed_results_t,
bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
301 typename thread_t::cont_t c;
302 std::generate_n(std::back_inserter(c), num_items,
typename thread_t::make());
306 const auto t1=std::chrono::high_resolution_clock::now();
307 th1.create_running();
308 th2.create_running();
310 api_threading_traits<platform_api, heavyweight_threading>::sleep(100);
311 }
while (th1.is_running() || th2.is_running());
312 const auto t2=std::chrono::high_resolution_clock::now();
313 BOOST_CHECK_EQUAL(th1.cont.size(), 0);
314 BOOST_CHECK(th1.cont.empty());
315 BOOST_CHECK_EQUAL(th2.cont.size(), 0);
316 BOOST_CHECK(th2.cont.empty());
317 BOOST_CHECK(c.empty());
318 return timed_results_t::value_type(num_items/(
static_cast<
double>(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count())/1000000));
321 std::cout<<thread_t::thread_traits::demangle_name(
typeid(ctr_t))<<
" rate cctors/sec="<<timed_results.first<<std::endl;
322 #ifdef JMMCG_PERFORMANCE_TESTS
323 stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
324 BOOST_CHECK(!timed_results.second);
328 BOOST_AUTO_TEST_SUITE_END()
330 BOOST_AUTO_TEST_SUITE(performance_dtor, *stats_to_csv::make_fixture(
"shared_ptr_parallel_dtor.csv"))
344 BOOST_AUTO_TEST_CASE_TEMPLATE(parallel_deletes, ctr_t, ctr_types) {
345 typedef dtor_thread<ctr_t> thread_t;
346 #ifdef JMMCG_PERFORMANCE_TESTS
347 const std::size_t num_items=10000000;
349 const std::size_t num_items=100;
351 const unsigned short loops_for_conv=50;
352 const double perc_conv_estimate=5.0;
354 const std::pair<timed_results_t,
bool> timed_results(compute_average_deviation<timed_results_t::value_type>(
358 typename thread_t::cont_t c;
359 std::generate_n(std::back_inserter(c), num_items,
typename thread_t::make());
363 const auto t1=std::chrono::high_resolution_clock::now();
364 th1.create_running();
365 th2.create_running();
367 api_threading_traits<platform_api, heavyweight_threading>::sleep(100);
368 }
while (th1.is_running() || th2.is_running());
369 const auto t2=std::chrono::high_resolution_clock::now();
370 BOOST_CHECK(th1.cont.empty());
371 BOOST_CHECK(th2.cont.empty());
372 BOOST_CHECK(c.empty());
373 return timed_results_t::value_type(num_items/(
static_cast<
double>(std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count())/1000000));
376 std::cout<<thread_t::thread_traits::demangle_name(
typeid(ctr_t))<<
" rate dtors/sec="<<timed_results.first<<std::endl;
377 #ifdef JMMCG_PERFORMANCE_TESTS
378 stats_to_csv::handle->stats<<timed_results.first.to_csv()<<std::flush;
379 BOOST_CHECK(!timed_results.second);
383 BOOST_AUTO_TEST_SUITE_END()
385 BOOST_AUTO_TEST_SUITE_END()