--- a/src/common/buffer.cc Wed May 28 13:59:53 2008 -0700
+++ b/src/common/buffer.cc Wed May 28 22:06:14 2008 -0700
@@ -24,10 +24,10 @@
NS_LOG_COMPONENT_DEFINE ("Buffer");
-#define LOG_INTERNAL_STATE(y) \
- NS_LOG_LOGIC (y << "start="<<m_start<<", end="<<m_end<<", zero start="<<m_zeroAreaStart<< \
- ", zero end="<<m_zeroAreaEnd<<", count="<<m_data->m_count<<", size="<<m_data->m_size<< \
- ", ownerId=" << m_ownerId << ", data owner=" << m_data->m_ownerId)
+#define LOG_INTERNAL_STATE(y) \
+NS_LOG_LOGIC (y << "start="<<m_start<<", end="<<m_end<<", zero start="<<m_zeroAreaStart<< \
+ ", zero end="<<m_zeroAreaEnd<<", count="<<m_data->m_count<<", size="<<m_data->m_size<< \
+ ", dirty start="<<m_data->m_dirtyStart<<", dirty end="<<m_data->m_dirtyEnd)
#ifdef BUFFER_HEURISTICS
#define HEURISTICS(x) x
@@ -58,10 +58,17 @@
* Each buffer which references an instance holds a count.
*/
uint32_t m_count;
- uint32_t m_ownerId;
/* the size of the m_data field below.
*/
uint32_t m_size;
+ /* offset from the start of the m_data field below to the
+ * start of the area in which user bytes were written.
+ */
+ uint32_t m_dirtyStart;
+ /* offset from the start of the m_data field below to the
+ * end of the area in which user bytes were written.
+ */
+ uint32_t m_dirtyEnd;
/* The real data buffer holds _at least_ one byte.
* Its real size is stored in the m_size field.
*/
@@ -130,7 +137,6 @@
struct BufferData *data = reinterpret_cast<struct BufferData*>(b);
data->m_size = reqSize;
data->m_count = 1;
- data->m_ownerId = 0;
return data;
}
@@ -214,15 +220,19 @@
m_start <= m_zeroAreaStart &&
m_zeroAreaStart <= m_zeroAreaEnd &&
m_zeroAreaEnd <= m_end;
+ bool dirtyOk =
+ m_start >= m_data->m_dirtyStart &&
+ m_end <= m_data->m_dirtyEnd;
bool internalSizeOk = m_end - (m_zeroAreaEnd - m_zeroAreaStart) <= m_data->m_size &&
m_start <= m_data->m_size &&
m_zeroAreaStart <= m_data->m_size;
- bool ok = m_data->m_count > 0 && offsetsOk && internalSizeOk;
+ bool ok = m_data->m_count > 0 && offsetsOk && dirtyOk && internalSizeOk;
if (!ok)
{
LOG_INTERNAL_STATE ("check " << this <<
", " << (offsetsOk?"true":"false") <<
+ ", " << (dirtyOk?"true":"false") <<
", " << (internalSizeOk?"true":"false") << " ");
}
return ok;
@@ -233,7 +243,6 @@
{
NS_LOG_FUNCTION (this << zeroSize);
m_data = Buffer::Create (0);
- m_ownerId = m_data->m_ownerId;
#ifdef BUFFER_HEURISTICS
m_start = std::min (m_data->m_size, g_recommendedStart);
m_maxZeroAreaStart = m_start;
@@ -243,12 +252,13 @@
m_zeroAreaStart = m_start;
m_zeroAreaEnd = m_zeroAreaStart + zeroSize;
m_end = m_zeroAreaEnd;
+ m_data->m_dirtyStart = m_start;
+ m_data->m_dirtyEnd = m_end;
NS_ASSERT (CheckInternalState ());
}
Buffer::Buffer (Buffer const&o)
: m_data (o.m_data),
- m_ownerId (o.m_ownerId),
#ifdef BUFFER_HEURISTICS
m_maxZeroAreaStart (o.m_zeroAreaStart),
#endif
@@ -276,7 +286,6 @@
Recycle (m_data);
}
m_data = o.m_data;
- m_ownerId = o.m_ownerId;
m_data->m_count++;
}
HEURISTICS (
@@ -340,7 +349,7 @@
NS_LOG_FUNCTION (this << start);
bool dirty;
NS_ASSERT (CheckInternalState ());
- bool isDirty = m_data->m_count > 1 && m_ownerId != m_data->m_ownerId;
+ bool isDirty = m_data->m_count > 1 && m_start > m_data->m_dirtyStart;
if (m_start >= start && !isDirty)
{
/* enough space in the buffer and not dirty.
@@ -348,11 +357,9 @@
* Before: |*****---------***|
* After: |***..---------***|
*/
- NS_ASSERT (m_data->m_count == 1 || m_ownerId == m_data->m_ownerId);
+ NS_ASSERT (m_data->m_count == 1 || m_start == m_data->m_dirtyStart);
m_start -= start;
- dirty = m_ownerId != m_data->m_ownerId;
- m_ownerId++;
- m_data->m_ownerId = m_ownerId;
+ dirty = m_start > m_data->m_dirtyStart;
HEURISTICS (g_nAddNoRealloc++);
}
else
@@ -366,7 +373,6 @@
Buffer::Recycle (m_data);
}
m_data = newData;
- m_ownerId = newData->m_ownerId;
int32_t delta = start - m_start;
m_start += delta;
@@ -380,6 +386,9 @@
HEURISTICS (g_nAddRealloc++);
}
HEURISTICS (m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart));
+ // update dirty area
+ m_data->m_dirtyStart = m_start;
+ m_data->m_dirtyEnd = m_end;
LOG_INTERNAL_STATE ("add start=" << start << ", ");
NS_ASSERT (CheckInternalState ());
return dirty;
@@ -390,7 +399,7 @@
NS_LOG_FUNCTION (this << end);
bool dirty;
NS_ASSERT (CheckInternalState ());
- bool isDirty = m_data->m_count > 1 && m_ownerId != m_data->m_ownerId;
+ bool isDirty = m_data->m_count > 1 && m_end < m_data->m_dirtyEnd;
if (GetInternalEnd () + end <= m_data->m_size && !isDirty)
{
/* enough space in buffer and not dirty
@@ -398,12 +407,10 @@
* Before: |**----*****|
* After: |**----...**|
*/
- NS_ASSERT (m_data->m_count == 1 || m_ownerId == m_data->m_ownerId);
+ NS_ASSERT (m_data->m_count == 1 || m_end == m_data->m_dirtyEnd);
m_end += end;
- dirty = m_ownerId != m_data->m_ownerId;
- m_ownerId++;
- m_data->m_ownerId = m_ownerId;
+ dirty = m_end < m_data->m_dirtyEnd;
HEURISTICS (g_nAddNoRealloc++);
}
@@ -418,7 +425,6 @@
Buffer::Recycle (m_data);
}
m_data = newData;
- m_ownerId = newData->m_ownerId;
int32_t delta = -m_start;
m_zeroAreaStart += delta;
@@ -432,6 +438,9 @@
HEURISTICS (g_nAddRealloc++);
}
HEURISTICS (m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart));
+ // update dirty area
+ m_data->m_dirtyStart = m_start;
+ m_data->m_dirtyEnd = m_end;
LOG_INTERNAL_STATE ("add end=" << end << ", ");
NS_ASSERT (CheckInternalState ());
@@ -444,7 +453,7 @@
NS_LOG_FUNCTION (this << &o);
if (m_data->m_count == 1 &&
m_end == m_zeroAreaEnd &&
- m_ownerId == m_data->m_ownerId &&
+ m_end == m_data->m_dirtyEnd &&
o.m_start == o.m_zeroAreaStart &&
o.m_zeroAreaEnd - o.m_zeroAreaStart > 0)
{
@@ -456,6 +465,7 @@
uint32_t zeroSize = o.m_zeroAreaEnd - o.m_zeroAreaStart;
m_zeroAreaEnd += zeroSize;
m_end = m_zeroAreaEnd;
+ m_data->m_dirtyEnd = m_zeroAreaEnd;
uint32_t endData = o.m_end - o.m_zeroAreaEnd;
AddAtEnd (endData);
Buffer::Iterator dst = End ();
@@ -740,6 +750,7 @@
NS_ASSERT (start.m_current <= end.m_current);
NS_ASSERT (start.m_zeroStart == end.m_zeroStart);
NS_ASSERT (start.m_zeroEnd == end.m_zeroEnd);
+ NS_ASSERT (m_data != start.m_data);
uint32_t size = end.m_current - start.m_current;
Iterator cur = start;
for (uint32_t i = 0; i < size; i++)
--- a/src/common/buffer.h Wed May 28 13:59:53 2008 -0700
+++ b/src/common/buffer.h Wed May 28 22:06:14 2008 -0700
@@ -58,13 +58,8 @@
* BufferData. If the BufferData::m_count field is one, it means that
* there exist only one instance of Buffer which references the
* BufferData instance so, it is safe to modify it. It is also
- * safe to modify the content of a BufferData if someone has not yet
- * made incompatible changes to the BufferData and we detect that
- * case when the m_ownerId field is equal to the m_ownerId of the
- * BufferData itself. Whenever a change potentially incompatible
- * with other users is made to a BufferData object, we update the
- * m_ownerId field of the BufferData to ensure that the other users
- * will detect out modification.
+ * safe to modify the content of a BufferData if the modification
+ * falls outside of the "dirty area" defined by the BufferData.
* In every other case, the BufferData must be copied before
* being modified.
*
@@ -486,13 +481,6 @@
/* This structure is described in the buffer.cc file.
*/
struct BufferData *m_data;
- /* id of the owner of the BufferData object.
- * If this id matches the id stored in the BufferData object,
- * we are the current owner of the data. If we are not the owner,
- * and we need to acquire ownership before making modifications
- * by doing a copy.
- */
- uint32_t m_ownerId;
#ifdef BUFFER_HEURISTICS
/* keep track of the maximum value of m_zeroAreaStart across
* the lifetime of a Buffer instance. This variable is used