libfoedus-core
FOEDUS Core Library
assorted_func.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2015, Hewlett-Packard Development Company, LP.
3  * This program is free software; you can redistribute it and/or modify it
4  * under the terms of the GNU General Public License as published by the Free
5  * Software Foundation; either version 2 of the License, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11  * more details. You should have received a copy of the GNU General Public
12  * License along with this program; if not, write to the Free Software
13  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14  *
15  * HP designates this particular file as subject to the "Classpath" exception
16  * as provided by HP in the LICENSE.txt file that accompanied this code.
17  */
19 
20 #ifdef __GNUC__ // for get_pretty_type_name()
21 #include <cxxabi.h>
22 #endif // __GNUC__
23 #include <stdint.h>
24 #include <unistd.h>
25 #include <valgrind.h>
26 
27 #include <algorithm>
28 #include <cstdlib>
29 #include <cstring>
30 #include <iostream>
31 #include <sstream>
32 #include <string>
33 #include <thread>
34 
36 
37 namespace foedus {
38 namespace assorted {
39 
40 int64_t int_div_ceil(int64_t dividee, int64_t dividor) {
41  std::ldiv_t result = std::div(dividee, dividor);
42  return result.rem != 0 ? (result.quot + 1) : result.quot;
43 }
44 
45 std::string replace_all(const std::string& target, const std::string& search,
46  const std::string& replacement) {
47  std::string subject = target;
48  while (true) {
49  std::size_t pos = subject.find(search);
50  if (pos != std::string::npos) {
51  subject.replace(pos, search.size(), replacement);
52  } else {
53  break;
54  }
55  }
56  return subject;
57 }
58 
59 std::string replace_all(const std::string& target, const std::string& search,
60  int replacement) {
61  std::stringstream str;
62  str << replacement;
63  std::string rep = str.str();
64  return replace_all(target, search, rep);
65 }
66 
67 std::string os_error() {
68  return os_error(errno);
69 }
70 
71 std::string os_error(int error_number) {
72  if (error_number == 0) {
73  return "[No Error]";
74  }
75  std::stringstream str;
76  // NOTE(Hideaki) is std::strerror thread-safe? Thre is no std::strerror_r. Windows, mmm.
77  str << "[Errno " << error_number << "] " << std::strerror(error_number);
78  return str.str();
79 }
80 
82  char buf[1024];
83  ssize_t len = ::readlink("/proc/self/exe", buf, sizeof(buf));
84  if (len == -1) {
85  std::cerr << "Failed to get the path of current executable. error=" << os_error() << std::endl;
86  return "";
87  }
88  return std::string(buf, len);
89 }
90 
91 const char* kUpperHexChars = "0123456789ABCDEF";
92 std::ostream& operator<<(std::ostream& o, const Hex& v) {
93  // Duh, even if I recover the flags, not good to contaminate the given ostream object.
94  // std::ios::fmtflags old_flags = o.flags();
95  // o << "0x";
96  // if (v.fix_digits_ >= 0) {
97  // o.width(v.fix_digits_);
98  // o.fill('0');
99  // }
100  // o << std::hex << std::uppercase << v.val_;
101  // o.flags(old_flags);
102 
103  // Let's do it ourselves
104  char buffer[17];
105  buffer[16] = 0;
106  for (uint16_t i = 0; i < 16U; ++i) {
107  buffer[i] = kUpperHexChars[(v.val_ >> ((15 - i) * 4)) & 0xFU];
108  }
109  uint16_t start_pos;
110  for (start_pos = 0; start_pos < 15U; ++start_pos) {
111  if (buffer[start_pos] != '0') {
112  break;
113  }
114  if (v.fix_digits_ >= 0 && start_pos > 16 - v.fix_digits_) {
115  break;
116  }
117  }
118 
119  o << "0x" << (buffer + start_pos);
120  return o;
121 }
122 
123 std::ostream& operator<<(std::ostream& o, const HexString& v) {
124  // Same above
125  o << "0x";
126  for (uint32_t i = 0; i < v.str_.size() && i < v.max_bytes_; ++i) {
127  if (i > 0 && i % 8U == 0) {
128  o << " "; // put space for every 8 bytes for readability
129  }
130  o << kUpperHexChars[(v.str_[i] >> 4) & 0xFU] << kUpperHexChars[v.str_[i] & 0xFU];
131  }
132  if (v.max_bytes_ != -1U && v.str_.size() > v.max_bytes_) {
133  o << " ...(" << (v.str_.size() - v.max_bytes_) << " more bytes)";
134  }
135  return o;
136 }
137 
138 std::ostream& operator<<(std::ostream& o, const Top& v) {
139  for (uint32_t i = 0; i < std::min<uint32_t>(v.data_len_, v.max_bytes_); ++i) {
140  o << i << ":" << static_cast<int>(v.data_[i]);
141  if (i != 0) {
142  o << ", ";
143  }
144  }
145  if (v.data_len_ > v.max_bytes_) {
146  o << "...";
147  }
148  return o;
149 }
150 
151 std::string demangle_type_name(const char* mangled_name) {
152 #ifdef __GNUC__
153  int status;
154  char* demangled = abi::__cxa_demangle(mangled_name, nullptr, nullptr, &status);
155  if (demangled) {
156  std::string ret(demangled);
157  ::free(demangled);
158  return ret;
159  }
160 #endif // __GNUC__
161  return mangled_name;
162 }
163 
164 uint64_t generate_almost_prime_below(uint64_t threshold) {
165  if (threshold <= 2) {
166  return 1; // almost an invalid input...
167  } else if (threshold < 5000) {
168  // for a small number, we just use a (very) sparse prime list
169  uint16_t small_primes[] = {3677, 2347, 1361, 773, 449, 263, 151, 89, 41, 17, 2};
170  for (int i = 0;; ++i) {
171  if (threshold > small_primes[i]) {
172  return small_primes[i];
173  }
174  }
175  } else {
176  // the following formula is monotonically increasing for i>=22 (which gives 3923).
177  uint64_t prev = 3677;
178  for (uint64_t i = 22;; ++i) {
179  uint64_t cur = (i * i * i * i * i - 133 * i * i * i * i + 6729 * i * i * i
180  - 158379 * i * i + 1720294 * i - 6823316) >> 2;
181  if (cur >= threshold) {
182  return prev;
183  } else if (cur <= prev) {
184  // sanity checking.
185  return prev;
186  } else {
187  prev = cur;
188  }
189  }
190  }
191 }
192 
194  // we initially used gcc's mm_pause and manual assembly, but now we use this to handle AArch64.
195  // It might be no-op (not guaranteed to yield, according to the C++ specifictation)
196  // depending on GCC's implementation, but portability is more important.
197  std::this_thread::yield();
198  // #if defined(__GNUC__)
199  // ::_mm_pause();
200  // #else // defined(__GNUC__)
201  // // Non-gcc compiler.
202  // asm volatile("pause" ::: "memory");
203  // #endif // defined(__GNUC__)
204 }
205 
207  if (spins_ == 0) {
208  // do the real initialization only when we couldn't get a lock.
209  // hopefully 99% cases we don't hit here.
210  std::hash<std::thread::id> h;
211  rnd_.set_current_seed(h(std::this_thread::get_id()));
212  rnd_.next_uint32();
213  }
214  ++spins_;
215 
216  // valgrind is single-threaded. so, we must yield as much as possible to let it run reasonably.
217  if (RUNNING_ON_VALGRIND) {
218  spinlock_yield();
219  return;
220  }
221 
222  // exponential backoff. also do yielding occasionally.
223  const uint64_t kMinSleepCycles = 1ULL << 7; // one atomic CAS
224  const uint64_t kMaxSleepCycles = 1ULL << 12; // even this might be too long..
225  uint64_t wait_cycles_max = spins_ < 5U ? kMinSleepCycles << spins_ : kMaxSleepCycles;
226  uint32_t wait_cycles = kMinSleepCycles + rnd_.next_uint32() % (wait_cycles_max - kMinSleepCycles);
227  debugging::wait_rdtsc_cycles(wait_cycles);
228  if (spins_ % 256U == 0) {
229  spinlock_yield();
230  }
231 }
232 
233 
234 } // namespace assorted
235 } // namespace foedus
236 
Root package of FOEDUS (Fast Optimistic Engine for Data Unification Services).
Definition: assert_nd.hpp:44
FileStatus status(const Path &p)
Returns the status of the file.
Definition: filesystem.cpp:45
void wait_rdtsc_cycles(uint64_t cycles)
Wait until the given CPU cycles elapse.
Definition: rdtsc.hpp:60
void set_current_seed(uint64_t seed)
std::string get_current_executable_path()
Returns the full path of current executable.
std::string replace_all(const std::string &target, const std::string &search, const std::string &replacement)
target.replaceAll(search, replacement).
const char * kUpperHexChars
Equivalent to std::hex in case the stream doesn't support it.
void spinlock_yield()
Invoke _mm_pause(), x86 PAUSE instruction, or something equivalent in the env.
Write only first few bytes to stream.
std::string os_error()
Thread-safe strerror(errno).
uint64_t generate_almost_prime_below(uint64_t threshold)
Generate a prime or some number that is almost prime less than the given number.
std::string demangle_type_name(const char *mangled_name)
Demangle the given C++ type name if possible (otherwise the original string).
Convenient way of writing hex integers to stream.
Implements an RDTSC (Real-time time stamp counter) wait to emulate latency on slower devices...
int64_t int_div_ceil(int64_t dividee, int64_t dividor)
Efficient ceil(dividee/dividor) for integer.
std::ostream & operator<<(std::ostream &o, const Hex &v)