summaryrefslogtreecommitdiff
path: root/indra/llmessage/llbuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/llbuffer.cpp')
-rwxr-xr-x[-rw-r--r--]indra/llmessage/llbuffer.cpp153
1 files changed, 105 insertions, 48 deletions
diff --git a/indra/llmessage/llbuffer.cpp b/indra/llmessage/llbuffer.cpp
index 1ffcecd84e..d07d9980c3 100644..100755
--- a/indra/llmessage/llbuffer.cpp
+++ b/indra/llmessage/llbuffer.cpp
@@ -4,31 +4,25 @@
* @date 2005-09-20
* @brief Implementation of the segments, buffers, and buffer arrays.
*
- * $LicenseInfo:firstyear=2005&license=viewergpl$
- *
- * Copyright (c) 2005-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,8 +30,11 @@
#include "llbuffer.h"
#include "llmath.h"
-#include "llmemtype.h"
#include "llstl.h"
+#include "llthread.h"
+#include <iterator>
+
+#define ASSERT_LLBUFFERARRAY_MUTEX_LOCKED() llassert(!mMutexp || mMutexp->isSelfLocked())
/**
* LLSegment
@@ -47,7 +44,6 @@ LLSegment::LLSegment() :
mData(NULL),
mSize(0)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
}
LLSegment::LLSegment(S32 channel, U8* data, S32 data_len) :
@@ -55,12 +51,10 @@ LLSegment::LLSegment(S32 channel, U8* data, S32 data_len) :
mData(data),
mSize(data_len)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
}
LLSegment::~LLSegment()
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
}
bool LLSegment::isOnChannel(S32 channel) const
@@ -107,7 +101,6 @@ LLHeapBuffer::LLHeapBuffer() :
mNextFree(NULL),
mReclaimedBytes(0)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
const S32 DEFAULT_HEAP_BUFFER_SIZE = 16384;
allocate(DEFAULT_HEAP_BUFFER_SIZE);
}
@@ -118,7 +111,6 @@ LLHeapBuffer::LLHeapBuffer(S32 size) :
mNextFree(NULL),
mReclaimedBytes(0)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
allocate(size);
}
@@ -128,7 +120,6 @@ LLHeapBuffer::LLHeapBuffer(const U8* src, S32 len) :
mNextFree(NULL),
mReclaimedBytes(0)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
if((len > 0) && src)
{
allocate(len);
@@ -142,7 +133,6 @@ LLHeapBuffer::LLHeapBuffer(const U8* src, S32 len) :
// virtual
LLHeapBuffer::~LLHeapBuffer()
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
delete[] mBuffer;
mBuffer = NULL;
mSize = 0;
@@ -160,7 +150,6 @@ bool LLHeapBuffer::createSegment(
S32 size,
LLSegment& segment)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
// get actual size of the segment.
S32 actual_size = llmin(size, (mSize - S32(mNextFree - mBuffer)));
@@ -192,8 +181,8 @@ bool LLHeapBuffer::reclaimSegment(const LLSegment& segment)
}
else if(mReclaimedBytes > mSize)
{
- llwarns << "LLHeapBuffer reclaimed more memory than allocated."
- << " This is probably programmer error." << llendl;
+ LL_WARNS() << "LLHeapBuffer reclaimed more memory than allocated."
+ << " This is probably programmer error." << LL_ENDL;
}
return true;
}
@@ -215,7 +204,6 @@ bool LLHeapBuffer::containsSegment(const LLSegment& segment) const
void LLHeapBuffer::allocate(S32 size)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
mReclaimedBytes = 0;
mBuffer = new U8[size];
if(mBuffer)
@@ -230,15 +218,16 @@ void LLHeapBuffer::allocate(S32 size)
* LLBufferArray
*/
LLBufferArray::LLBufferArray() :
- mNextBaseChannel(0)
+ mNextBaseChannel(0),
+ mMutexp(NULL)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
}
LLBufferArray::~LLBufferArray()
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
std::for_each(mBuffers.begin(), mBuffers.end(), DeletePointer());
+ mBuffers.clear();
+ delete mMutexp;
}
// static
@@ -249,14 +238,57 @@ LLChannelDescriptors LLBufferArray::makeChannelConsumer(
return rv;
}
+void LLBufferArray::lock()
+{
+ if(mMutexp)
+ {
+ mMutexp->lock() ;
+ }
+}
+
+void LLBufferArray::unlock()
+{
+ if(mMutexp)
+ {
+ mMutexp->unlock() ;
+ }
+}
+
+LLMutex* LLBufferArray::getMutex()
+{
+ return mMutexp ;
+}
+
+void LLBufferArray::setThreaded(bool threaded)
+{
+ if(threaded)
+ {
+ if(!mMutexp)
+ {
+ mMutexp = new LLMutex(NULL);
+ }
+ }
+ else
+ {
+ if(mMutexp)
+ {
+ delete mMutexp ;
+ mMutexp = NULL ;
+ }
+ }
+}
+
LLChannelDescriptors LLBufferArray::nextChannel()
{
LLChannelDescriptors rv(mNextBaseChannel++);
return rv;
}
+//mMutexp should be locked before calling this.
S32 LLBufferArray::capacity() const
{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+
S32 total = 0;
const_buffer_iterator_t iter = mBuffers.begin();
const_buffer_iterator_t end = mBuffers.end();
@@ -269,7 +301,8 @@ S32 LLBufferArray::capacity() const
bool LLBufferArray::append(S32 channel, const U8* src, S32 len)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
+ LLMutexLock lock(mMutexp) ;
+
std::vector<LLSegment> segments;
if(copyIntoBuffers(channel, src, len, segments))
{
@@ -279,9 +312,11 @@ bool LLBufferArray::append(S32 channel, const U8* src, S32 len)
return false;
}
+//mMutexp should be locked before calling this.
bool LLBufferArray::prepend(S32 channel, const U8* src, S32 len)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+
std::vector<LLSegment> segments;
if(copyIntoBuffers(channel, src, len, segments))
{
@@ -297,8 +332,9 @@ bool LLBufferArray::insertAfter(
const U8* src,
S32 len)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
std::vector<LLSegment> segments;
+
+ LLMutexLock lock(mMutexp) ;
if(mSegments.end() != segment)
{
++segment;
@@ -311,9 +347,11 @@ bool LLBufferArray::insertAfter(
return false;
}
+//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+
segment_iterator_t end = mSegments.end();
segment_iterator_t it = getSegment(address);
if(it == end)
@@ -341,21 +379,26 @@ LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address)
return rv;
}
+//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::beginSegment()
{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
return mSegments.begin();
}
+//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::endSegment()
{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
return mSegments.end();
}
+//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter(
U8* address,
LLSegment& segment)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
segment_iterator_t rv = mSegments.begin();
segment_iterator_t end = mSegments.end();
if(!address)
@@ -401,8 +444,10 @@ LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter(
return rv;
}
+//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address)
{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
segment_iterator_t end = mSegments.end();
if(!address)
{
@@ -420,9 +465,11 @@ LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address)
return end;
}
+//mMutexp should be locked before calling this.
LLBufferArray::const_segment_iterator_t LLBufferArray::getSegment(
U8* address) const
{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
const_segment_iterator_t end = mSegments.end();
if(!address)
{
@@ -472,6 +519,8 @@ S32 LLBufferArray::countAfter(S32 channel, U8* start) const
S32 count = 0;
S32 offset = 0;
const_segment_iterator_t it;
+
+ LLMutexLock lock(mMutexp) ;
const_segment_iterator_t end = mSegments.end();
if(start)
{
@@ -513,7 +562,6 @@ U8* LLBufferArray::readAfter(
U8* dest,
S32& len) const
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
U8* rv = start;
if(!dest || len <= 0)
{
@@ -523,6 +571,8 @@ U8* LLBufferArray::readAfter(
len = 0;
S32 bytes_to_copy = 0;
const_segment_iterator_t it;
+
+ LLMutexLock lock(mMutexp) ;
const_segment_iterator_t end = mSegments.end();
if(start)
{
@@ -574,7 +624,7 @@ U8* LLBufferArray::seek(
U8* start,
S32 delta) const
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
const_segment_iterator_t it;
const_segment_iterator_t end = mSegments.end();
U8* rv = start;
@@ -715,9 +765,12 @@ U8* LLBufferArray::seek(
return rv;
}
+//test use only
bool LLBufferArray::takeContents(LLBufferArray& source)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
+ LLMutexLock lock(mMutexp);
+ source.lock();
+
std::copy(
source.mBuffers.begin(),
source.mBuffers.end(),
@@ -729,14 +782,17 @@ bool LLBufferArray::takeContents(LLBufferArray& source)
std::back_insert_iterator<segment_list_t>(mSegments));
source.mSegments.clear();
source.mNextBaseChannel = 0;
+ source.unlock();
+
return true;
}
+//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::makeSegment(
S32 channel,
S32 len)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
// start at the end of the buffers, because it is the most likely
// to have free space.
LLSegment segment;
@@ -771,9 +827,10 @@ LLBufferArray::segment_iterator_t LLBufferArray::makeSegment(
return send;
}
+//mMutexp should be locked before calling this.
bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
// Find out which buffer contains the segment, and if it is found,
// ask it to reclaim the memory.
@@ -798,14 +855,14 @@ bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter)
return rv;
}
-
+//mMutexp should be locked before calling this.
bool LLBufferArray::copyIntoBuffers(
S32 channel,
const U8* src,
S32 len,
std::vector<LLSegment>& segments)
{
- LLMemType m1(LLMemType::MTYPE_IO_BUFFER);
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
if(!src || !len) return false;
S32 copied = 0;
LLSegment segment;