summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcoryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1998-10-14 04:09:51 +0000
committercoryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1998-10-14 04:09:51 +0000
commitbd1719144c32060fb372c01dddd85f591b0829bc (patch)
tree7c6b72b8fd8bd36c96e3ad4c3a98a00a718d5180
parenta533021684c3380d4b72a3e1df4e07c1fd453f0a (diff)
downloadATCD-bd1719144c32060fb372c01dddd85f591b0829bc.tar.gz
ChangeLogTag:Tue Oct 13 22:40:40 1998 Carlos O'Ryan <coryan@cs.wustl.edu>
-rw-r--r--ChangeLog-98b22
-rw-r--r--ace/Message_Block.cpp53
-rw-r--r--ace/Message_Block.h26
-rw-r--r--ace/Message_Block.i10
-rw-r--r--ace/Message_Block_T.cpp51
-rw-r--r--ace/Message_Block_T.h76
-rw-r--r--ace/Message_Block_T.i28
7 files changed, 247 insertions, 19 deletions
diff --git a/ChangeLog-98b b/ChangeLog-98b
index 30e7248af02..78b8f50fa70 100644
--- a/ChangeLog-98b
+++ b/ChangeLog-98b
@@ -1,3 +1,25 @@
+Tue Oct 13 22:40:40 1998 Carlos O'Ryan <coryan@cs.wustl.edu>
+
+ * ace/Makefile:
+ * ace/Message_Block.h:
+ * ace/Message_Block.i:
+ * ace/Message_Block.cpp:
+ * ace/Message_Block_T.h:
+ * ace/Message_Block_T.i:
+ * ace/Message_Block_T.cpp:
+ Added a new variant of the ACE_Data_Block class that holds an
+ instance of its locking strategy, this is useful because in some
+ cases the lifetime of the lock is tied to the lifetime of the
+ Data_Block itself.
+ The Message_Block class was carefullly modified to support this
+ new feature, i.e. it does not hold a lock while removing the
+ data block because the hold may be part of the data block
+ itself.
+ Still all the features in the Message_Blocks are supported, for
+ instance, a complete Message_Block chain ca be destroyed while
+ holding a single lock, shared by all the Data_Blocks in the
+ chain.
+
Tue Oct 13 22:39:42 1998 David L. Levine <levine@cs.wustl.edu>
* tests/MM_Shared_Memory_Test.cpp (client): added an
diff --git a/ace/Message_Block.cpp b/ace/Message_Block.cpp
index 14bdfe3dca6..65a99201b51 100644
--- a/ace/Message_Block.cpp
+++ b/ace/Message_Block.cpp
@@ -509,13 +509,12 @@ ACE_Data_Block::release_i (void)
}
ACE_Data_Block *
-ACE_Data_Block::release (ACE_Lock *lock)
+ACE_Data_Block::release_no_delete (ACE_Lock *lock)
{
- ACE_TRACE ("ACE_Data_Block::release");
+ ACE_TRACE ("ACE_Data_Block::release_no_delete");
ACE_Data_Block *result = 0;
ACE_Lock *lock_to_be_used = 0;
- ACE_Allocator *allocator = this->data_block_allocator_;
// Check if we were passed in a lock
if (lock != 0)
@@ -546,6 +545,18 @@ ACE_Data_Block::release (ACE_Lock *lock)
else
result = this->release_i ();
+ return result;
+}
+
+ACE_Data_Block *
+ACE_Data_Block::release (ACE_Lock *lock)
+{
+ ACE_TRACE ("ACE_Data_Block::release");
+
+ ACE_Allocator *allocator = this->data_block_allocator_;
+
+ ACE_Data_Block *result = this->release_no_delete (lock);
+
// We must delete this outside the scope of the locking_strategy_
// since otherwise we'd be trying to "release" through a deleted
// pointer!
@@ -560,7 +571,14 @@ ACE_Message_Block::release (void)
{
ACE_TRACE ("ACE_Message_Block::release");
- ACE_Message_Block *result = 0;
+ // We want to hold the data block in a temporary variable because we
+ // invoked "delete this;" at some point, so using this->data_block_
+ // could be a bad idea.
+ ACE_Data_Block *tmp = this->data_block ();
+
+ // This flag is set to 1 when we have to destroy the data_block
+ int destroy_dblock = 0;
+
ACE_Lock *lock = 0;
// Do we have a valid data block
@@ -576,21 +594,24 @@ ACE_Message_Block::release (void)
ACE_GUARD_RETURN (ACE_Lock, ace_mon, *lock, 0);
// Call non-guarded release with <lock>
- result = this->release_i (lock);
+ destroy_dblock = this->release_i (lock);
}
// This is the case when we have a valid data block but no lock
else
// Call non-guarded release with no lock
- result = this->release_i (0);
+ destroy_dblock = this->release_i (0);
}
else
// This is the case when we don't even have a valid data block
- result = this->release_i (0);
+ destroy_dblock = this->release_i (0);
- return result;
+ if (destroy_dblock != 0)
+ ACE_DES_FREE (tmp, tmp->data_block_allocator ()->free, ACE_Data_Block);
+
+ return 0;
}
-ACE_Message_Block *
+int
ACE_Message_Block::release_i (ACE_Lock *lock)
{
ACE_TRACE ("ACE_Message_Block::release_i");
@@ -607,23 +628,29 @@ ACE_Message_Block::release_i (ACE_Lock *lock)
mb = mb->cont_;
tmp->cont_ = 0;
- tmp->release_i (lock);
+ ACE_Data_Block *db = tmp->data_block ();
+ if (tmp->release_i (lock) != 0)
+ ACE_DES_FREE (db, db->data_block_allocator ()->free, ACE_Data_Block);
}
while (mb);
this->cont_ = 0;
}
+ int result = 0;
+
if (this->data_block ())
{
- this->data_block ()->release (lock);
+ if (this->data_block ()->release_no_delete (lock) == 0)
+ result = 1;
this->data_block_ = 0;
}
- // We will now commit suicide: this object *must* have come from the heap
+ // We will now commit suicide: this object *must* have come from the
+ // heap
delete this;
- return 0;
+ return result;
}
/* static */ ACE_Message_Block *
diff --git a/ace/Message_Block.h b/ace/Message_Block.h
index f8e823a4514..765fcfca2ca 100644
--- a/ace/Message_Block.h
+++ b/ace/Message_Block.h
@@ -350,8 +350,9 @@ private:
ACE_Allocator *data_block_allocator);
// Perform the actual initialization.
- ACE_Message_Block *release_i (ACE_Lock *lock);
+ int release_i (ACE_Lock *lock);
// Internal release implementation
+ // Returns 1 if the data block has to be destroyed.
int init_i (size_t size,
ACE_Message_Type type,
@@ -454,9 +455,12 @@ public:
// Set the total amount of space in the message. Returns 0 if
// successful, else -1.
- ACE_Data_Block *clone (ACE_Message_Block::Message_Flags mask = 0) const;
+ virtual ACE_Data_Block *clone (ACE_Message_Block::Message_Flags mask = 0) const;
// Return an exact "deep copy" of the message, i.e., create fresh
// new copies of all the Data_Blocks and continuations.
+ // Notice that Data_Blocks can act as "Prototypes", i.e. derived
+ // classes can override this method and create instances of
+ // themselves.
ACE_Data_Block *duplicate (void);
// Return a "shallow" copy that increments our reference count by 1.
@@ -479,6 +483,9 @@ public:
ACE_Message_Block::Message_Flags flags (void) const;
// Get the current message flags.
+ ACE_Allocator *allocator_strategy (void) const;
+ // Obtain the allocator strategy.
+
// = The locking strategy prevents race conditions.
ACE_Lock *locking_strategy (void);
// Get the locking strategy.
@@ -491,13 +498,22 @@ public:
int reference_count (void) const;
// Get the current reference count.
- ACE_Allocator *data_block_allocator (void);
+ ACE_Allocator *data_block_allocator (void) const;
// Get the allocator used to create this object
private:
ACE_Data_Block *release_i (void);
// Internal release implementation
+ friend class ACE_Message_Block;
+ ACE_Data_Block *release_no_delete (ACE_Lock *lock);
+ // Decrease the reference count, but don't delete the object.
+ // Returns 0 if the object should be removed.
+ // If <lock> is equal to the locking strategy then we assume that
+ // the lock is beign held by the current thread; this is used to
+ // release all the data blocks in a chain while holding a single
+ // lock.
+
ACE_Message_Block::ACE_Message_Type type_;
// Type of message.
@@ -685,10 +701,10 @@ public:
// Dump the state of the strategy.
};
-
-
#if defined (__ACE_INLINE__)
#include "ace/Message_Block.i"
#endif /* __ACE_INLINE__ */
+#include "ace/Message_Block_T.h"
+
#endif /* ACE_MESSAGE_BLOCK_H */
diff --git a/ace/Message_Block.i b/ace/Message_Block.i
index ff3f8152cb0..31f63a9a641 100644
--- a/ace/Message_Block.i
+++ b/ace/Message_Block.i
@@ -50,8 +50,9 @@ ACE_Data_Block::flags (void) const
}
ACE_INLINE ACE_Allocator*
-ACE_Data_Block::data_block_allocator (void)
+ACE_Data_Block::data_block_allocator (void) const
{
+ ACE_TRACE ("ACE_Message_Block::data_block_allocator");
return this->data_block_allocator_;
}
@@ -325,6 +326,13 @@ ACE_Message_Block::prev (void) const
return this->prev_;
}
+ACE_INLINE ACE_Allocator *
+ACE_Data_Block::allocator_strategy (void) const
+{
+ ACE_TRACE ("ACE_Data_Block::allocator_strategy");
+ return this->allocator_strategy_;
+}
+
ACE_INLINE ACE_Lock *
ACE_Data_Block::locking_strategy (void)
{
diff --git a/ace/Message_Block_T.cpp b/ace/Message_Block_T.cpp
new file mode 100644
index 00000000000..fb55ef6238c
--- /dev/null
+++ b/ace/Message_Block_T.cpp
@@ -0,0 +1,51 @@
+// $Id$
+
+#if !defined (ACE_MESSAGE_BLOCK_T_C)
+#define ACE_MESSAGE_BLOCK_T_C
+
+#define ACE_BUILD_DLL
+#include "ace/Message_Block_T.h"
+
+ACE_RCSID(ace, Message_Block_T, "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Message_Block_T.i"
+#endif /* __ACE_INLINE__ */
+
+template<class ACE_LOCK>
+ACE_Locked_Data_Block<ACE_LOCK>::~ACE_Locked_Data_Block (void)
+{
+}
+
+template<class L> ACE_Data_Block *
+ACE_Locked_Data_Block<L>::clone (ACE_Message_Block::Message_Flags mask) const
+{
+ ACE_TRACE ("ACE_Data_Block::clone");
+
+ // You always want to clear this one to prevent memory leaks but you
+ // might add some others later.
+ const ACE_Message_Block::Message_Flags always_clear =
+ ACE_Message_Block::DONT_DELETE;
+
+ ACE_Locked_Data_Block<L> *nb;
+
+ ACE_NEW_MALLOC_RETURN (nb,
+ ACE_static_cast(ACE_Locked_Data_Block<L>*,
+ this->data_block_allocator ()->malloc (sizeof (ACE_Locked_Data_Block<L>))),
+ ACE_Locked_Data_Block<L> (this->size (),
+ this->msg_type (),
+ 0,
+ this->allocator_strategy (),
+ this->flags (),
+ this->data_block_allocator ()),
+ 0);
+
+ // Copy all of the payload memory into the new object.
+ ACE_OS::memcpy (nb->base (), this->base (), this->size ());
+
+ // Set new flags minus the mask...
+ nb->clr_flags (mask | always_clear);
+ return nb;
+}
+
+#endif /* ACE_MESSAGE_BLOCK_T_C */
diff --git a/ace/Message_Block_T.h b/ace/Message_Block_T.h
new file mode 100644
index 00000000000..353ee00d23a
--- /dev/null
+++ b/ace/Message_Block_T.h
@@ -0,0 +1,76 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ace
+//
+// = FILENAME
+// Message_Block_T.h
+//
+// = AUTHOR
+// Doug Schmidt & Carlos O'Ryan
+//
+// ============================================================================
+
+#if !defined (ACE_MESSAGE_BLOCK_T_H)
+#define ACE_MESSAGE_BLOCK_T_H
+
+#include "ace/Message_Block.h"
+
+template<class ACE_LOCK>
+class ACE_Export ACE_Locked_Data_Block : public ACE_Data_Block
+{
+ // = TITLE
+ // A Data_Block with a concrete locking strategy.
+ //
+ // = DESCRIPTION
+ // Data_Blocks can be parametric on the kind of lock they use; in
+ // many cases the lifetime of the lock is tied to the lifetime of
+ // the Data_Block itself. But since Data_Blocks are reference
+ // counted it is hard for users to control the lock lifetime.
+ // This class is parametric over the kind of lock used.
+ //
+public:
+ // = Initialization and termination methods.
+ ACE_Locked_Data_Block (void);
+ // Default "do-nothing" constructor.
+
+ ACE_Locked_Data_Block (size_t size,
+ ACE_Message_Block::ACE_Message_Type msg_type,
+ const char *msg_data,
+ ACE_Allocator *allocator_strategy,
+ ACE_Message_Block::Message_Flags flags,
+ ACE_Allocator *data_block_allocator);
+ // Initialize.
+
+ virtual ~ACE_Locked_Data_Block (void);
+ // Delete all the resources held in the message.
+
+ virtual ACE_Data_Block *clone (ACE_Message_Block::Message_Flags mask = 0) const;
+ // Return an exact "deep copy" of the message, the dynamic type is
+ // ACE_Locked_Data_Block<>
+
+private:
+ ACE_LOCK lock_;
+ // The lock
+
+ // = Disallow these operations.
+ ACE_UNIMPLEMENTED_FUNC (ACE_Locked_Data_Block &operator= (const ACE_Locked_Data_Block<ACE_LOCK> &))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Locked_Data_Block (const ACE_Locked_Data_Block<ACE_LOCK> &))
+};
+
+#if defined (__ACE_INLINE__)
+#include "ace/Message_Block_T.i"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "ace/Message_Block_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Message_Block_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* ACE_MESSAGE_BLOCK_T_H */
diff --git a/ace/Message_Block_T.i b/ace/Message_Block_T.i
new file mode 100644
index 00000000000..fa4f1aba34c
--- /dev/null
+++ b/ace/Message_Block_T.i
@@ -0,0 +1,28 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Message_Block_T.i
+
+
+template<class ACE_LOCK> ACE_INLINE
+ACE_Locked_Data_Block<ACE_LOCK>::ACE_Locked_Data_Block (void)
+{
+}
+
+template<class ACE_LOCK> ACE_INLINE
+ACE_Locked_Data_Block<ACE_LOCK>::
+ACE_Locked_Data_Block (size_t size,
+ ACE_Message_Block::ACE_Message_Type msg_type,
+ const char *msg_data,
+ ACE_Allocator *allocator_strategy,
+ ACE_Message_Block::Message_Flags flags,
+ ACE_Allocator *data_block_allocator)
+ : ACE_Data_Block (size,
+ msg_type,
+ msg_data,
+ allocator_strategy,
+ &lock_,
+ flags,
+ data_block_allocator)
+{
+}