summaryrefslogtreecommitdiff
path: root/bson/util
diff options
context:
space:
mode:
Diffstat (limited to 'bson/util')
-rw-r--r--bson/util/atomic_int.h11
-rw-r--r--bson/util/builder.h87
-rw-r--r--bson/util/misc.h21
3 files changed, 99 insertions, 20 deletions
diff --git a/bson/util/atomic_int.h b/bson/util/atomic_int.h
index 1573552..e85a023 100644
--- a/bson/util/atomic_int.h
+++ b/bson/util/atomic_int.h
@@ -36,15 +36,17 @@ namespace mongo {
inline AtomicUInt operator--(); // --prefix
inline AtomicUInt operator--(int); // postfix--
- inline void zero() { x = 0; } // TODO: this isn't thread safe
+ inline void zero();
volatile unsigned x;
};
#if defined(_WIN32)
+ void AtomicUInt::zero() {
+ InterlockedExchange((volatile long*)&x, 0);
+ }
AtomicUInt AtomicUInt::operator++() {
- // InterlockedIncrement returns the new value
- return InterlockedIncrement((volatile long*)&x); //long is 32bits in Win64
+ return InterlockedIncrement((volatile long*)&x);
}
AtomicUInt AtomicUInt::operator++(int) {
return InterlockedIncrement((volatile long*)&x)-1;
@@ -57,6 +59,7 @@ namespace mongo {
}
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
// this is in GCC >= 4.1
+ inline void AtomicUInt::zero() { x = 0; } // TODO: this isn't thread safe - maybe
AtomicUInt AtomicUInt::operator++() {
return __sync_add_and_fetch(&x, 1);
}
@@ -70,8 +73,8 @@ namespace mongo {
return __sync_fetch_and_add(&x, -1);
}
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+ inline void AtomicUInt::zero() { x = 0; } // TODO: this isn't thread safe
// from boost 1.39 interprocess/detail/atomic.hpp
-
inline unsigned atomic_int_helper(volatile unsigned *x, int val) {
int r;
asm volatile
diff --git a/bson/util/builder.h b/bson/util/builder.h
index 6f4ff9e..710c2d4 100644
--- a/bson/util/builder.h
+++ b/bson/util/builder.h
@@ -20,8 +20,6 @@
#include <string>
#include <string.h>
#include <stdio.h>
-#include <boost/shared_ptr.hpp>
-
#include "../inline_decls.h"
#include "../stringdata.h"
@@ -49,11 +47,47 @@ namespace mongo {
void msgasserted(int msgid, const char *msg);
- class BufBuilder {
+ class TrivialAllocator {
+ public:
+ void* Malloc(size_t sz) { return malloc(sz); }
+ void* Realloc(void *p, size_t sz) { return realloc(p, sz); }
+ void Free(void *p) { free(p); }
+ };
+
+ class StackAllocator {
+ public:
+ enum { SZ = 512 };
+ void* Malloc(size_t sz) {
+ if( sz <= SZ ) return buf;
+ return malloc(sz);
+ }
+ void* Realloc(void *p, size_t sz) {
+ if( p == buf ) {
+ if( sz <= SZ ) return buf;
+ void *d = malloc(sz);
+ memcpy(d, p, SZ);
+ return d;
+ }
+ return realloc(p, sz);
+ }
+ void Free(void *p) {
+ if( p != buf )
+ free(p);
+ }
+ private:
+ char buf[SZ];
+ };
+
+ template< class Allocator >
+ class _BufBuilder {
+ // non-copyable, non-assignable
+ _BufBuilder( const _BufBuilder& );
+ _BufBuilder& operator=( const _BufBuilder& );
+ Allocator al;
public:
- BufBuilder(int initsize = 512) : size(initsize) {
+ _BufBuilder(int initsize = 512) : size(initsize) {
if ( size > 0 ) {
- data = (char *) malloc(size);
+ data = (char *) al.Malloc(size);
if( data == 0 )
msgasserted(10000, "out of memory BufBuilder");
}
@@ -62,22 +96,23 @@ namespace mongo {
}
l = 0;
}
- ~BufBuilder() {
- kill();
- }
+ ~_BufBuilder() { kill(); }
void kill() {
if ( data ) {
- free(data);
+ al.Free(data);
data = 0;
}
}
- void reset( int maxSize = 0 ) {
+ void reset() {
+ l = 0;
+ }
+ void reset( int maxSize ) {
l = 0;
if ( maxSize && size > maxSize ) {
- free(data);
- data = (char*)malloc(maxSize);
+ al.Free(data);
+ data = (char*)al.Malloc(maxSize);
size = maxSize;
}
}
@@ -94,6 +129,9 @@ namespace mongo {
/* assume ownership of the buffer - you must then free() it */
void decouple() { data = 0; }
+ void appendUChar(unsigned char j) {
+ *((unsigned char*)grow(sizeof(unsigned char))) = j;
+ }
void appendChar(char j) {
*((char*)grow(sizeof(char))) = j;
}
@@ -131,13 +169,15 @@ namespace mongo {
appendBuf(&s, sizeof(T));
}
- void appendStr(const StringData &str , bool includeEOO = true ) {
- const int len = str.size() + ( includeEOO ? 1 : 0 );
+ void appendStr(const StringData &str , bool includeEndingNull = true ) {
+ const int len = str.size() + ( includeEndingNull ? 1 : 0 );
memcpy(grow(len), str.data(), len);
}
+ /** @return length of current string */
int len() const { return l; }
void setlen( int newLen ) { l = newLen; }
+ /** @return size of the buffer */
int getSize() const { return size; }
/* returns the pre-grow write position */
@@ -160,7 +200,7 @@ namespace mongo {
a = l + 16 * 1024;
if ( a > BufferMaxSize )
msgasserted(13548, "BufBuilder grow() > 64MB");
- data = (char *) realloc(data, a);
+ data = (char *) al.Realloc(data, a);
size= a;
}
@@ -171,6 +211,21 @@ namespace mongo {
friend class StringBuilder;
};
+ typedef _BufBuilder<TrivialAllocator> BufBuilder;
+
+ /** The StackBufBuilder builds smaller datasets on the stack instead of using malloc.
+ this can be significantly faster for small bufs. However, you can not decouple() the
+ buffer with StackBufBuilder.
+ While designed to be a variable on the stack, if you were to dynamically allocate one,
+ nothing bad would happen. In fact in some circumstances this might make sense, say,
+ embedded in some other object.
+ */
+ class StackBufBuilder : public _BufBuilder<StackAllocator> {
+ public:
+ StackBufBuilder() : _BufBuilder<StackAllocator>(StackAllocator::SZ) { }
+ void decouple(); // not allowed. not implemented.
+ };
+
#if defined(_WIN32)
#pragma warning( push )
// warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
@@ -236,6 +291,8 @@ namespace mongo {
void reset( int maxSize = 0 ) { _buf.reset( maxSize ); }
std::string str() const { return std::string(_buf.data, _buf.l); }
+
+ int len() const { return _buf.l; }
private:
BufBuilder _buf;
diff --git a/bson/util/misc.h b/bson/util/misc.h
index b31f36f..33764e3 100644
--- a/bson/util/misc.h
+++ b/bson/util/misc.h
@@ -1,4 +1,4 @@
-/* @file util.h
+/* @file misc.h
*/
/*
@@ -91,4 +91,23 @@ namespace mongo {
return i;
return -1;
}
+
+ inline bool isNumber( char c ) {
+ return c >= '0' && c <= '9';
+ }
+
+ inline unsigned stringToNum(const char *str) {
+ unsigned x = 0;
+ const char *p = str;
+ while( 1 ) {
+ if( !isNumber(*p) ) {
+ if( *p == 0 && p != str )
+ break;
+ throw 0;
+ }
+ x = x * 10 + *p++ - '0';
+ }
+ return x;
+ }
+
}