diff options
author | coryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1998-10-14 04:09:51 +0000 |
---|---|---|
committer | coryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1998-10-14 04:09:51 +0000 |
commit | bd1719144c32060fb372c01dddd85f591b0829bc (patch) | |
tree | 7c6b72b8fd8bd36c96e3ad4c3a98a00a718d5180 /ace | |
parent | a533021684c3380d4b72a3e1df4e07c1fd453f0a (diff) | |
download | ATCD-bd1719144c32060fb372c01dddd85f591b0829bc.tar.gz |
ChangeLogTag:Tue Oct 13 22:40:40 1998 Carlos O'Ryan <coryan@cs.wustl.edu>
Diffstat (limited to 'ace')
-rw-r--r-- | ace/Message_Block.cpp | 53 | ||||
-rw-r--r-- | ace/Message_Block.h | 26 | ||||
-rw-r--r-- | ace/Message_Block.i | 10 | ||||
-rw-r--r-- | ace/Message_Block_T.cpp | 51 | ||||
-rw-r--r-- | ace/Message_Block_T.h | 76 | ||||
-rw-r--r-- | ace/Message_Block_T.i | 28 |
6 files changed, 225 insertions, 19 deletions
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) +{ +} |