trivial_destructor_example.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. *
  3. * (C) Copyright John Maddock 1999-2005.
  4. * Use, modification and distribution are subject to the
  5. * Boost Software License, Version 1.0. (See accompanying file
  6. * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. *
  8. * This file provides some example of type_traits usage -
  9. * by "optimising" various algorithms:
  10. *
  11. * opt::destroy_array - an example of optimisation based upon omitted destructor calls
  12. *
  13. */
  14. #include <iostream>
  15. #include <boost/test/included/prg_exec_monitor.hpp>
  16. #include <boost/timer.hpp>
  17. #include <boost/type_traits.hpp>
  18. using std::cout;
  19. using std::endl;
  20. using std::cin;
  21. namespace opt{
  22. //
  23. // algorithm destroy_array:
  24. // The reverse of std::unitialized_copy, takes a block of
  25. // initialized memory and calls destructors on all objects therein.
  26. //
  27. namespace detail{
  28. template <class T>
  29. void do_destroy_array(T* first, T* last, const boost::false_type&)
  30. {
  31. while(first != last)
  32. {
  33. first->~T();
  34. ++first;
  35. }
  36. }
  37. template <class T>
  38. inline void do_destroy_array(T* first, T* last, const boost::true_type&)
  39. {
  40. }
  41. } // namespace detail
  42. template <class T>
  43. inline void destroy_array(T* p1, T* p2)
  44. {
  45. detail::do_destroy_array(p1, p2, ::boost::has_trivial_destructor<T>());
  46. }
  47. //
  48. // unoptimised versions of destroy_array:
  49. //
  50. template <class T>
  51. void destroy_array1(T* first, T* last)
  52. {
  53. while(first != last)
  54. {
  55. first->~T();
  56. ++first;
  57. }
  58. }
  59. template <class T>
  60. void destroy_array2(T* first, T* last)
  61. {
  62. for(; first != last; ++first) first->~T();
  63. }
  64. } // namespace opt
  65. //
  66. // define some global data:
  67. //
  68. const int array_size = 1000;
  69. int i_array[array_size] = {0,};
  70. const int ci_array[array_size] = {0,};
  71. char c_array[array_size] = {0,};
  72. const char cc_array[array_size] = { 0,};
  73. const int iter_count = 1000000;
  74. int cpp_main(int argc, char* argv[])
  75. {
  76. boost::timer t;
  77. double result;
  78. int i;
  79. //
  80. // test destroy_array,
  81. // compare destruction time of an array of ints
  82. // with unoptimised form.
  83. //
  84. cout << "Measuring times in micro-seconds per 1000 elements processed" << endl << endl;
  85. cout << "testing destroy_array...\n"
  86. "[Some compilers may be able to optimise the \"unoptimised\"\n versions as well as type_traits does.]" << endl;
  87. // cache load:
  88. opt::destroy_array(i_array, i_array + array_size);
  89. // time optimised version:
  90. t.restart();
  91. for(i = 0; i < iter_count; ++i)
  92. {
  93. opt::destroy_array(i_array, i_array + array_size);
  94. }
  95. result = t.elapsed();
  96. cout << "destroy_array<int>: " << result << endl;
  97. // cache load:
  98. opt::destroy_array1(i_array, i_array + array_size);
  99. // time unoptimised version #1:
  100. t.restart();
  101. for(i = 0; i < iter_count; ++i)
  102. {
  103. opt::destroy_array1(i_array, i_array + array_size);
  104. }
  105. result = t.elapsed();
  106. cout << "destroy_array<int>(unoptimised#1): " << result << endl;
  107. // cache load:
  108. opt::destroy_array2(i_array, i_array + array_size);
  109. // time unoptimised version #2:
  110. t.restart();
  111. for(i = 0; i < iter_count; ++i)
  112. {
  113. opt::destroy_array2(i_array, i_array + array_size);
  114. }
  115. result = t.elapsed();
  116. cout << "destroy_array<int>(unoptimised#2): " << result << endl << endl;
  117. return 0;
  118. }