4
/* Copyright 2009 10gen Inc.
6
* Licensed under the Apache License, Version 2.0 (the "License");
7
* you may not use this file except in compliance with the License.
8
* You may obtain a copy of the License at
10
* http://www.apache.org/licenses/LICENSE-2.0
12
* Unless required by applicable law or agreed to in writing, software
13
* distributed under the License is distributed on an "AS IS" BASIS,
14
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
* See the License for the specific language governing permissions and
16
* limitations under the License.
27
#if !defined(_WIN32) && !defined(NOEXECINFO)
36
inline pthread_t GetCurrentThreadId() {
37
return pthread_self();
40
/* use "addr2line -CFe <exe>" to parse. */
41
inline void printStackTrace( ostream &o = cout ) {
47
size = backtrace(b, 20);
48
strings = backtrace_symbols(b, size);
50
for (i = 0; i < size; i++)
51
o << hex << b[i] << dec << ' ';
53
for (i = 0; i < size; i++)
54
o << ' ' << strings[i] << '\n';
59
inline void printStackTrace( ostream &o = cout ) { }
62
/* set to TRUE if we are exiting */
63
extern bool goingAway;
65
/* find the multimap member which matches a particular key and value.
67
note this can be slow if there are a lot with the same key.
69
template<class C,class K,class V> inline typename C::iterator kv_find(C& c, const K& k,const V& v) {
70
pair<typename C::iterator,typename C::iterator> p = c.equal_range(k);
72
for ( typename C::iterator it=p.first; it!=p.second; ++it)
73
if ( it->second == v )
82
inline void dumpmemory(const char *data, int len) {
89
for ( int i = 0; i < 16; i++ ) {
90
if ( *p >= 32 && *p <= 126 )
98
for ( int i = 0; i < 16; i++ )
99
cout << (unsigned) ((unsigned char)*p++) << ' ';
107
// PRINT(2+2); prints "2+2: 4"
108
#define PRINT(x) cout << #x ": " << (x) << endl
109
// PRINTFL; prints file:line
110
#define PRINTFL cout << __FILE__ ":" << __LINE__ << endl
115
#define assert xassert
122
WrappingInt(unsigned z) : x(z) { }
124
operator unsigned() const {
128
// returns original value (like x++)
129
WrappingInt atomicIncrement(){
131
// InterlockedIncrement returns the new value
132
return InterlockedIncrement((volatile long*)&x)-1; //long is 32bits in Win64
133
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
134
// this is in GCC >= 4.1
135
return __sync_fetch_and_add(&x, 1);
136
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
137
// from boost 1.39 interprocess/detail/atomic.hpp
144
"+m"( x ), "=r"( r ): // outputs (%0, %1)
145
"1"( val ): // inputs (%2 == %1)
146
"memory", "cc" // clobbers
150
# error "unsupported compiler or platform"
154
static int diff(unsigned a, unsigned b) {
157
bool operator<=(WrappingInt r) {
158
// platform dependent
162
bool operator>(WrappingInt r) {
173
inline void time_t_to_String(time_t t, char *buf) {
175
ctime_s(buf, 64, &t);
179
buf[24] = 0; // don't want the \n
182
#define asctime _asctime_not_threadsafe_
183
#define gmtime _gmtime_not_threadsafe_
184
#define localtime _localtime_not_threadsafe_
185
#define ctime _ctime_is_not_threadsafe_
187
#if defined(_WIN32) || defined(__sunos__)
188
inline void sleepsecs(int s) {
190
boost::xtime_get(&xt, boost::TIME_UTC);
192
boost::thread::sleep(xt);
194
inline void sleepmillis(int s) {
196
boost::xtime_get(&xt, boost::TIME_UTC);
197
xt.sec += ( s / 1000 );
198
xt.nsec += ( s % 1000 ) * 1000000;
199
if ( xt.nsec >= 1000000000 ) {
200
xt.nsec -= 1000000000;
203
boost::thread::sleep(xt);
205
inline void sleepmicros(int s) {
207
boost::xtime_get(&xt, boost::TIME_UTC);
208
xt.sec += ( s / 1000000 );
209
xt.nsec += ( s % 1000000 ) * 1000;
210
if ( xt.nsec >= 1000000000 ) {
211
xt.nsec -= 1000000000;
214
boost::thread::sleep(xt);
217
inline void sleepsecs(int s) {
221
if ( nanosleep( &t , 0 ) ){
222
cout << "nanosleep failed" << endl;
225
inline void sleepmicros(int s) {
227
t.tv_sec = (int)(s / 1000000);
228
t.tv_nsec = s % 1000000;
229
if ( nanosleep( &t , 0 ) ){
230
cout << "nanosleep failed" << endl;
233
inline void sleepmillis(int s) {
234
sleepmicros( s * 1000 );
239
inline int tdiff(unsigned told, unsigned tnew) {
240
return WrappingInt::diff(tnew, told);
242
inline unsigned curTimeMillis() {
244
boost::xtime_get(&xt, boost::TIME_UTC);
245
unsigned t = xt.nsec / 1000000;
246
return (xt.sec & 0xfffff) * 1000 + t;
250
// TODO: make signed (and look for related TODO's)
251
unsigned long long millis;
252
Date_t(): millis(0) {}
253
Date_t(unsigned long long m): millis(m) {}
254
operator unsigned long long&() { return millis; }
255
operator const unsigned long long&() const { return millis; }
258
inline Date_t jsTime() {
260
boost::xtime_get(&xt, boost::TIME_UTC);
261
unsigned long long t = xt.nsec / 1000000;
262
return ((unsigned long long) xt.sec * 1000) + t;
265
inline unsigned long long curTimeMicros64() {
267
boost::xtime_get(&xt, boost::TIME_UTC);
268
unsigned long long t = xt.nsec / 1000;
269
return (((unsigned long long) xt.sec) * 1000000) + t;
272
// measures up to 1024 seconds. or, 512 seconds with tdiff that is...
273
inline unsigned curTimeMicros() {
275
boost::xtime_get(&xt, boost::TIME_UTC);
276
unsigned t = xt.nsec / 1000;
277
unsigned secs = xt.sec % 1024;
278
return secs*1000000 + t;
280
using namespace boost;
281
typedef boost::mutex::scoped_lock boostlock;
282
typedef boost::recursive_mutex::scoped_lock recursive_boostlock;
284
// simple scoped timer
290
Timer( unsigned long long start ) {
294
return (int)(micros() / 1000000);
297
return (long)(micros() / 1000);
299
unsigned long long micros() {
300
unsigned long long n = curTimeMicros64();
303
unsigned long long micros(unsigned long long & n) { // returns cur time in addition to timer result
304
n = curTimeMicros64();
307
unsigned long long startTime(){
311
old = curTimeMicros64();
314
unsigned long long old;
319
class DebugMutex : boost::noncopyable {
324
DebugMutex() : locked(0); { }
325
bool isLocked() { return locked; }
330
//typedef boostlock lock;
332
inline bool startsWith(const char *str, const char *prefix) {
333
unsigned l = strlen(prefix);
334
if ( strlen(str) < l ) return false;
335
return strncmp(str, prefix, l) == 0;
338
inline bool endsWith(const char *p, const char *suffix) {
340
int b = strlen(suffix);
341
if ( b > a ) return false;
342
return strcmp(p + a - b, suffix) == 0;
347
#include "boost/detail/endian.hpp"
351
inline unsigned long swapEndian(unsigned long x) {
354
((x & 0xff00) << 8) |
355
((x & 0xff0000) >> 8) |
356
((x & 0xff000000) >> 24);
359
#if defined(BOOST_LITTLE_ENDIAN)
360
inline unsigned long fixEndian(unsigned long x) {
364
inline unsigned long fixEndian(unsigned long x) {
365
return swapEndian(x);
369
// Like strlen, but only scans up to n bytes.
370
// Returns -1 if no '0' found.
371
inline int strnlen( const char *s, int n ) {
372
for( int i = 0; i < n; ++i )
380
inline void strcpy_s(char *dst, unsigned len, const char *src) {
384
typedef void *HANDLE;
387
/* thread local "value" rather than a pointer
388
good for things which have copy constructors (and the copy constructor is fast enough)
390
ThreadLocalValue<int> myint;
393
class ThreadLocalValue {
395
ThreadLocalValue( T def = 0 ) : _default( def ) { }
398
T * val = _val.get();
404
void set( const T& i ) {
416
boost::thread_specific_ptr<T> _val;
419
class ProgressMeter {
421
ProgressMeter( long long total , int secondsBetween = 3 , int checkInterval = 100 )
422
: _total( total ) , _secondsBetween( secondsBetween ) , _checkInterval( checkInterval ) ,
423
_done(0) , _hits(0) , _lastTime( (int) time(0) ){
426
bool hit( int n = 1 ){
429
if ( _hits % _checkInterval )
432
int t = (int) time(0);
433
if ( t - _lastTime < _secondsBetween )
437
int per = (int)( ( (double)_done * 100.0 ) / (double)_total );
438
cout << "\t\t" << _done << "/" << _total << "\t" << per << "%" << endl;
465
TicketHolder( int num ){
471
boostlock lk( _mutex );
474
cerr << "DISASTER! in TicketHolder" << endl;
483
boostlock lk( _mutex );
487
void resize( int newSize ){
488
boostlock lk( _mutex );
489
int used = _outof - _num;
490
if ( used > newSize ){
491
cout << "ERROR: can't resize since we're using (" << used << ") more than newSize(" << newSize << ")" << endl;
496
_num = _outof - used;
504
return _outof - _num;
513
class TicketHolderReleaser {
515
TicketHolderReleaser( TicketHolder * holder ){
519
~TicketHolderReleaser(){
523
TicketHolder * _holder;