mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2025-11-29 17:38:24 +08:00
1301 lines
42 KiB
C++
1301 lines
42 KiB
C++
#include "ace/Message_Block.h"
|
|
|
|
#if !defined (__ACE_INLINE__)
|
|
#include "ace/Message_Block.inl"
|
|
#endif /* __ACE_INLINE__ */
|
|
|
|
#include "ace/Guard_T.h"
|
|
#include "ace/Log_Category.h"
|
|
#include "ace/Malloc_Base.h"
|
|
#include "ace/OS_NS_string.h"
|
|
|
|
//#define ACE_ENABLE_TIMEPROBES
|
|
#include "ace/Timeprobe.h"
|
|
|
|
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
|
|
|
|
ACE_ALLOC_HOOK_DEFINE (ACE_Message_Block)
|
|
|
|
#if defined (ACE_ENABLE_TIMEPROBES)
|
|
|
|
static const char *ACE_MB_Timeprobe_Description[] =
|
|
{
|
|
"Message_Block::init_i - enter",
|
|
"Message_Block::init_i - leave",
|
|
"Message_Block::init_i - db alloc",
|
|
"Message_Block::init_i - db ctor",
|
|
"Data_Block::ctor[1] - enter",
|
|
"Data_Block::ctor[1] - leave",
|
|
"Data_Block::ctor[2] - enter",
|
|
"Data_Block::ctor[2] - leave",
|
|
"Data_Block::clone - enter",
|
|
"Data_Block::clone - leave"
|
|
};
|
|
|
|
enum
|
|
{
|
|
ACE_MESSAGE_BLOCK_INIT_I_ENTER = 3000,
|
|
ACE_MESSAGE_BLOCK_INIT_I_LEAVE,
|
|
ACE_MESSAGE_BLOCK_INIT_I_DB_ALLOC,
|
|
ACE_MESSAGE_BLOCK_INIT_I_DB_CTOR,
|
|
ACE_DATA_BLOCK_CTOR1_ENTER,
|
|
ACE_DATA_BLOCK_CTOR1_LEAVE,
|
|
ACE_DATA_BLOCK_CTOR2_ENTER,
|
|
ACE_DATA_BLOCK_CTOR2_LEAVE,
|
|
ACE_DATA_BLOCK_CLONE_ENTER,
|
|
ACE_DATA_BLOCK_CLONE_LEAVE
|
|
};
|
|
|
|
|
|
// Setup Timeprobes
|
|
ACE_TIMEPROBE_EVENT_DESCRIPTIONS (ACE_MB_Timeprobe_Description,
|
|
ACE_MESSAGE_BLOCK_INIT_I_ENTER);
|
|
|
|
#endif /* ACE_ENABLE_TIMEPROBES */
|
|
|
|
void
|
|
ACE_Message_Block::data_block (ACE_Data_Block *db)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::data_block");
|
|
if (ACE_BIT_DISABLED (this->flags_,
|
|
ACE_Message_Block::DONT_DELETE)
|
|
&& this->data_block_ != 0)
|
|
this->data_block_->release ();
|
|
|
|
this->data_block_ = db;
|
|
|
|
// Set the read and write pointers in the <Message_Block> to point
|
|
// to the buffer in the <ACE_Data_Block>.
|
|
this->rd_ptr (this->data_block ()->base ());
|
|
this->wr_ptr (this->data_block ()->base ());
|
|
}
|
|
|
|
int
|
|
ACE_Message_Block::copy (const char *buf, size_t n)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::copy");
|
|
|
|
/*size_t len = static_cast<size_t> (this->end () - this->wr_ptr ());*/
|
|
// Note that for this to work correct, end () *must* be >= mark ().
|
|
size_t len = this->space ();
|
|
|
|
if (len < n)
|
|
{
|
|
errno = ENOSPC;
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
(void) ACE_OS::memcpy (this->wr_ptr (),
|
|
buf,
|
|
n);
|
|
this->wr_ptr (n);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int
|
|
ACE_Message_Block::copy (const char *buf)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::copy");
|
|
|
|
/* size_t len = static_cast<size_t> (this->end () - this->wr_ptr ()); */
|
|
// Note that for this to work correct, end() *must* be >= wr_ptr().
|
|
size_t len = this->space ();
|
|
|
|
size_t buflen = ACE_OS::strlen (buf) + 1;
|
|
|
|
if (len < buflen)
|
|
{
|
|
errno = ENOSPC;
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
(void) ACE_OS::memcpy (this->wr_ptr (),
|
|
buf,
|
|
buflen);
|
|
this->wr_ptr (buflen);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int
|
|
ACE_Message_Block::crunch (void)
|
|
{
|
|
if (this->rd_ptr_ != 0)
|
|
{
|
|
if (this->rd_ptr_ > this->wr_ptr_)
|
|
return -1;
|
|
|
|
size_t const len = this->length ();
|
|
(void) ACE_OS::memmove (this->base (),
|
|
this->rd_ptr (),
|
|
len);
|
|
this->rd_ptr (this->base ());
|
|
this->wr_ptr (this->base () + len);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
ACE_Data_Block::dump (void) const
|
|
{
|
|
#if defined (ACE_HAS_DUMP)
|
|
ACE_TRACE ("ACE_Data_Block::dump");
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
|
|
ACELIB_DEBUG ((LM_DEBUG,
|
|
ACE_TEXT ("-----( Data Block )-----\n")
|
|
ACE_TEXT ("type_ = %d\n")
|
|
ACE_TEXT ("cur_size_ = %u\n")
|
|
ACE_TEXT ("max_size_ = %u\n")
|
|
ACE_TEXT ("flags_ = %u\n")
|
|
ACE_TEXT ("base_ = %@\n")
|
|
ACE_TEXT ("locking_strategy_ = %u\n")
|
|
ACE_TEXT ("reference_count_ = %u\n")
|
|
ACE_TEXT ("---------------------------\n"),
|
|
this->type_,
|
|
this->cur_size_,
|
|
this->max_size_,
|
|
this->flags_,
|
|
this->base_,
|
|
this->locking_strategy_,
|
|
this->reference_count_));
|
|
this->allocator_strategy_->dump ();
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
|
|
#endif /* ACE_HAS_DUMP */
|
|
}
|
|
|
|
void
|
|
ACE_Message_Block::dump (void) const
|
|
{
|
|
#if defined (ACE_HAS_DUMP)
|
|
ACE_TRACE ("ACE_Message_Block::dump");
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
|
|
ACELIB_DEBUG ((LM_DEBUG,
|
|
ACE_TEXT ("-----( Message Block )-----\n")
|
|
ACE_TEXT ("priority_ = %d\n")
|
|
ACE_TEXT ("next_ = %@\n")
|
|
ACE_TEXT ("prev_ = %@\n")
|
|
ACE_TEXT ("cont_ = %@\n")
|
|
ACE_TEXT ("rd_ptr_ = %@\n")
|
|
ACE_TEXT ("wr_ptr_ = %@\n")
|
|
ACE_TEXT ("---------------------------\n"),
|
|
this->priority_,
|
|
this->next_,
|
|
this->prev_,
|
|
this->cont_,
|
|
this->rd_ptr_,
|
|
this->wr_ptr_));
|
|
this->data_block ()->dump ();
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
|
|
#endif /* ACE_HAS_DUMP */
|
|
}
|
|
|
|
int
|
|
ACE_Data_Block::reference_count (void) const
|
|
{
|
|
if (this->locking_strategy_)
|
|
{
|
|
// We need to acquire the lock before retrieving the count
|
|
ACE_GUARD_RETURN (ACE_Lock, ace_mon, *this->locking_strategy_, 0);
|
|
|
|
return this->reference_count_i ();
|
|
}
|
|
|
|
return this->reference_count_i ();
|
|
}
|
|
|
|
int
|
|
ACE_Data_Block::size (size_t length)
|
|
{
|
|
ACE_TRACE ("ACE_Data_Block::size");
|
|
|
|
if (length <= this->max_size_)
|
|
this->cur_size_ = length;
|
|
else
|
|
{
|
|
// We need to resize!
|
|
char *buf = 0;
|
|
ACE_ALLOCATOR_RETURN (buf,
|
|
(char *) this->allocator_strategy_->malloc (length),
|
|
-1);
|
|
|
|
ACE_OS::memcpy (buf,
|
|
this->base_,
|
|
this->cur_size_);
|
|
if (ACE_BIT_DISABLED (this->flags_,
|
|
ACE_Message_Block::DONT_DELETE))
|
|
this->allocator_strategy_->free ((void *) this->base_);
|
|
else
|
|
// We now assume ownership.
|
|
ACE_CLR_BITS (this->flags_,
|
|
ACE_Message_Block::DONT_DELETE);
|
|
this->max_size_ = length;
|
|
this->cur_size_ = length;
|
|
this->base_ = buf;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ACE_Message_Block::size (size_t length)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::size");
|
|
|
|
// Resize the underlying <ACE_Data_Block>.
|
|
if (this->data_block ()->size (length) == -1)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
ACE_Message_Block::total_size_and_length (size_t &mb_size,
|
|
size_t &mb_length) const
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::total_size_and_length");
|
|
|
|
for (const ACE_Message_Block *i = this;
|
|
i != 0;
|
|
i = i->cont ())
|
|
{
|
|
mb_size += i->size ();
|
|
mb_length += i->length ();
|
|
}
|
|
}
|
|
|
|
size_t
|
|
ACE_Message_Block::total_size (void) const
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::total_size");
|
|
|
|
size_t size = 0;
|
|
for (const ACE_Message_Block *i = this;
|
|
i != 0;
|
|
i = i->cont ())
|
|
size += i->size ();
|
|
|
|
return size;
|
|
}
|
|
|
|
size_t
|
|
ACE_Message_Block::total_length (void) const
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::total_length");
|
|
|
|
size_t length = 0;
|
|
for (const ACE_Message_Block *i = this;
|
|
i != 0;
|
|
i = i->cont ())
|
|
length += i->length ();
|
|
|
|
return length;
|
|
}
|
|
|
|
size_t
|
|
ACE_Message_Block::total_capacity (void) const
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::total_capacity");
|
|
|
|
size_t size = 0;
|
|
|
|
for (const ACE_Message_Block *i = this;
|
|
i != 0;
|
|
i = i->cont ())
|
|
size += i->capacity ();
|
|
|
|
return size;
|
|
}
|
|
|
|
ACE_Data_Block::ACE_Data_Block (void)
|
|
: type_ (ACE_Message_Block::MB_DATA),
|
|
cur_size_ (0),
|
|
max_size_ (0),
|
|
flags_ (ACE_Message_Block::DONT_DELETE),
|
|
base_ (0),
|
|
allocator_strategy_ (0),
|
|
locking_strategy_ (0),
|
|
reference_count_ (1),
|
|
data_block_allocator_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_Data_Block::ACE_Data_Block");
|
|
ACE_FUNCTION_TIMEPROBE (ACE_DATA_BLOCK_CTOR1_ENTER);
|
|
|
|
ACE_ALLOCATOR (this->allocator_strategy_,
|
|
ACE_Allocator::instance ());
|
|
|
|
ACE_ALLOCATOR (this->data_block_allocator_,
|
|
ACE_Allocator::instance ());
|
|
}
|
|
|
|
ACE_Data_Block::ACE_Data_Block (size_t size,
|
|
ACE_Message_Block::ACE_Message_Type msg_type,
|
|
const char *msg_data,
|
|
ACE_Allocator *allocator_strategy,
|
|
ACE_Lock *locking_strategy,
|
|
ACE_Message_Block::Message_Flags flags,
|
|
ACE_Allocator *data_block_allocator)
|
|
: type_ (msg_type),
|
|
cur_size_ (0), // Reset later if memory alloc'd ok
|
|
max_size_ (0),
|
|
flags_ (flags),
|
|
base_ (const_cast <char *> (msg_data)),
|
|
allocator_strategy_ (allocator_strategy),
|
|
locking_strategy_ (locking_strategy),
|
|
reference_count_ (1),
|
|
data_block_allocator_ (data_block_allocator)
|
|
{
|
|
ACE_TRACE ("ACE_Data_Block::ACE_Data_Block");
|
|
ACE_FUNCTION_TIMEPROBE (ACE_DATA_BLOCK_CTOR2_ENTER);
|
|
|
|
// If the user didn't pass one in, let's use the
|
|
// <ACE_Allocator::instance>.
|
|
if (this->allocator_strategy_ == 0)
|
|
ACE_ALLOCATOR (this->allocator_strategy_,
|
|
ACE_Allocator::instance ());
|
|
|
|
if (this->data_block_allocator_ == 0)
|
|
ACE_ALLOCATOR (this->data_block_allocator_,
|
|
ACE_Allocator::instance ());
|
|
|
|
if (msg_data == 0)
|
|
{
|
|
ACE_ALLOCATOR (this->base_,
|
|
(char *) this->allocator_strategy_->malloc (size));
|
|
#if defined (ACE_INITIALIZE_MEMORY_BEFORE_USE)
|
|
(void) ACE_OS::memset (this->base_,
|
|
'\0',
|
|
size);
|
|
#endif /* ACE_INITIALIZE_MEMORY_BEFORE_USE */
|
|
}
|
|
|
|
// ACE_ALLOCATOR returns on alloc failure but we cant throw, so setting
|
|
// the size to 0 (i.e. "bad bit") ...
|
|
if (this->base_ == 0)
|
|
{
|
|
size = 0;
|
|
}
|
|
|
|
// The memory is legit, whether passed in or allocated, so set
|
|
// the size.
|
|
this->cur_size_ = this->max_size_ = size;
|
|
}
|
|
|
|
ACE_Message_Block::ACE_Message_Block (const char *data,
|
|
size_t size,
|
|
unsigned long priority)
|
|
: flags_ (0),
|
|
data_block_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
|
|
|
|
if (this->init_i (size, // size
|
|
MB_DATA, // type
|
|
0, // cont
|
|
data, // data
|
|
0, // allocator
|
|
0, // locking strategy
|
|
ACE_Message_Block::DONT_DELETE, // flags
|
|
priority, // priority
|
|
ACE_Time_Value::zero, // execution time
|
|
ACE_Time_Value::max_time, // absolute time of deadline
|
|
0, // data block
|
|
0, // data_block allocator
|
|
0) == -1) // message_block allocator
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("ACE_Message_Block")));
|
|
}
|
|
|
|
ACE_Message_Block::ACE_Message_Block (ACE_Allocator *message_block_allocator)
|
|
: flags_ (0),
|
|
data_block_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
|
|
|
|
if (this->init_i (0, // size
|
|
MB_DATA, // type
|
|
0, // cont
|
|
0, // data
|
|
0, // allocator
|
|
0, // locking strategy
|
|
ACE_Message_Block::DONT_DELETE, // flags
|
|
0, // priority
|
|
ACE_Time_Value::zero, // execution time
|
|
ACE_Time_Value::max_time, // absolute time of deadline
|
|
0, // data block
|
|
0, // data_block allocator
|
|
message_block_allocator) == -1) // message_block allocator
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("ACE_Message_Block")));
|
|
}
|
|
|
|
ACE_Message_Block::ACE_Message_Block (size_t size,
|
|
ACE_Message_Type msg_type,
|
|
ACE_Message_Block *msg_cont,
|
|
const char *msg_data,
|
|
ACE_Allocator *allocator_strategy,
|
|
ACE_Lock *locking_strategy,
|
|
unsigned long priority,
|
|
const ACE_Time_Value &execution_time,
|
|
const ACE_Time_Value &deadline_time,
|
|
ACE_Allocator *data_block_allocator,
|
|
ACE_Allocator *message_block_allocator)
|
|
:flags_ (0),
|
|
data_block_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
|
|
|
|
if (this->init_i (size,
|
|
msg_type,
|
|
msg_cont,
|
|
msg_data,
|
|
allocator_strategy,
|
|
locking_strategy,
|
|
msg_data ? ACE_Message_Block::DONT_DELETE : 0,
|
|
priority,
|
|
execution_time,
|
|
deadline_time,
|
|
0, // data block
|
|
data_block_allocator,
|
|
message_block_allocator) == -1)
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("ACE_Message_Block")));
|
|
}
|
|
|
|
int
|
|
ACE_Message_Block::init (size_t size,
|
|
ACE_Message_Type msg_type,
|
|
ACE_Message_Block *msg_cont,
|
|
const char *msg_data,
|
|
ACE_Allocator *allocator_strategy,
|
|
ACE_Lock *locking_strategy,
|
|
unsigned long priority,
|
|
const ACE_Time_Value &execution_time,
|
|
const ACE_Time_Value &deadline_time,
|
|
ACE_Allocator *data_block_allocator,
|
|
ACE_Allocator *message_block_allocator)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::init");
|
|
|
|
return this->init_i (size,
|
|
msg_type,
|
|
msg_cont,
|
|
msg_data,
|
|
allocator_strategy,
|
|
locking_strategy,
|
|
msg_data ? ACE_Message_Block::DONT_DELETE : 0,
|
|
priority,
|
|
execution_time,
|
|
deadline_time,
|
|
0, // data block
|
|
data_block_allocator,
|
|
message_block_allocator);
|
|
}
|
|
|
|
int
|
|
ACE_Message_Block::init (const char *data,
|
|
size_t size)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::init");
|
|
// Should we also initialize all the other fields, as well?
|
|
|
|
return this->init_i (size, // size
|
|
MB_DATA, // type
|
|
0, // cont
|
|
data, // data
|
|
0, // allocator
|
|
0, // locking strategy
|
|
ACE_Message_Block::DONT_DELETE, // flags
|
|
0, // priority
|
|
ACE_Time_Value::zero, // execution time
|
|
ACE_Time_Value::max_time, // absolute time of deadline
|
|
0, // data block
|
|
0, // data_block allocator
|
|
0); // message_block allocator
|
|
}
|
|
|
|
ACE_Message_Block::ACE_Message_Block (size_t size,
|
|
ACE_Message_Type msg_type,
|
|
ACE_Message_Block *msg_cont,
|
|
const char *msg_data,
|
|
ACE_Allocator *allocator_strategy,
|
|
ACE_Lock *locking_strategy,
|
|
Message_Flags flags,
|
|
unsigned long priority,
|
|
const ACE_Time_Value &execution_time,
|
|
const ACE_Time_Value &deadline_time,
|
|
ACE_Data_Block *db,
|
|
ACE_Allocator *data_block_allocator,
|
|
ACE_Allocator *message_block_allocator)
|
|
: flags_ (0),
|
|
data_block_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
|
|
|
|
if (this->init_i (size,
|
|
msg_type,
|
|
msg_cont,
|
|
msg_data,
|
|
allocator_strategy,
|
|
locking_strategy,
|
|
flags,
|
|
priority,
|
|
execution_time,
|
|
deadline_time,
|
|
db,
|
|
data_block_allocator,
|
|
message_block_allocator) == -1)
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("ACE_Message_Block")));
|
|
}
|
|
|
|
ACE_Message_Block::ACE_Message_Block (ACE_Data_Block *data_block,
|
|
ACE_Message_Block::Message_Flags flags,
|
|
ACE_Allocator *message_block_allocator)
|
|
: flags_ (flags),
|
|
data_block_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
|
|
|
|
if (this->init_i (0, // size
|
|
MB_NORMAL, // type
|
|
0, // cont
|
|
0, // data
|
|
0, // allocator
|
|
0, // locking strategy
|
|
0, // flags
|
|
0, // priority
|
|
ACE_Time_Value::zero, // execution time
|
|
ACE_Time_Value::max_time, // absolute time of deadline
|
|
data_block, // data block
|
|
data_block->data_block_allocator (),
|
|
message_block_allocator) == -1)
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("ACE_Message_Block")));
|
|
}
|
|
|
|
ACE_Message_Block::ACE_Message_Block (const ACE_Message_Block &mb,
|
|
size_t align)
|
|
:flags_ (0),
|
|
data_block_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
|
|
|
|
if (ACE_BIT_DISABLED (mb.flags_,
|
|
ACE_Message_Block::DONT_DELETE))
|
|
{
|
|
if (this->init_i (0, // size
|
|
MB_NORMAL, // type
|
|
0, // cont
|
|
0, // data
|
|
0, // allocator
|
|
0, // locking strategy
|
|
0, // flags
|
|
0, // priority
|
|
ACE_Time_Value::zero, // execution time
|
|
ACE_Time_Value::max_time, // absolute time of deadline
|
|
mb.data_block ()->duplicate (), // data block
|
|
mb.data_block ()->data_block_allocator (),
|
|
mb.message_block_allocator_) == -1)
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("ACE_Message_Block")));
|
|
#if !defined (ACE_LACKS_CDR_ALIGNMENT)
|
|
// Align ourselves
|
|
char *start = ACE_ptr_align_binary (this->base (),
|
|
align);
|
|
#else
|
|
char *start = this->base ();
|
|
#endif /* ACE_LACKS_CDR_ALIGNMENT */
|
|
|
|
// Set our rd & wr pointers
|
|
this->rd_ptr (start);
|
|
this->wr_ptr (start);
|
|
|
|
}
|
|
else
|
|
{
|
|
if (this->init_i (0, // size
|
|
MB_NORMAL, // type
|
|
0, // cont
|
|
0, // data
|
|
0, // allocator
|
|
0, // locking strategy
|
|
0, // flags
|
|
0, // priority
|
|
ACE_Time_Value::zero, // execution time
|
|
ACE_Time_Value::max_time, // absolute time of deadline
|
|
mb.data_block ()->clone_nocopy (),// data block
|
|
mb.data_block ()->data_block_allocator (),
|
|
mb.message_block_allocator_) == -1)
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("ACE_Message_Block")));
|
|
|
|
#if !defined (ACE_LACKS_CDR_ALIGNMENT)
|
|
// Align ourselves
|
|
char *start = ACE_ptr_align_binary (this->base (),
|
|
align);
|
|
#else
|
|
char *start = this->base ();
|
|
#endif /* ACE_LACKS_CDR_ALIGNMENT */
|
|
|
|
// Set our rd & wr pointers
|
|
this->rd_ptr (start);
|
|
this->wr_ptr (start);
|
|
|
|
#if !defined (ACE_LACKS_CDR_ALIGNMENT)
|
|
// Get the alignment offset of the incoming ACE_Message_Block
|
|
start = ACE_ptr_align_binary (mb.base (),
|
|
align);
|
|
#else
|
|
start = mb.base ();
|
|
#endif /* ACE_LACKS_CDR_ALIGNMENT */
|
|
|
|
// Actual offset for the incoming message block assuming that it
|
|
// is also aligned to the same "align" byte
|
|
size_t const wr_offset = mb.wr_ptr_ - (start - mb.base ());
|
|
|
|
// Copy wr_offset amount of data in to <this->data_block>
|
|
(void) ACE_OS::memcpy (this->wr_ptr (),
|
|
start,
|
|
wr_offset);
|
|
|
|
// Dont move the write pointer, just leave it to the application
|
|
// to do what it wants
|
|
|
|
}
|
|
#if defined (ACE_LACKS_CDR_ALIGNMENT)
|
|
ACE_UNUSED_ARG (align);
|
|
#endif /* ACE_LACKS_CDR_ALIGNMENT */
|
|
}
|
|
|
|
int
|
|
ACE_Message_Block::init_i (size_t size,
|
|
ACE_Message_Type msg_type,
|
|
ACE_Message_Block *msg_cont,
|
|
const char *msg_data,
|
|
ACE_Allocator *allocator_strategy,
|
|
ACE_Lock *locking_strategy,
|
|
Message_Flags flags,
|
|
unsigned long priority,
|
|
const ACE_Time_Value &execution_time,
|
|
const ACE_Time_Value &deadline_time,
|
|
ACE_Data_Block *db,
|
|
ACE_Allocator *data_block_allocator,
|
|
ACE_Allocator *message_block_allocator)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::init_i");
|
|
ACE_FUNCTION_TIMEPROBE (ACE_MESSAGE_BLOCK_INIT_I_ENTER);
|
|
|
|
this->rd_ptr_ = 0;
|
|
this->wr_ptr_ = 0;
|
|
this->priority_ = priority;
|
|
#if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
|
|
this->execution_time_ = execution_time;
|
|
this->deadline_time_ = deadline_time;
|
|
#else
|
|
ACE_UNUSED_ARG (execution_time);
|
|
ACE_UNUSED_ARG (deadline_time);
|
|
#endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
|
|
this->cont_ = msg_cont;
|
|
this->next_ = 0;
|
|
this->prev_ = 0;
|
|
|
|
this->message_block_allocator_ = message_block_allocator;
|
|
|
|
if (this->data_block_ != 0)
|
|
{
|
|
this->data_block_->release ();
|
|
this->data_block_ = 0;
|
|
}
|
|
|
|
if (db == 0)
|
|
{
|
|
if (data_block_allocator == 0)
|
|
ACE_ALLOCATOR_RETURN (data_block_allocator,
|
|
ACE_Allocator::instance (),
|
|
-1);
|
|
|
|
ACE_TIMEPROBE (ACE_MESSAGE_BLOCK_INIT_I_DB_ALLOC);
|
|
|
|
// Allocate the <ACE_Data_Block> portion, which is reference
|
|
// counted.
|
|
ACE_NEW_MALLOC_RETURN (db,
|
|
static_cast<ACE_Data_Block *> (
|
|
data_block_allocator->malloc (sizeof (ACE_Data_Block))),
|
|
ACE_Data_Block (size,
|
|
msg_type,
|
|
msg_data,
|
|
allocator_strategy,
|
|
locking_strategy,
|
|
flags,
|
|
data_block_allocator),
|
|
-1);
|
|
ACE_TIMEPROBE (ACE_MESSAGE_BLOCK_INIT_I_DB_CTOR);
|
|
|
|
// Message block initialization may fail, while the construction
|
|
// succeds. Since ACE may throw no exceptions, we have to do a
|
|
// separate check and clean up, like this:
|
|
if (db != 0 && db->size () < size)
|
|
{
|
|
db->ACE_Data_Block::~ACE_Data_Block(); // placement destructor ...
|
|
data_block_allocator->free (db); // free ...
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// Reset the data_block_ pointer.
|
|
this->data_block (db);
|
|
|
|
return 0;
|
|
}
|
|
|
|
ACE_Data_Block::~ACE_Data_Block (void)
|
|
{
|
|
// Sanity check...
|
|
ACE_ASSERT (this->reference_count_ <= 1);
|
|
|
|
// Just to be safe...
|
|
this->reference_count_ = 0;
|
|
|
|
if (ACE_BIT_DISABLED (this->flags_,
|
|
ACE_Message_Block::DONT_DELETE))
|
|
{
|
|
this->allocator_strategy_->free ((void *) this->base_);
|
|
this->base_ = 0;
|
|
}
|
|
}
|
|
|
|
ACE_Data_Block *
|
|
ACE_Data_Block::release_i (void)
|
|
{
|
|
ACE_TRACE ("ACE_Data_Block::release_i");
|
|
|
|
ACE_ASSERT (this->reference_count_ > 0);
|
|
|
|
ACE_Data_Block *result = 0;
|
|
|
|
// decrement reference count
|
|
--this->reference_count_;
|
|
|
|
if (this->reference_count_ == 0)
|
|
// this will cause deletion of this
|
|
result = 0;
|
|
else
|
|
result = this;
|
|
|
|
return result;
|
|
}
|
|
|
|
ACE_Data_Block *
|
|
ACE_Data_Block::release_no_delete (ACE_Lock *lock)
|
|
{
|
|
ACE_TRACE ("ACE_Data_Block::release_no_delete");
|
|
|
|
ACE_Data_Block *result = 0;
|
|
ACE_Lock *lock_to_be_used = 0;
|
|
|
|
// Check if we were passed in a lock
|
|
if (lock != 0)
|
|
{
|
|
// Make sure that the lock passed in and our lock are the same
|
|
if (lock == this->locking_strategy_)
|
|
// In this case no locking is required.
|
|
lock_to_be_used = 0;
|
|
|
|
// The lock passed in does not match our lock
|
|
else
|
|
// Lock to be used is our lock
|
|
lock_to_be_used = this->locking_strategy_;
|
|
}
|
|
// This is the case when no lock was passed in
|
|
else
|
|
{
|
|
// Lock to be used is our lock
|
|
lock_to_be_used = this->locking_strategy_;
|
|
}
|
|
|
|
// If there's a locking strategy then we need to acquire the lock
|
|
// before decrementing the count.
|
|
if (lock_to_be_used != 0)
|
|
{
|
|
ACE_GUARD_RETURN (ACE_Lock, ace_mon, *lock_to_be_used, 0);
|
|
|
|
result = this->release_i ();
|
|
}
|
|
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!
|
|
if (result == 0)
|
|
ACE_DES_FREE (this,
|
|
allocator->free,
|
|
ACE_Data_Block);
|
|
return result;
|
|
}
|
|
|
|
ACE_Message_Block *
|
|
ACE_Message_Block::release (void)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::release");
|
|
|
|
// 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
|
|
if (this->data_block ())
|
|
{
|
|
// Grab the lock that belongs to my data block
|
|
lock = this->data_block ()->locking_strategy ();
|
|
|
|
// if we have a lock
|
|
if (lock != 0)
|
|
{
|
|
// One guard for all
|
|
ACE_GUARD_RETURN (ACE_Lock, ace_mon, *lock, 0);
|
|
|
|
// Call non-guarded release with @a 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
|
|
destroy_dblock = this->release_i (0);
|
|
}
|
|
else
|
|
// This is the case when we don't even have a valid data block
|
|
destroy_dblock = this->release_i (0);
|
|
|
|
if (destroy_dblock != 0)
|
|
{
|
|
ACE_Allocator *allocator = tmp->data_block_allocator ();
|
|
ACE_DES_FREE (tmp,
|
|
allocator->free,
|
|
ACE_Data_Block);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ACE_Message_Block::release_i (ACE_Lock *lock)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::release_i");
|
|
|
|
// Free up all the continuation messages.
|
|
if (this->cont_)
|
|
{
|
|
ACE_Message_Block *mb = this->cont_;
|
|
ACE_Message_Block *tmp = 0;
|
|
|
|
do
|
|
{
|
|
tmp = mb;
|
|
mb = mb->cont_;
|
|
tmp->cont_ = 0;
|
|
|
|
ACE_Data_Block *db = tmp->data_block ();
|
|
if (tmp->release_i (lock) != 0)
|
|
{
|
|
ACE_Allocator *allocator = db->data_block_allocator ();
|
|
ACE_DES_FREE (db,
|
|
allocator->free,
|
|
ACE_Data_Block);
|
|
}
|
|
}
|
|
while (mb);
|
|
|
|
this->cont_ = 0;
|
|
}
|
|
|
|
int result = 0;
|
|
|
|
if (ACE_BIT_DISABLED (this->flags_,
|
|
ACE_Message_Block::DONT_DELETE) &&
|
|
this->data_block ())
|
|
{
|
|
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
|
|
// allocator given.
|
|
if (this->message_block_allocator_ == 0)
|
|
delete this;
|
|
else
|
|
{
|
|
ACE_Allocator *allocator = this->message_block_allocator_;
|
|
ACE_DES_FREE (this,
|
|
allocator->free,
|
|
ACE_Message_Block);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* static */ ACE_Message_Block *
|
|
ACE_Message_Block::release (ACE_Message_Block *mb)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::release");
|
|
|
|
if (mb != 0)
|
|
return mb->release ();
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
ACE_Message_Block::~ACE_Message_Block (void)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::~ACE_Message_Block");
|
|
|
|
if (ACE_BIT_DISABLED (this->flags_,
|
|
ACE_Message_Block::DONT_DELETE)&&
|
|
this->data_block ())
|
|
this->data_block ()->release ();
|
|
|
|
this->prev_ = 0;
|
|
this->next_ = 0;
|
|
this->cont_ = 0;
|
|
}
|
|
|
|
ACE_Data_Block *
|
|
ACE_Data_Block::duplicate (void)
|
|
{
|
|
ACE_TRACE ("ACE_Data_Block::duplicate");
|
|
|
|
// Create a new <ACE_Message_Block>, but share the <base_> pointer
|
|
// data (i.e., don't copy that).
|
|
if (this->locking_strategy_)
|
|
{
|
|
// We need to acquire the lock before incrementing the count.
|
|
ACE_GUARD_RETURN (ACE_Lock, ace_mon, *this->locking_strategy_, 0);
|
|
++this->reference_count_;
|
|
}
|
|
else
|
|
++this->reference_count_;
|
|
|
|
return this;
|
|
}
|
|
|
|
#if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
|
|
#define ACE_EXECUTION_TIME this->execution_time_
|
|
#define ACE_DEADLINE_TIME this->deadline_time_
|
|
#else
|
|
#define ACE_EXECUTION_TIME ACE_Time_Value::zero
|
|
#define ACE_DEADLINE_TIME ACE_Time_Value::max_time
|
|
#endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
|
|
|
|
ACE_Message_Block *
|
|
ACE_Message_Block::duplicate (void) const
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::duplicate");
|
|
|
|
ACE_Message_Block *nb_top = 0;
|
|
ACE_Message_Block *nb = 0;
|
|
|
|
const ACE_Message_Block *current = this;
|
|
|
|
// Increment the reference counts of all the continuation messages.
|
|
while (current)
|
|
{
|
|
ACE_Message_Block* cur_dup = 0;
|
|
|
|
// Create a new <ACE_Message_Block> that contains unique copies of
|
|
// the message block fields, but a reference counted duplicate of
|
|
// the <ACE_Data_Block>.
|
|
|
|
// If there is no allocator, use the standard new and delete calls.
|
|
if (current->message_block_allocator_ == 0)
|
|
ACE_NEW_NORETURN (cur_dup,
|
|
ACE_Message_Block (0, // size
|
|
ACE_Message_Type (0), // type
|
|
0, // cont
|
|
0, // data
|
|
0, // allocator
|
|
0, // locking strategy
|
|
0, // flags
|
|
current->priority_, // priority
|
|
ACE_EXECUTION_TIME,
|
|
ACE_DEADLINE_TIME,
|
|
// Get a pointer to a
|
|
// "duplicated" <ACE_Data_Block>
|
|
// (will simply increment the
|
|
// reference count).
|
|
current->data_block ()->duplicate (),
|
|
current->data_block ()->data_block_allocator (),
|
|
current->message_block_allocator_));
|
|
else // Otherwise, use the message_block_allocator passed in.
|
|
ACE_NEW_MALLOC_NORETURN (cur_dup,
|
|
static_cast<ACE_Message_Block*> (
|
|
current->message_block_allocator_->malloc (sizeof (ACE_Message_Block))),
|
|
ACE_Message_Block (0, // size
|
|
ACE_Message_Type (0), // type
|
|
0, // cont
|
|
0, // data
|
|
0, // allocator
|
|
0, // locking strategy
|
|
0, // flags
|
|
current->priority_, // priority
|
|
ACE_EXECUTION_TIME,
|
|
ACE_DEADLINE_TIME,
|
|
// Get a pointer to a
|
|
// "duplicated" <ACE_Data_Block>
|
|
// (will simply increment the
|
|
// reference count).
|
|
current->data_block ()->duplicate (),
|
|
current->data_block ()->data_block_allocator (),
|
|
current->message_block_allocator_));
|
|
|
|
|
|
// If allocation failed above, release everything done so far and return NULL
|
|
if (cur_dup == 0)
|
|
{
|
|
if (nb_top != 0)
|
|
{
|
|
nb_top->release ();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Set the read and write pointers in the new <Message_Block> to the
|
|
// same relative offset as in the existing <Message_Block>. Note
|
|
// that we are assuming that the data_block()->base() pointer
|
|
// doesn't change when it's duplicated.
|
|
cur_dup->rd_ptr (current->rd_ptr_);
|
|
cur_dup->wr_ptr (current->wr_ptr_);
|
|
|
|
if (!nb)
|
|
{
|
|
/* First in the list: set leading pointers */
|
|
nb_top = nb = cur_dup;
|
|
}
|
|
else
|
|
{
|
|
/* Continuing on: append to nb and walk down the list */
|
|
nb->cont_ = cur_dup;
|
|
nb = nb->cont_;
|
|
}
|
|
|
|
current = current->cont_;
|
|
}
|
|
|
|
return nb_top;
|
|
}
|
|
|
|
ACE_Message_Block *
|
|
ACE_Message_Block::duplicate (const ACE_Message_Block *mb)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::duplicate");
|
|
if (mb == 0)
|
|
return 0;
|
|
else
|
|
return mb->duplicate ();
|
|
}
|
|
|
|
ACE_Data_Block *
|
|
ACE_Data_Block::clone (ACE_Message_Block::Message_Flags mask) const
|
|
{
|
|
ACE_TRACE ("ACE_Data_Block::clone");
|
|
|
|
ACE_Data_Block *nb = this->clone_nocopy (mask);
|
|
|
|
// Copy all of the payload memory into the new object. The new block
|
|
// was allocated with max_size_ (and, thus, it's cur_size_ is the same
|
|
// as max_size_). Maintain the same "has been written" boundary in the
|
|
// new block by only copying cur_size_ bytes.
|
|
if (nb != 0)
|
|
{
|
|
ACE_OS::memcpy (nb->base_,
|
|
this->base_,
|
|
this->cur_size_);
|
|
}
|
|
|
|
return nb;
|
|
}
|
|
|
|
ACE_Data_Block *
|
|
ACE_Data_Block::clone_nocopy (ACE_Message_Block::Message_Flags mask,
|
|
size_t max_size) const
|
|
{
|
|
ACE_FUNCTION_TIMEPROBE(ACE_DATA_BLOCK_CLONE_ENTER);
|
|
|
|
ACE_TRACE ("ACE_Data_Block::clone_nocopy");
|
|
|
|
// 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;
|
|
|
|
const size_t newsize =
|
|
max_size == 0 ? this->max_size_ : max_size;
|
|
|
|
ACE_Data_Block *nb = 0;
|
|
|
|
ACE_NEW_MALLOC_RETURN (nb,
|
|
static_cast<ACE_Data_Block*> (
|
|
this->data_block_allocator_->malloc (sizeof (ACE_Data_Block))),
|
|
ACE_Data_Block (newsize, // size
|
|
this->type_, // type
|
|
0, // data
|
|
this->allocator_strategy_, // allocator
|
|
this->locking_strategy_, // locking strategy
|
|
this->flags_, // flags
|
|
this->data_block_allocator_),
|
|
0);
|
|
|
|
// Message block initialization may fail while the construction
|
|
// succeds. Since as a matter of policy, ACE may throw no
|
|
// exceptions, we have to do a separate check like this.
|
|
if (nb != 0 && nb->size () < newsize)
|
|
{
|
|
nb->ACE_Data_Block::~ACE_Data_Block(); // placement destructor ...
|
|
this->data_block_allocator_->free (nb); // free ...
|
|
errno = ENOMEM;
|
|
return 0;
|
|
}
|
|
|
|
|
|
// Set new flags minus the mask...
|
|
nb->clr_flags (mask | always_clear);
|
|
return nb;
|
|
}
|
|
|
|
ACE_Message_Block *
|
|
ACE_Message_Block::clone (Message_Flags mask) const
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::clone");
|
|
|
|
const ACE_Message_Block *old_message_block = this;
|
|
ACE_Message_Block *new_message_block = 0;
|
|
ACE_Message_Block *new_previous_message_block = 0;
|
|
ACE_Message_Block *new_root_message_block = 0;
|
|
|
|
do
|
|
{
|
|
// Get a pointer to a "cloned"<ACE_Data_Block> (will copy the
|
|
// values rather than increment the reference count).
|
|
ACE_Data_Block *db = old_message_block->data_block ()->clone (mask);
|
|
|
|
if (db == 0)
|
|
return 0;
|
|
|
|
if(old_message_block->message_block_allocator_ == 0)
|
|
{
|
|
ACE_NEW_RETURN (new_message_block,
|
|
ACE_Message_Block (0, // size
|
|
ACE_Message_Type (0), // type
|
|
0, // cont
|
|
0, // data
|
|
0, // allocator
|
|
0, // locking strategy
|
|
0, // flags
|
|
old_message_block->priority_, // priority
|
|
ACE_EXECUTION_TIME, // execution time
|
|
ACE_DEADLINE_TIME, // absolute time to deadline
|
|
// Get a pointer to a
|
|
// "duplicated"<ACE_Data_Block>
|
|
// (will simply increment the
|
|
// reference count).
|
|
db,
|
|
db->data_block_allocator (),
|
|
old_message_block->message_block_allocator_),
|
|
0);
|
|
}
|
|
else
|
|
{
|
|
// This is the ACE_NEW_MALLOC macro with the return check removed.
|
|
// We need to do it this way because if it fails we need to release
|
|
// the cloned data block that was created above. If we used
|
|
// ACE_NEW_MALLOC_RETURN, there would be a memory leak because the
|
|
// above db pointer would be left dangling.
|
|
new_message_block = static_cast<ACE_Message_Block*> (old_message_block->message_block_allocator_->malloc (sizeof (ACE_Message_Block)));
|
|
if (new_message_block != 0)
|
|
new (new_message_block) ACE_Message_Block (0, // size
|
|
ACE_Message_Type (0), // type
|
|
0, // cont
|
|
0, // data
|
|
0, // allocator
|
|
0, // locking strategy
|
|
0, // flags
|
|
old_message_block->priority_, // priority
|
|
ACE_EXECUTION_TIME, // execution time
|
|
ACE_DEADLINE_TIME, // absolute time to deadline
|
|
db,
|
|
db->data_block_allocator (),
|
|
old_message_block->message_block_allocator_);
|
|
}
|
|
|
|
if (new_message_block == 0)
|
|
{
|
|
db->release ();
|
|
return 0;
|
|
}
|
|
|
|
// Set the read and write pointers in the new <Message_Block> to the
|
|
// same relative offset as in the existing <Message_Block>.
|
|
new_message_block->rd_ptr (old_message_block->rd_ptr_);
|
|
new_message_block->wr_ptr (old_message_block->wr_ptr_);
|
|
// save the root message block to return
|
|
if (new_root_message_block == 0)
|
|
new_root_message_block = new_message_block;
|
|
if (new_previous_message_block != 0)
|
|
// we're a continuation of the previous block, add ourself to its chain
|
|
new_previous_message_block->cont_ = new_message_block;
|
|
new_previous_message_block = new_message_block;
|
|
old_message_block = old_message_block->cont ();
|
|
}
|
|
while (old_message_block != 0);
|
|
|
|
return new_root_message_block;
|
|
}
|
|
|
|
// This is private.
|
|
ACE_Message_Block &
|
|
ACE_Message_Block::operator= (const ACE_Message_Block &)
|
|
{
|
|
ACE_TRACE ("ACE_Message_Block::operator=");
|
|
return *this;
|
|
}
|
|
|
|
void
|
|
ACE_Data_Block::base (char *msg_data,
|
|
size_t msg_length,
|
|
ACE_Message_Block::Message_Flags msg_flags)
|
|
{
|
|
if (ACE_BIT_DISABLED (this->flags_,
|
|
ACE_Message_Block::DONT_DELETE))
|
|
this->allocator_strategy_->free (this->base_);
|
|
|
|
this->max_size_ = msg_length;
|
|
this->cur_size_ = msg_length;
|
|
this->base_ = msg_data;
|
|
this->flags_ = msg_flags;
|
|
}
|
|
|
|
ACE_END_VERSIONED_NAMESPACE_DECL
|