Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/interprocess/sync/spin/wait.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 ////////////////////////////////////////////////////////////////////////////// | |
2 // | |
3 // (C) Copyright Peter Dimov 2008. | |
4 // (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost | |
5 // 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 // See http://www.boost.org/libs/interprocess for documentation. | |
9 // | |
10 ////////////////////////////////////////////////////////////////////////////// | |
11 | |
12 //Parts of this file come from boost/smart_ptr/detail/yield_k.hpp | |
13 //Many thanks to Peter Dimov. | |
14 | |
15 #ifndef BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED | |
16 #define BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED | |
17 | |
18 #if defined(_MSC_VER) && (_MSC_VER >= 1020) | |
19 # pragma once | |
20 #endif | |
21 | |
22 #include <boost/interprocess/detail/config_begin.hpp> | |
23 #include <boost/interprocess/detail/workaround.hpp> | |
24 #include <boost/interprocess/detail/os_thread_functions.hpp> | |
25 | |
26 //#define BOOST_INTERPROCESS_SPIN_WAIT_DEBUG | |
27 #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG | |
28 #include <iostream> | |
29 #endif | |
30 | |
31 // BOOST_INTERPROCESS_SMT_PAUSE | |
32 | |
33 #if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) | |
34 | |
35 extern "C" void _mm_pause(); | |
36 #pragma intrinsic( _mm_pause ) | |
37 | |
38 #define BOOST_INTERPROCESS_SMT_PAUSE _mm_pause(); | |
39 | |
40 #elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) | |
41 | |
42 #define BOOST_INTERPROCESS_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" ); | |
43 | |
44 #endif | |
45 | |
46 namespace boost{ | |
47 namespace interprocess{ | |
48 namespace ipcdetail { | |
49 | |
50 template<int Dummy = 0> | |
51 class num_core_holder | |
52 { | |
53 public: | |
54 static unsigned int get() | |
55 { | |
56 if(!num_cores){ | |
57 return ipcdetail::get_num_cores(); | |
58 } | |
59 else{ | |
60 return num_cores; | |
61 } | |
62 } | |
63 | |
64 private: | |
65 static unsigned int num_cores; | |
66 }; | |
67 | |
68 template<int Dummy> | |
69 unsigned int num_core_holder<Dummy>::num_cores = ipcdetail::get_num_cores(); | |
70 | |
71 } //namespace ipcdetail { | |
72 | |
73 class spin_wait | |
74 { | |
75 public: | |
76 | |
77 static const unsigned int nop_pause_limit = 32u; | |
78 spin_wait() | |
79 : m_count_start(), m_ul_yield_only_counts(), m_k() | |
80 {} | |
81 | |
82 #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG | |
83 ~spin_wait() | |
84 { | |
85 if(m_k){ | |
86 std::cout << "final m_k: " << m_k | |
87 << " system tick(us): " << ipcdetail::get_system_tick_us() << std::endl; | |
88 } | |
89 } | |
90 #endif | |
91 | |
92 unsigned int count() const | |
93 { return m_k; } | |
94 | |
95 void yield() | |
96 { | |
97 //Lazy initialization of limits | |
98 if( !m_k){ | |
99 this->init_limits(); | |
100 } | |
101 //Nop tries | |
102 if( m_k < (nop_pause_limit >> 2) ){ | |
103 | |
104 } | |
105 //Pause tries if the processor supports it | |
106 #if defined(BOOST_INTERPROCESS_SMT_PAUSE) | |
107 else if( m_k < nop_pause_limit ){ | |
108 BOOST_INTERPROCESS_SMT_PAUSE | |
109 } | |
110 #endif | |
111 //Yield/Sleep strategy | |
112 else{ | |
113 //Lazy initialization of tick information | |
114 if(m_k == nop_pause_limit){ | |
115 this->init_tick_info(); | |
116 } | |
117 else if( this->yield_or_sleep() ){ | |
118 ipcdetail::thread_yield(); | |
119 } | |
120 else{ | |
121 ipcdetail::thread_sleep_tick(); | |
122 } | |
123 } | |
124 ++m_k; | |
125 } | |
126 | |
127 void reset() | |
128 { | |
129 m_k = 0u; | |
130 } | |
131 | |
132 private: | |
133 | |
134 void init_limits() | |
135 { | |
136 unsigned int num_cores = ipcdetail::num_core_holder<0>::get(); | |
137 m_k = num_cores > 1u ? 0u : nop_pause_limit; | |
138 } | |
139 | |
140 void init_tick_info() | |
141 { | |
142 m_ul_yield_only_counts = ipcdetail::get_system_tick_in_highres_counts(); | |
143 m_count_start = ipcdetail::get_current_system_highres_count(); | |
144 } | |
145 | |
146 //Returns true if yield must be called, false is sleep must be called | |
147 bool yield_or_sleep() | |
148 { | |
149 if(!m_ul_yield_only_counts){ //If yield-only limit was reached then yield one in every two tries | |
150 return (m_k & 1u) != 0; | |
151 } | |
152 else{ //Try to see if we've reched yield-only time limit | |
153 const ipcdetail::OS_highres_count_t now = ipcdetail::get_current_system_highres_count(); | |
154 const ipcdetail::OS_highres_count_t elapsed = ipcdetail::system_highres_count_subtract(now, m_count_start); | |
155 if(!ipcdetail::system_highres_count_less_ul(elapsed, m_ul_yield_only_counts)){ | |
156 #ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG | |
157 std::cout << "elapsed!\n" | |
158 << " m_ul_yield_only_counts: " << m_ul_yield_only_counts | |
159 << " system tick(us): " << ipcdetail::get_system_tick_us() << '\n' | |
160 << " m_k: " << m_k << " elapsed counts: "; | |
161 ipcdetail::ostream_highres_count(std::cout, elapsed) << std::endl; | |
162 #endif | |
163 //Yield-only time reached, now it's time to sleep | |
164 m_ul_yield_only_counts = 0ul; | |
165 return false; | |
166 } | |
167 } | |
168 return true; //Otherwise yield | |
169 } | |
170 | |
171 ipcdetail::OS_highres_count_t m_count_start; | |
172 unsigned long m_ul_yield_only_counts; | |
173 unsigned int m_k; | |
174 }; | |
175 | |
176 } // namespace interprocess | |
177 } // namespace boost | |
178 | |
179 #include <boost/interprocess/detail/config_end.hpp> | |
180 | |
181 #endif // #ifndef BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED |