// hack hack hack ugly FIXME
long buffer_total_alloc = 0;
+Mutex bufferlock;
+
OSDFileLayout g_OSD_FileLayout( 1<<20, 1, 1<<20 ); // stripe files over whole objects
#include <iostream>
using namespace std;
+
+
void parse_config_options(int argc, char **argv,
int& nargc, char**&nargv)
{
#include "include/config.h"
#define bdbout(x) if (x <= g_conf.debug_buffer) cout
+#include "common/Mutex.h"
+// HACK: in config.cc
+/*
+ * WARNING: bufferlock placements are tricky for efficiency. note that only bufferptr and
+ * buffer ever use buffer._ref, and only bufferptr should call ~buffer().
+ *
+ * So, I only need to protect:
+ * - buffer()'s modification of buffer_total_alloc
+ * - ~bufferptr() check of buffer._ref, and ~buffer's mod of buffer_total_alloc
+ *
+ * I don't protect
+ * - buffer._get() .. increment is atomic on any sane architecture
+ * - buffer._put() .. only called by ~bufferptr.
+ * - ~buffer .. only called by ~bufferptr *** I HOPE!!
+ */
+extern Mutex bufferlock;
extern long buffer_total_alloc;
+
+
/*
* buffer - the underlying buffer container. with a reference count.
*
int _ref;
int _get() {
bdbout(1) << "buffer.get " << *this << " get " << _ref+1 << endl;
- return ++_ref;
+ return ++_ref;
}
int _put() {
bdbout(1) << "buffer.put " << *this << " put " << _ref-1 << endl;
- return --_ref;
+ return --_ref;
}
friend class bufferptr;
buffer(int a) : _dataptr(0), _len(0), _alloc_len(a), _ref(0), _myptr(true) {
bdbout(1) << "buffer.cons " << *this << endl;
_dataptr = new char[a];
+ bufferlock.Lock();
buffer_total_alloc += _alloc_len;
+ bufferlock.Unlock();
bdbout(1) << "buffer.malloc " << (void*)_dataptr << endl;
}
~buffer() {
if (mode & BUFFER_MODE_COPY) {
_dataptr = new char[_alloc_len];
bdbout(1) << "buffer.malloc " << (void*)_dataptr << endl;
+ bufferlock.Lock();
buffer_total_alloc += _alloc_len;
+ bufferlock.Unlock();
memcpy(_dataptr, p, l);
bdbout(1) << "buffer.copy " << *this << endl;
} else {
}
~bufferptr() {
- if (_buffer && _buffer->_put() == 0)
- delete _buffer;
+ if (_buffer) {
+ bufferlock.Lock();
+ if (_buffer->_put() == 0)
+ delete _buffer;
+ bufferlock.Unlock();
+ }
}