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