summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkitty <kitty@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2002-09-10 19:12:37 +0000
committerkitty <kitty@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2002-09-10 19:12:37 +0000
commita219563acd6e2720f19519c2b8e5902fde3f0832 (patch)
tree06ed6c584d049775cbcffaaf09425038ed33ff64
parentf0729202a0b24c98d3782059773e7f9763223600 (diff)
downloadATCD-a219563acd6e2720f19519c2b8e5902fde3f0832.tar.gz
ChangeLogTag: Tue Sep 10 14:06:02 2002 Krishnakumar B <kitty@cs.wustl.edu>
-rw-r--r--ChangeLog21
-rw-r--r--ChangeLogs/ChangeLog-03a21
-rw-r--r--ace/Obstack_T.cpp50
-rw-r--r--ace/Obstack_T.h21
-rw-r--r--tests/Obstack_Test.cpp84
5 files changed, 169 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index 47822ae4169..ee239cc187f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+Tue Sep 10 14:06:02 2002 Krishnakumar B <kitty@cs.wustl.edu>
+
+ * ace/Obstack_T.cpp:
+ * ace/Obstack_T.h:
+
+ Obstack is no longer restricted to fixed-size chunks. Chunk size
+ is increased by a power of two if we run out of memory in a
+ chunk. Added implementation of unwind operations. Stack can be
+ unwound by giving the address of an object on the stack. Fixed a
+ couple of bugs in the existing implementation when used with
+ WCHAR. We were incrementing the pointers by sizeof (CHAR) as
+ well as multiplying by sizeof (CHAR) to get the number of bytes
+ to be copied. This improvement doesn't deal with the alignment
+ issues as it requires a change in Obchunk which is postponed
+ till ACE 5.2.3 is released.
+
+ * tests/Obstack_Test.cpp:
+
+ New, improved test which exercises all the code paths in the
+ implementation unlike the previous test.
+
Tue Sep 10 12:32:33 2002 Carlos O'Ryan <coryan@atdesk.com>
* ace/Connector.cpp:
diff --git a/ChangeLogs/ChangeLog-03a b/ChangeLogs/ChangeLog-03a
index 47822ae4169..ee239cc187f 100644
--- a/ChangeLogs/ChangeLog-03a
+++ b/ChangeLogs/ChangeLog-03a
@@ -1,3 +1,24 @@
+Tue Sep 10 14:06:02 2002 Krishnakumar B <kitty@cs.wustl.edu>
+
+ * ace/Obstack_T.cpp:
+ * ace/Obstack_T.h:
+
+ Obstack is no longer restricted to fixed-size chunks. Chunk size
+ is increased by a power of two if we run out of memory in a
+ chunk. Added implementation of unwind operations. Stack can be
+ unwound by giving the address of an object on the stack. Fixed a
+ couple of bugs in the existing implementation when used with
+ WCHAR. We were incrementing the pointers by sizeof (CHAR) as
+ well as multiplying by sizeof (CHAR) to get the number of bytes
+ to be copied. This improvement doesn't deal with the alignment
+ issues as it requires a change in Obchunk which is postponed
+ till ACE 5.2.3 is released.
+
+ * tests/Obstack_Test.cpp:
+
+ New, improved test which exercises all the code paths in the
+ implementation unlike the previous test.
+
Tue Sep 10 12:32:33 2002 Carlos O'Ryan <coryan@atdesk.com>
* ace/Connector.cpp:
diff --git a/ace/Obstack_T.cpp b/ace/Obstack_T.cpp
index 4d342c33506..cb96dd40a13 100644
--- a/ace/Obstack_T.cpp
+++ b/ace/Obstack_T.cpp
@@ -39,14 +39,12 @@ ACE_Obstack_T<CHAR>::request (size_t len)
// Check to see if there's room for the requested length, including
// any part of an existing string, if any.
- size_t resulting_len =
- ((this->curr_->cur_ - this->curr_->block_) * sizeof (CHAR)) + len;
+ size_t resulting_len = (this->curr_->cur_ - this->curr_->block_) + len;
- // We will always have enough room for null terminating char
- // unless sizeof (char) > 4.
- // There's no way we can handle more than this->size_ of strings.
+ // Increase the length of the underlying chunks if the request made is
+ // for bigger sized chunks.
if (this->size_ < resulting_len)
- return -1;
+ this->size_ = this->size_ << 1;
// We now know the request will fit; see if it can fit in the current
// chunk or will need a new one.
@@ -58,7 +56,10 @@ ACE_Obstack_T<CHAR>::request (size_t len)
if (this->curr_->next_ == 0)
{
// We must allocate new memory.
- this->curr_->next_ = this->new_chunk ();
+ ACE_Obchunk* tmp = this->new_chunk();
+ if (!tmp)
+ return -1;
+ this->curr_->next_ = tmp;
this->curr_ = this->curr_->next_;
}
else
@@ -71,11 +72,13 @@ ACE_Obstack_T<CHAR>::request (size_t len)
// Copy any initial characters to the new chunk.
if (temp->cur_ != temp->block_)
{
- size_t datasize = (temp->cur_ - temp->block_) * sizeof (CHAR);
+ size_t datasize = temp->cur_ - temp->block_;
ACE_OS::memcpy (this->curr_->block_,
temp->block_,
datasize);
this->curr_->cur_ = this->curr_->block_ + datasize;
+ // Reset the old chunk.
+ temp->cur_ = temp->block_;
}
}
@@ -142,7 +145,7 @@ ACE_Obstack_T<CHAR>::~ACE_Obstack_T (void)
{
ACE_Obchunk *next = temp->next_;
temp->next_ = 0;
- this->allocator_strategy_->free ((void *) temp);
+ this->allocator_strategy_->free (temp);
temp = next;
}
}
@@ -163,6 +166,35 @@ ACE_Obstack_T<CHAR>::copy (const CHAR *s,
}
template <class CHAR> void
+ACE_Obstack_T<CHAR>::unwind (void* obj)
+{
+ if (obj >= this->curr_->contents_ && obj < this->curr_->end_)
+ this->curr_->block_ = this->curr_->cur_ = ACE_reinterpret_cast (char*,
+ obj);
+ else
+ this->unwind_i (obj);
+}
+
+template <class CHAR> void
+ACE_Obstack_T<CHAR>::unwind_i (void* obj)
+{
+ ACE_Obchunk* curr;
+
+ curr = this->head_;
+ while (curr != 0 && (curr->contents_ > obj || curr->end_ < obj))
+ curr = curr->next_;
+ if (curr)
+ {
+ this->curr_ = curr;
+ this->curr_->block_ = this->curr_->cur_ = ACE_reinterpret_cast (char*,
+ obj);
+ }
+ else if (obj != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("Deletion of non-existent object.\n%a")));
+}
+
+template <class CHAR> void
ACE_Obstack_T<CHAR>::release (void)
{
ACE_TRACE ("ACE_Obstack_T<CHAR>::release");
diff --git a/ace/Obstack_T.h b/ace/Obstack_T.h
index 098dd5b29a4..9f4dd1f06aa 100644
--- a/ace/Obstack_T.h
+++ b/ace/Obstack_T.h
@@ -65,13 +65,22 @@ public:
CHAR *copy (const CHAR *data,
size_t len);
- /// Return the maximum @a length or @a size of a string that can be put into
- /// this Obstack. @a size = @a length * sizeof (CHAR).
+ /// Return the maximum @a length or @a size of a string that can be put
+ /// into this Obstack. @a size = @a length * sizeof (CHAR).
+ ///
+ /// Deprecated : No need to use this function as you can put objects of
+ /// arbitrary lengths into the obstack now.
size_t length (void) const;
size_t size (void) const;
- /// "Release" the entire stack of Obchunks, putting it back on the
- /// free list.
+ /// "Unwind" the stack. If @a obj is a null pointer, everything allocated
+ /// in the stack is released. Otherwise, @a obj must be an address of an
+ /// object allocated in the stack. In this case, @a obj is released along
+ /// with everthing allocated in the Obstack since @a obj.
+ void unwind (void* obj);
+
+ /// "Release" the entire stack of Obchunks, putting it back on the free
+ /// list.
void release (void);
/// Dump the state of an object.
@@ -83,6 +92,10 @@ public:
protected:
class ACE_Obchunk *new_chunk (void);
+ /// Search through the list of Obchunks and release them. Helper funtion
+ /// used by unwind.
+ void unwind_i (void* obj);
+
/// Pointer to the allocator used by this Obstack.
ACE_Allocator *allocator_strategy_;
diff --git a/tests/Obstack_Test.cpp b/tests/Obstack_Test.cpp
index 33db8816ae2..110fea4eba9 100644
--- a/tests/Obstack_Test.cpp
+++ b/tests/Obstack_Test.cpp
@@ -31,30 +31,84 @@ int ACE_TMAIN (int, ACE_TCHAR *[])
int errors = 0;
// For this test, the length of the ACE_Obstack must be larger than
// both of these strings, but less than their sum.
- const ACE_TCHAR *str1 = ACE_TEXT ("Mary had a little lamb.");
- const ACE_TCHAR *str2 = ACE_TEXT ("It's fleece was white as snow.");
- ACE_Obstack_T<ACE_TCHAR> stack (ACE_OS_String::strlen (str2) + 5);
+ const ACE_TCHAR str1[] = ACE_TEXT ("Mary had a little lamb.");
+ const ACE_TCHAR str2[] = ACE_TEXT ("It's fleece was white as snow; but....");
+ ACE_Obstack_T<ACE_TCHAR> stack (sizeof (str1) + 1);
- // This test checks to see that if a request can't be lengthened,
- // the first part of it doesn't get lost.
for (size_t i = 0; i < ACE_OS_String::strlen (str1); i++)
stack.grow_fast (str1[i]);
- if (stack.request (ACE_OS_String::strlen (str2)) == 0) {
- ACE_ERROR ((LM_ERROR,
- ACE_TEXT ("Request allowed but it should overflow\n")));
- ++errors;
- }
+
ACE_TCHAR *str = stack.freeze ();
- if (str == 0) {
+
+ if (str == 0)
+ {
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("freeze failed!\n")));
+ ++errors;
+ }
+ else if (ACE_OS_String::strcmp (str, str1) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT("Lost first string; expected: %s, have: %s\n"),
+ str1, str));
+ ++errors;
+ }
+
+ for (size_t j = 0; j < ACE_OS_String::strlen (str2); ++j)
+ stack.grow (str2[j]);
+
+ ACE_TCHAR* temp = stack.freeze();
+
+ if (temp == 0)
+ {
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("freeze failed!\n")));
+ ++errors;
+ }
+ else if (ACE_OS::strcmp (temp, str2) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT("Lost second string; expected: %s, have: %s\n"),
+ str2, temp));
+ ++errors;
+ }
+
+ for (size_t k = 0; k < ACE_OS_String::strlen (str1); ++k)
+ stack.grow (str1[k]);
+
+ ACE_TCHAR* tmp = stack.freeze ();
+ if (tmp == 0)
+ {
ACE_ERROR ((LM_ERROR, ACE_TEXT ("freeze failed!\n")));
++errors;
}
- else if (ACE_OS_String::strcmp (str, str1) != 0) {
- ACE_ERROR ((LM_ERROR, ACE_TEXT ("Lost a string; expected: %s, have: %s\n"),
- str1, str));
+ else if (ACE_OS_String::strcmp (tmp, str1) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Lost third string; expected: %s, have: %s\n"),
+ str1, tmp));
+ ++errors;
+ }
+
+ stack.unwind (temp);
+
+ for (size_t l = 0; l < ACE_OS_String::strlen (str2); ++l)
+ stack.grow (str2[l]);
+
+ temp = stack.freeze();
+
+ if (temp == 0)
+ {
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("freeze failed!\n")));
+ ++errors;
+ }
+ else if (ACE_OS::strcmp (temp, str2) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Lost fourth string; expected: %s, have: %s\n"),
+ str2, temp));
++errors;
}
- else
+
+ if (!errors)
ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Test ok\n")));
ACE_END_TEST;