Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / Message_Block.cpp
blob4ff96b35f9dac915e68d053df335ce67d6ee421e
1 #include "ace/Message_Block.h"
3 #if !defined (__ACE_INLINE__)
4 #include "ace/Message_Block.inl"
5 #endif /* __ACE_INLINE__ */
7 #include "ace/Guard_T.h"
8 #include "ace/Log_Category.h"
9 #include "ace/Malloc_Base.h"
10 #include "ace/OS_NS_string.h"
12 //#define ACE_ENABLE_TIMEPROBES
13 #include "ace/Timeprobe.h"
15 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
17 ACE_ALLOC_HOOK_DEFINE (ACE_Message_Block)
19 #if defined (ACE_ENABLE_TIMEPROBES)
21 static const char *ACE_MB_Timeprobe_Description[] =
23 "Message_Block::init_i - enter",
24 "Message_Block::init_i - leave",
25 "Message_Block::init_i - db alloc",
26 "Message_Block::init_i - db ctor",
27 "Data_Block::ctor[1] - enter",
28 "Data_Block::ctor[1] - leave",
29 "Data_Block::ctor[2] - enter",
30 "Data_Block::ctor[2] - leave",
31 "Data_Block::clone - enter",
32 "Data_Block::clone - leave"
35 enum
37 ACE_MESSAGE_BLOCK_INIT_I_ENTER = 3000,
38 ACE_MESSAGE_BLOCK_INIT_I_LEAVE,
39 ACE_MESSAGE_BLOCK_INIT_I_DB_ALLOC,
40 ACE_MESSAGE_BLOCK_INIT_I_DB_CTOR,
41 ACE_DATA_BLOCK_CTOR1_ENTER,
42 ACE_DATA_BLOCK_CTOR1_LEAVE,
43 ACE_DATA_BLOCK_CTOR2_ENTER,
44 ACE_DATA_BLOCK_CTOR2_LEAVE,
45 ACE_DATA_BLOCK_CLONE_ENTER,
46 ACE_DATA_BLOCK_CLONE_LEAVE
50 // Setup Timeprobes
51 ACE_TIMEPROBE_EVENT_DESCRIPTIONS (ACE_MB_Timeprobe_Description,
52 ACE_MESSAGE_BLOCK_INIT_I_ENTER);
54 #endif /* ACE_ENABLE_TIMEPROBES */
56 void
57 ACE_Message_Block::data_block (ACE_Data_Block *db)
59 ACE_TRACE ("ACE_Message_Block::data_block");
60 if (ACE_BIT_DISABLED (this->flags_,
61 ACE_Message_Block::DONT_DELETE)
62 && this->data_block_ != 0)
63 this->data_block_->release ();
65 this->data_block_ = db;
67 // Set the read and write pointers in the <Message_Block> to point
68 // to the buffer in the <ACE_Data_Block>.
69 this->rd_ptr (this->data_block ()->base ());
70 this->wr_ptr (this->data_block ()->base ());
73 int
74 ACE_Message_Block::copy (const char *buf, size_t n)
76 ACE_TRACE ("ACE_Message_Block::copy");
78 /*size_t len = static_cast<size_t> (this->end () - this->wr_ptr ());*/
79 // Note that for this to work correct, end () *must* be >= mark ().
80 size_t len = this->space ();
82 if (len < n)
84 errno = ENOSPC;
85 return -1;
87 else
89 (void) ACE_OS::memcpy (this->wr_ptr (),
90 buf,
91 n);
92 this->wr_ptr (n);
93 return 0;
97 int
98 ACE_Message_Block::copy (const char *buf)
100 ACE_TRACE ("ACE_Message_Block::copy");
102 /* size_t len = static_cast<size_t> (this->end () - this->wr_ptr ()); */
103 // Note that for this to work correct, end() *must* be >= wr_ptr().
104 size_t len = this->space ();
106 size_t buflen = ACE_OS::strlen (buf) + 1;
108 if (len < buflen)
110 errno = ENOSPC;
111 return -1;
113 else
115 (void) ACE_OS::memcpy (this->wr_ptr (),
116 buf,
117 buflen);
118 this->wr_ptr (buflen);
119 return 0;
124 ACE_Message_Block::crunch ()
126 if (this->rd_ptr_ != 0)
128 if (this->rd_ptr_ > this->wr_ptr_)
129 return -1;
131 size_t const len = this->length ();
132 (void) ACE_OS::memmove (this->base (),
133 this->rd_ptr (),
134 len);
135 this->rd_ptr (this->base ());
136 this->wr_ptr (this->base () + len);
138 return 0;
141 void
142 ACE_Data_Block::dump () const
144 #if defined (ACE_HAS_DUMP)
145 ACE_TRACE ("ACE_Data_Block::dump");
146 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
147 ACELIB_DEBUG ((LM_DEBUG,
148 ACE_TEXT ("-----( Data Block )-----\n")
149 ACE_TEXT ("type_ = %d\n")
150 ACE_TEXT ("cur_size_ = %u\n")
151 ACE_TEXT ("max_size_ = %u\n")
152 ACE_TEXT ("flags_ = %u\n")
153 ACE_TEXT ("base_ = %@\n")
154 ACE_TEXT ("locking_strategy_ = %u\n")
155 ACE_TEXT ("reference_count_ = %u\n")
156 ACE_TEXT ("---------------------------\n"),
157 this->type_,
158 this->cur_size_,
159 this->max_size_,
160 this->flags_,
161 this->base_,
162 this->locking_strategy_,
163 this->reference_count_));
164 this->allocator_strategy_->dump ();
165 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
166 #endif /* ACE_HAS_DUMP */
169 void
170 ACE_Message_Block::dump () const
172 #if defined (ACE_HAS_DUMP)
173 ACE_TRACE ("ACE_Message_Block::dump");
174 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
175 ACELIB_DEBUG ((LM_DEBUG,
176 ACE_TEXT ("-----( Message Block )-----\n")
177 ACE_TEXT ("priority_ = %d\n")
178 ACE_TEXT ("next_ = %@\n")
179 ACE_TEXT ("prev_ = %@\n")
180 ACE_TEXT ("cont_ = %@\n")
181 ACE_TEXT ("rd_ptr_ = %@\n")
182 ACE_TEXT ("wr_ptr_ = %@\n")
183 ACE_TEXT ("---------------------------\n"),
184 this->priority_,
185 this->next_,
186 this->prev_,
187 this->cont_,
188 this->rd_ptr_,
189 this->wr_ptr_));
190 this->data_block ()->dump ();
191 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
192 #endif /* ACE_HAS_DUMP */
196 ACE_Data_Block::reference_count () const
198 if (this->locking_strategy_)
200 // We need to acquire the lock before retrieving the count
201 ACE_GUARD_RETURN (ACE_Lock, ace_mon, *this->locking_strategy_, 0);
203 return this->reference_count_i ();
206 return this->reference_count_i ();
210 ACE_Data_Block::size (size_t length)
212 ACE_TRACE ("ACE_Data_Block::size");
214 if (length <= this->max_size_)
215 this->cur_size_ = length;
216 else
218 // We need to resize!
219 char *buf = 0;
220 ACE_ALLOCATOR_RETURN (buf,
221 (char *) this->allocator_strategy_->malloc (length),
222 -1);
224 ACE_OS::memcpy (buf,
225 this->base_,
226 this->cur_size_);
227 if (ACE_BIT_DISABLED (this->flags_,
228 ACE_Message_Block::DONT_DELETE))
229 this->allocator_strategy_->free ((void *) this->base_);
230 else
231 // We now assume ownership.
232 ACE_CLR_BITS (this->flags_,
233 ACE_Message_Block::DONT_DELETE);
234 this->max_size_ = length;
235 this->cur_size_ = length;
236 this->base_ = buf;
238 return 0;
242 ACE_Message_Block::size (size_t length)
244 ACE_TRACE ("ACE_Message_Block::size");
246 // Resize the underlying <ACE_Data_Block>.
247 if (this->data_block ()->size (length) == -1)
248 return -1;
250 return 0;
253 void
254 ACE_Message_Block::total_size_and_length (size_t &mb_size,
255 size_t &mb_length) const
257 ACE_TRACE ("ACE_Message_Block::total_size_and_length");
259 for (const ACE_Message_Block *i = this;
260 i != 0;
261 i = i->cont ())
263 mb_size += i->size ();
264 mb_length += i->length ();
268 size_t
269 ACE_Message_Block::total_size () const
271 ACE_TRACE ("ACE_Message_Block::total_size");
273 size_t size = 0;
274 for (const ACE_Message_Block *i = this;
275 i != 0;
276 i = i->cont ())
277 size += i->size ();
279 return size;
282 size_t
283 ACE_Message_Block::total_length () const
285 ACE_TRACE ("ACE_Message_Block::total_length");
287 size_t length = 0;
288 for (const ACE_Message_Block *i = this;
289 i != 0;
290 i = i->cont ())
291 length += i->length ();
293 return length;
296 size_t
297 ACE_Message_Block::total_capacity () const
299 ACE_TRACE ("ACE_Message_Block::total_capacity");
301 size_t size = 0;
303 for (const ACE_Message_Block *i = this;
304 i != 0;
305 i = i->cont ())
306 size += i->capacity ();
308 return size;
311 ACE_Data_Block::ACE_Data_Block ()
312 : type_ (ACE_Message_Block::MB_DATA),
313 cur_size_ (0),
314 max_size_ (0),
315 flags_ (ACE_Message_Block::DONT_DELETE),
316 base_ (0),
317 allocator_strategy_ (0),
318 locking_strategy_ (0),
319 reference_count_ (1),
320 data_block_allocator_ (0)
322 ACE_TRACE ("ACE_Data_Block::ACE_Data_Block");
323 ACE_FUNCTION_TIMEPROBE (ACE_DATA_BLOCK_CTOR1_ENTER);
325 ACE_ALLOCATOR (this->allocator_strategy_,
326 ACE_Allocator::instance ());
328 ACE_ALLOCATOR (this->data_block_allocator_,
329 ACE_Allocator::instance ());
332 ACE_Data_Block::ACE_Data_Block (size_t size,
333 ACE_Message_Block::ACE_Message_Type msg_type,
334 const char *msg_data,
335 ACE_Allocator *allocator_strategy,
336 ACE_Lock *locking_strategy,
337 ACE_Message_Block::Message_Flags flags,
338 ACE_Allocator *data_block_allocator)
339 : type_ (msg_type),
340 cur_size_ (0), // Reset later if memory alloc'd ok
341 max_size_ (0),
342 flags_ (flags),
343 base_ (const_cast <char *> (msg_data)),
344 allocator_strategy_ (allocator_strategy),
345 locking_strategy_ (locking_strategy),
346 reference_count_ (1),
347 data_block_allocator_ (data_block_allocator)
349 ACE_TRACE ("ACE_Data_Block::ACE_Data_Block");
350 ACE_FUNCTION_TIMEPROBE (ACE_DATA_BLOCK_CTOR2_ENTER);
352 // If the user didn't pass one in, let's use the
353 // <ACE_Allocator::instance>.
354 if (this->allocator_strategy_ == 0)
355 ACE_ALLOCATOR (this->allocator_strategy_,
356 ACE_Allocator::instance ());
358 if (this->data_block_allocator_ == 0)
359 ACE_ALLOCATOR (this->data_block_allocator_,
360 ACE_Allocator::instance ());
362 if (msg_data == 0)
364 ACE_ALLOCATOR (this->base_,
365 (char *) this->allocator_strategy_->malloc (size));
366 #if defined (ACE_INITIALIZE_MEMORY_BEFORE_USE)
367 (void) ACE_OS::memset (this->base_,
368 '\0',
369 size);
370 #endif /* ACE_INITIALIZE_MEMORY_BEFORE_USE */
373 // ACE_ALLOCATOR returns on alloc failure but we cant throw, so setting
374 // the size to 0 (i.e. "bad bit") ...
375 if (this->base_ == 0)
377 size = 0;
380 // The memory is legit, whether passed in or allocated, so set
381 // the size.
382 this->cur_size_ = this->max_size_ = size;
385 ACE_Message_Block::ACE_Message_Block (const char *data,
386 size_t size,
387 unsigned long priority)
388 : flags_ (0),
389 data_block_ (0)
391 ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
393 if (this->init_i (size, // size
394 MB_DATA, // type
395 nullptr, // cont
396 data, // data
397 nullptr, // allocator
398 0, // locking strategy
399 ACE_Message_Block::DONT_DELETE, // flags
400 priority, // priority
401 ACE_Time_Value::zero, // execution time
402 ACE_Time_Value::max_time, // absolute time of deadline
403 nullptr, // data block
404 nullptr, // data_block allocator
405 0) == -1) // message_block allocator
406 ACELIB_ERROR ((LM_ERROR,
407 ACE_TEXT ("ACE_Message_Block")));
410 ACE_Message_Block::ACE_Message_Block (ACE_Allocator *message_block_allocator)
411 : flags_ (0),
412 data_block_ (0)
414 ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
416 if (this->init_i (0, // size
417 MB_DATA, // type
418 nullptr, // cont
419 nullptr, // data
420 nullptr, // allocator
421 0, // locking strategy
422 ACE_Message_Block::DONT_DELETE, // flags
423 0, // priority
424 ACE_Time_Value::zero, // execution time
425 ACE_Time_Value::max_time, // absolute time of deadline
426 nullptr, // data block
427 nullptr, // data_block allocator
428 message_block_allocator) == -1) // message_block allocator
429 ACELIB_ERROR ((LM_ERROR,
430 ACE_TEXT ("ACE_Message_Block")));
433 ACE_Message_Block::ACE_Message_Block (size_t size,
434 ACE_Message_Type msg_type,
435 ACE_Message_Block *msg_cont,
436 const char *msg_data,
437 ACE_Allocator *allocator_strategy,
438 ACE_Lock *locking_strategy,
439 unsigned long priority,
440 const ACE_Time_Value &execution_time,
441 const ACE_Time_Value &deadline_time,
442 ACE_Allocator *data_block_allocator,
443 ACE_Allocator *message_block_allocator)
444 :flags_ (0),
445 data_block_ (0)
447 ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
449 if (this->init_i (size,
450 msg_type,
451 msg_cont,
452 msg_data,
453 allocator_strategy,
454 locking_strategy,
455 msg_data ? ACE_Message_Block::DONT_DELETE : 0,
456 priority,
457 execution_time,
458 deadline_time,
459 0, // data block
460 data_block_allocator,
461 message_block_allocator) == -1)
462 ACELIB_ERROR ((LM_ERROR,
463 ACE_TEXT ("ACE_Message_Block")));
467 ACE_Message_Block::init (size_t size,
468 ACE_Message_Type msg_type,
469 ACE_Message_Block *msg_cont,
470 const char *msg_data,
471 ACE_Allocator *allocator_strategy,
472 ACE_Lock *locking_strategy,
473 unsigned long priority,
474 const ACE_Time_Value &execution_time,
475 const ACE_Time_Value &deadline_time,
476 ACE_Allocator *data_block_allocator,
477 ACE_Allocator *message_block_allocator)
479 ACE_TRACE ("ACE_Message_Block::init");
481 return this->init_i (size,
482 msg_type,
483 msg_cont,
484 msg_data,
485 allocator_strategy,
486 locking_strategy,
487 msg_data ? ACE_Message_Block::DONT_DELETE : 0,
488 priority,
489 execution_time,
490 deadline_time,
491 0, // data block
492 data_block_allocator,
493 message_block_allocator);
497 ACE_Message_Block::init (const char *data, size_t size)
499 ACE_TRACE ("ACE_Message_Block::init");
500 // Should we also initialize all the other fields, as well?
502 return this->init_i (size, // size
503 MB_DATA, // type
504 nullptr, // cont
505 data, // data
506 nullptr, // allocator
507 0, // locking strategy
508 ACE_Message_Block::DONT_DELETE, // flags
509 0, // priority
510 ACE_Time_Value::zero, // execution time
511 ACE_Time_Value::max_time, // absolute time of deadline
512 nullptr, // data block
513 nullptr, // data_block allocator
514 nullptr); // message_block allocator
517 ACE_Message_Block::ACE_Message_Block (size_t size,
518 ACE_Message_Type msg_type,
519 ACE_Message_Block *msg_cont,
520 const char *msg_data,
521 ACE_Allocator *allocator_strategy,
522 ACE_Lock *locking_strategy,
523 Message_Flags flags,
524 unsigned long priority,
525 const ACE_Time_Value &execution_time,
526 const ACE_Time_Value &deadline_time,
527 ACE_Data_Block *db,
528 ACE_Allocator *data_block_allocator,
529 ACE_Allocator *message_block_allocator)
530 : flags_ (0),
531 data_block_ (nullptr)
533 ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
535 if (this->init_i (size,
536 msg_type,
537 msg_cont,
538 msg_data,
539 allocator_strategy,
540 locking_strategy,
541 flags,
542 priority,
543 execution_time,
544 deadline_time,
546 data_block_allocator,
547 message_block_allocator) == -1)
548 ACELIB_ERROR ((LM_ERROR,
549 ACE_TEXT ("ACE_Message_Block")));
552 ACE_Message_Block::ACE_Message_Block (ACE_Data_Block *data_block,
553 ACE_Message_Block::Message_Flags flags,
554 ACE_Allocator *message_block_allocator)
555 : flags_ (flags),
556 data_block_ (nullptr)
558 ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
560 if (this->init_i (0, // size
561 MB_NORMAL, // type
562 0, // cont
563 0, // data
564 0, // allocator
565 0, // locking strategy
566 0, // flags
567 0, // priority
568 ACE_Time_Value::zero, // execution time
569 ACE_Time_Value::max_time, // absolute time of deadline
570 data_block, // data block
571 data_block->data_block_allocator (),
572 message_block_allocator) == -1)
573 ACELIB_ERROR ((LM_ERROR,
574 ACE_TEXT ("ACE_Message_Block")));
577 ACE_Message_Block::ACE_Message_Block (const ACE_Message_Block &mb,
578 size_t align)
579 :flags_ (0),
580 data_block_ (nullptr)
582 ACE_TRACE ("ACE_Message_Block::ACE_Message_Block");
584 if (ACE_BIT_DISABLED (mb.flags_,
585 ACE_Message_Block::DONT_DELETE))
587 if (this->init_i (0, // size
588 MB_NORMAL, // type
589 nullptr, // cont
590 nullptr, // data
591 nullptr, // allocator
592 nullptr, // locking strategy
593 0, // flags
594 0, // priority
595 ACE_Time_Value::zero, // execution time
596 ACE_Time_Value::max_time, // absolute time of deadline
597 mb.data_block ()->duplicate (), // data block
598 mb.data_block ()->data_block_allocator (),
599 mb.message_block_allocator_) == -1)
600 ACELIB_ERROR ((LM_ERROR,
601 ACE_TEXT ("ACE_Message_Block")));
602 #if !defined (ACE_LACKS_CDR_ALIGNMENT)
603 // Align ourselves
604 char *start = ACE_ptr_align_binary (this->base (),
605 align);
606 #else
607 char *start = this->base ();
608 #endif /* ACE_LACKS_CDR_ALIGNMENT */
610 // Set our rd & wr pointers
611 this->rd_ptr (start);
612 this->wr_ptr (start);
614 else
616 if (this->init_i (0, // size
617 MB_NORMAL, // type
618 nullptr, // cont
619 nullptr, // data
620 nullptr, // allocator
621 nullptr, // locking strategy
622 0, // flags
623 0, // priority
624 ACE_Time_Value::zero, // execution time
625 ACE_Time_Value::max_time, // absolute time of deadline
626 mb.data_block ()->clone_nocopy (),// data block
627 mb.data_block ()->data_block_allocator (),
628 mb.message_block_allocator_) == -1)
629 ACELIB_ERROR ((LM_ERROR,
630 ACE_TEXT ("ACE_Message_Block")));
632 #if !defined (ACE_LACKS_CDR_ALIGNMENT)
633 // Align ourselves
634 char *start = ACE_ptr_align_binary (this->base (),
635 align);
636 #else
637 char *start = this->base ();
638 #endif /* ACE_LACKS_CDR_ALIGNMENT */
640 // Set our rd & wr pointers
641 this->rd_ptr (start);
642 this->wr_ptr (start);
644 #if !defined (ACE_LACKS_CDR_ALIGNMENT)
645 // Get the alignment offset of the incoming ACE_Message_Block
646 start = ACE_ptr_align_binary (mb.base (), align);
647 #else
648 start = mb.base ();
649 #endif /* ACE_LACKS_CDR_ALIGNMENT */
651 // Actual offset for the incoming message block assuming that it
652 // is also aligned to the same "align" byte
653 size_t const wr_offset = mb.wr_ptr_ - (start - mb.base ());
655 // Copy wr_offset amount of data in to <this->data_block>
656 (void) ACE_OS::memcpy (this->wr_ptr (),
657 start,
658 wr_offset);
660 // Don't move the write pointer, just leave it to the application
661 // to do what it wants
663 #if defined (ACE_LACKS_CDR_ALIGNMENT)
664 ACE_UNUSED_ARG (align);
665 #endif /* ACE_LACKS_CDR_ALIGNMENT */
669 ACE_Message_Block::init_i (size_t size,
670 ACE_Message_Type msg_type,
671 ACE_Message_Block *msg_cont,
672 const char *msg_data,
673 ACE_Allocator *allocator_strategy,
674 ACE_Lock *locking_strategy,
675 Message_Flags flags,
676 unsigned long priority,
677 const ACE_Time_Value &execution_time,
678 const ACE_Time_Value &deadline_time,
679 ACE_Data_Block *db,
680 ACE_Allocator *data_block_allocator,
681 ACE_Allocator *message_block_allocator)
683 ACE_TRACE ("ACE_Message_Block::init_i");
684 ACE_FUNCTION_TIMEPROBE (ACE_MESSAGE_BLOCK_INIT_I_ENTER);
686 this->rd_ptr_ = 0;
687 this->wr_ptr_ = 0;
688 this->priority_ = priority;
689 #if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
690 this->execution_time_ = execution_time;
691 this->deadline_time_ = deadline_time;
692 #else
693 ACE_UNUSED_ARG (execution_time);
694 ACE_UNUSED_ARG (deadline_time);
695 #endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
696 this->cont_ = msg_cont;
697 this->next_ = nullptr;
698 this->prev_ = nullptr;
700 this->message_block_allocator_ = message_block_allocator;
702 if (this->data_block_ != 0)
704 this->data_block_->release ();
705 this->data_block_ = 0;
708 if (db == 0)
710 if (data_block_allocator == 0)
711 ACE_ALLOCATOR_RETURN (data_block_allocator,
712 ACE_Allocator::instance (),
713 -1);
715 ACE_TIMEPROBE (ACE_MESSAGE_BLOCK_INIT_I_DB_ALLOC);
717 // Allocate the <ACE_Data_Block> portion, which is reference
718 // counted.
719 ACE_NEW_MALLOC_RETURN (db,
720 static_cast<ACE_Data_Block *> (
721 data_block_allocator->malloc (sizeof (ACE_Data_Block))),
722 ACE_Data_Block (size,
723 msg_type,
724 msg_data,
725 allocator_strategy,
726 locking_strategy,
727 flags,
728 data_block_allocator),
729 -1);
730 ACE_TIMEPROBE (ACE_MESSAGE_BLOCK_INIT_I_DB_CTOR);
732 // Message block initialization may fail, while the construction
733 // succeeds. Since ACE may throw no exceptions, we have to do a
734 // separate check and clean up, like this:
735 if (db != 0 && db->size () < size)
737 db->ACE_Data_Block::~ACE_Data_Block(); // placement destructor ...
738 data_block_allocator->free (db); // free ...
739 errno = ENOMEM;
740 return -1;
744 // Reset the data_block_ pointer.
745 this->data_block (db);
747 return 0;
750 ACE_Data_Block::~ACE_Data_Block ()
752 // Sanity check...
753 ACE_ASSERT (this->reference_count_ <= 1);
755 // Just to be safe...
756 this->reference_count_ = 0;
758 if (ACE_BIT_DISABLED (this->flags_,
759 ACE_Message_Block::DONT_DELETE))
761 this->allocator_strategy_->free ((void *) this->base_);
762 this->base_ = nullptr;
766 ACE_Data_Block *
767 ACE_Data_Block::release_i ()
769 ACE_TRACE ("ACE_Data_Block::release_i");
771 ACE_ASSERT (this->reference_count_ > 0);
773 ACE_Data_Block *result = nullptr;
775 // decrement reference count
776 --this->reference_count_;
778 if (this->reference_count_ == 0)
779 // this will cause deletion of this
780 result = nullptr;
781 else
782 result = this;
784 return result;
787 ACE_Data_Block *
788 ACE_Data_Block::release_no_delete (ACE_Lock *lock)
790 ACE_TRACE ("ACE_Data_Block::release_no_delete");
792 ACE_Data_Block *result = nullptr;
793 ACE_Lock *lock_to_be_used = nullptr;
795 // Check if we were passed in a lock
796 if (lock != 0)
798 // Make sure that the lock passed in and our lock are the same
799 if (lock == this->locking_strategy_)
800 // In this case no locking is required.
801 lock_to_be_used = 0;
803 // The lock passed in does not match our lock
804 else
805 // Lock to be used is our lock
806 lock_to_be_used = this->locking_strategy_;
808 // This is the case when no lock was passed in
809 else
811 // Lock to be used is our lock
812 lock_to_be_used = this->locking_strategy_;
815 // If there's a locking strategy then we need to acquire the lock
816 // before decrementing the count.
817 if (lock_to_be_used != 0)
819 ACE_GUARD_RETURN (ACE_Lock, ace_mon, *lock_to_be_used, 0);
821 result = this->release_i ();
823 else
825 result = this->release_i ();
828 return result;
831 ACE_Data_Block *
832 ACE_Data_Block::release (ACE_Lock *lock)
834 ACE_TRACE ("ACE_Data_Block::release");
836 ACE_Allocator *allocator = this->data_block_allocator_;
838 ACE_Data_Block *result = this->release_no_delete (lock);
840 // We must delete this outside the scope of the locking_strategy_
841 // since otherwise we'd be trying to "release" through a deleted
842 // pointer!
843 if (result == nullptr)
844 ACE_DES_FREE_THIS (allocator->free,
845 ACE_Data_Block);
846 return result;
849 ACE_Message_Block *
850 ACE_Message_Block::release ()
852 ACE_TRACE ("ACE_Message_Block::release");
854 // We want to hold the data block in a temporary variable because we
855 // invoked "delete this;" at some point, so using this->data_block_
856 // could be a bad idea.
857 ACE_Data_Block *tmp = this->data_block ();
859 // This flag is set to 1 when we have to destroy the data_block
860 int destroy_dblock = 0;
862 ACE_Lock *lock = 0;
864 // Do we have a valid data block
865 if (this->data_block ())
867 // Grab the lock that belongs to my data block
868 lock = this->data_block ()->locking_strategy ();
870 // if we have a lock
871 if (lock != 0)
873 // One guard for all
874 ACE_GUARD_RETURN (ACE_Lock, ace_mon, *lock, 0);
876 // Call non-guarded release with @a lock
877 destroy_dblock = this->release_i (lock);
879 // This is the case when we have a valid data block but no lock
880 else
881 // Call non-guarded release with no lock
882 destroy_dblock = this->release_i (0);
884 else
885 // This is the case when we don't even have a valid data block
886 destroy_dblock = this->release_i (0);
888 if (destroy_dblock != 0)
890 ACE_Allocator *allocator = tmp->data_block_allocator ();
891 ACE_DES_FREE (tmp,
892 allocator->free,
893 ACE_Data_Block);
896 return 0;
900 ACE_Message_Block::release_i (ACE_Lock *lock)
902 ACE_TRACE ("ACE_Message_Block::release_i");
904 // Free up all the continuation messages.
905 if (this->cont_)
907 ACE_Message_Block *mb = this->cont_;
908 ACE_Message_Block *tmp = nullptr;
912 tmp = mb;
913 mb = mb->cont_;
914 tmp->cont_ = 0;
916 ACE_Data_Block *db = tmp->data_block ();
917 if (tmp->release_i (lock) != 0)
919 ACE_Allocator *allocator = db->data_block_allocator ();
920 ACE_DES_FREE (db,
921 allocator->free,
922 ACE_Data_Block);
925 while (mb);
927 this->cont_ = 0;
930 int result = 0;
932 if (ACE_BIT_DISABLED (this->flags_,
933 ACE_Message_Block::DONT_DELETE) &&
934 this->data_block ())
936 if (this->data_block ()->release_no_delete (lock) == 0)
937 result = 1;
938 this->data_block_ = nullptr;
941 // We will now commit suicide: this object *must* have come from the
942 // allocator given.
943 if (this->message_block_allocator_ == nullptr)
944 delete this;
945 else
947 ACE_Allocator *allocator = this->message_block_allocator_;
948 ACE_DES_FREE_THIS (allocator->free,
949 ACE_Message_Block);
952 return result;
955 /* static */ ACE_Message_Block *
956 ACE_Message_Block::release (ACE_Message_Block *mb)
958 ACE_TRACE ("ACE_Message_Block::release");
960 if (mb != nullptr)
961 return mb->release ();
962 else
963 return nullptr;
966 ACE_Message_Block::~ACE_Message_Block ()
968 ACE_TRACE ("ACE_Message_Block::~ACE_Message_Block");
970 if (ACE_BIT_DISABLED (this->flags_, ACE_Message_Block::DONT_DELETE) &&
971 this->data_block ())
973 this->data_block ()->release ();
976 this->prev_ = nullptr;
977 this->next_ = nullptr;
978 this->cont_ = nullptr;
981 ACE_Data_Block *
982 ACE_Data_Block::duplicate ()
984 ACE_TRACE ("ACE_Data_Block::duplicate");
986 // Create a new <ACE_Message_Block>, but share the <base_> pointer
987 // data (i.e., don't copy that).
988 if (this->locking_strategy_)
990 // We need to acquire the lock before incrementing the count.
991 ACE_GUARD_RETURN (ACE_Lock, ace_mon, *this->locking_strategy_, 0);
992 ++this->reference_count_;
994 else
995 ++this->reference_count_;
997 return this;
1000 #if defined (ACE_HAS_TIMED_MESSAGE_BLOCKS)
1001 #define ACE_EXECUTION_TIME this->execution_time_
1002 #define ACE_DEADLINE_TIME this->deadline_time_
1003 #else
1004 #define ACE_EXECUTION_TIME ACE_Time_Value::zero
1005 #define ACE_DEADLINE_TIME ACE_Time_Value::max_time
1006 #endif /* ACE_HAS_TIMED_MESSAGE_BLOCKS */
1008 ACE_Message_Block *
1009 ACE_Message_Block::duplicate () const
1011 ACE_TRACE ("ACE_Message_Block::duplicate");
1013 ACE_Message_Block *nb_top = nullptr;
1014 ACE_Message_Block *nb = nullptr;
1015 const ACE_Message_Block *current = this;
1017 // Increment the reference counts of all the continuation messages.
1018 while (current)
1020 ACE_Message_Block* cur_dup = 0;
1022 // Create a new <ACE_Message_Block> that contains unique copies of
1023 // the message block fields, but a reference counted duplicate of
1024 // the <ACE_Data_Block>.
1026 // If there is no allocator, use the standard new and delete calls.
1027 if (current->message_block_allocator_ == 0)
1028 ACE_NEW_NORETURN (cur_dup,
1029 ACE_Message_Block (0, // size
1030 ACE_Message_Type (0), // type
1031 nullptr, // cont
1032 nullptr, // data
1033 nullptr, // allocator
1034 nullptr, // locking strategy
1035 0, // flags
1036 current->priority_, // priority
1037 ACE_EXECUTION_TIME,
1038 ACE_DEADLINE_TIME,
1039 // Get a pointer to a
1040 // "duplicated" <ACE_Data_Block>
1041 // (will simply increment the
1042 // reference count).
1043 current->data_block ()->duplicate (),
1044 current->data_block ()->data_block_allocator (),
1045 current->message_block_allocator_));
1046 else // Otherwise, use the message_block_allocator passed in.
1047 ACE_NEW_MALLOC_NORETURN (cur_dup,
1048 static_cast<ACE_Message_Block*> (
1049 current->message_block_allocator_->malloc (sizeof (ACE_Message_Block))),
1050 ACE_Message_Block (0, // size
1051 ACE_Message_Type (0), // type
1052 nullptr, // cont
1053 nullptr, // data
1054 nullptr, // allocator
1055 nullptr, // locking strategy
1056 0, // flags
1057 current->priority_, // priority
1058 ACE_EXECUTION_TIME,
1059 ACE_DEADLINE_TIME,
1060 // Get a pointer to a
1061 // "duplicated" <ACE_Data_Block>
1062 // (will simply increment the
1063 // reference count).
1064 current->data_block ()->duplicate (),
1065 current->data_block ()->data_block_allocator (),
1066 current->message_block_allocator_));
1069 // If allocation failed above, release everything done so far and return NULL
1070 if (cur_dup == 0)
1072 if (nb_top != 0)
1074 nb_top->release ();
1076 return 0;
1079 // Set the read and write pointers in the new <Message_Block> to the
1080 // same relative offset as in the existing <Message_Block>. Note
1081 // that we are assuming that the data_block()->base() pointer
1082 // doesn't change when it's duplicated.
1083 cur_dup->rd_ptr (current->rd_ptr_);
1084 cur_dup->wr_ptr (current->wr_ptr_);
1086 if (!nb)
1088 /* First in the list: set leading pointers */
1089 nb_top = nb = cur_dup;
1091 else
1093 /* Continuing on: append to nb and walk down the list */
1094 nb->cont_ = cur_dup;
1095 nb = nb->cont_;
1098 current = current->cont_;
1101 return nb_top;
1104 ACE_Message_Block *
1105 ACE_Message_Block::duplicate (const ACE_Message_Block *mb)
1107 ACE_TRACE ("ACE_Message_Block::duplicate");
1108 if (mb == nullptr)
1109 return nullptr;
1110 else
1111 return mb->duplicate ();
1114 ACE_Data_Block *
1115 ACE_Data_Block::clone (ACE_Message_Block::Message_Flags mask) const
1117 ACE_TRACE ("ACE_Data_Block::clone");
1119 ACE_Data_Block *nb = this->clone_nocopy (mask);
1121 // Copy all of the payload memory into the new object. The new block
1122 // was allocated with max_size_ (and, thus, it's cur_size_ is the same
1123 // as max_size_). Maintain the same "has been written" boundary in the
1124 // new block by only copying cur_size_ bytes.
1125 if (nb != nullptr)
1127 ACE_OS::memcpy (nb->base_,
1128 this->base_,
1129 this->cur_size_);
1132 return nb;
1135 ACE_Data_Block *
1136 ACE_Data_Block::clone_nocopy (ACE_Message_Block::Message_Flags mask,
1137 size_t max_size) const
1139 ACE_FUNCTION_TIMEPROBE(ACE_DATA_BLOCK_CLONE_ENTER);
1141 ACE_TRACE ("ACE_Data_Block::clone_nocopy");
1143 // You always want to clear this one to prevent memory leaks but you
1144 // might add some others later.
1145 const ACE_Message_Block::Message_Flags always_clear = ACE_Message_Block::DONT_DELETE;
1146 const size_t newsize = max_size == 0 ? this->max_size_ : max_size;
1147 ACE_Data_Block *nb = nullptr;
1149 ACE_NEW_MALLOC_RETURN (nb,
1150 static_cast<ACE_Data_Block*> (
1151 this->data_block_allocator_->malloc (sizeof (ACE_Data_Block))),
1152 ACE_Data_Block (newsize, // size
1153 this->type_, // type
1154 0, // data
1155 this->allocator_strategy_, // allocator
1156 this->locking_strategy_, // locking strategy
1157 this->flags_, // flags
1158 this->data_block_allocator_),
1161 // Message block initialization may fail while the construction
1162 // succeeds. Since as a matter of policy, ACE may throw no
1163 // exceptions, we have to do a separate check like this.
1164 if (nb != 0 && nb->size () < newsize)
1166 nb->ACE_Data_Block::~ACE_Data_Block(); // placement destructor ...
1167 this->data_block_allocator_->free (nb); // free ...
1168 errno = ENOMEM;
1169 return 0;
1172 // Set new flags minus the mask...
1173 nb->clr_flags (mask | always_clear);
1174 return nb;
1177 ACE_Message_Block *
1178 ACE_Message_Block::clone (Message_Flags mask) const
1180 ACE_TRACE ("ACE_Message_Block::clone");
1182 const ACE_Message_Block *old_message_block = this;
1183 ACE_Message_Block *new_message_block {};
1184 ACE_Message_Block *new_previous_message_block {};
1185 ACE_Message_Block *new_root_message_block {};
1189 // Get a pointer to a "cloned" ACE_Data_Block (will copy the
1190 // values rather than increment the reference count).
1191 ACE_Data_Block *db = old_message_block->data_block ()->clone (mask);
1193 if (!db)
1194 return nullptr;
1196 if(old_message_block->message_block_allocator_ == nullptr)
1198 ACE_NEW_NORETURN (new_message_block,
1199 ACE_Message_Block (0, // size
1200 ACE_Message_Type (0), // type
1201 nullptr, // cont
1202 nullptr, // data
1203 nullptr, // allocator
1204 nullptr, // locking strategy
1205 0, // flags
1206 old_message_block->priority_, // priority
1207 ACE_EXECUTION_TIME, // execution time
1208 ACE_DEADLINE_TIME, // absolute time to deadline
1209 // Get a pointer to a
1210 // "duplicated"<ACE_Data_Block>
1211 // (will simply increment the
1212 // reference count).
1214 db->data_block_allocator (),
1215 old_message_block->message_block_allocator_));
1217 else
1219 // This is the ACE_NEW_MALLOC macro with the return check removed.
1220 // We need to do it this way because if it fails we need to release
1221 // the cloned data block that was created above. If we used
1222 // ACE_NEW_MALLOC_RETURN, there would be a memory leak because the
1223 // above db pointer would be left dangling.
1224 new_message_block = static_cast<ACE_Message_Block*> (old_message_block->message_block_allocator_->malloc (sizeof (ACE_Message_Block)));
1225 if (new_message_block != nullptr)
1226 new (new_message_block) ACE_Message_Block (0, // size
1227 ACE_Message_Type (0), // type
1228 nullptr, // cont
1229 nullptr, // data
1230 nullptr, // allocator
1231 nullptr, // locking strategy
1232 0, // flags
1233 old_message_block->priority_, // priority
1234 ACE_EXECUTION_TIME, // execution time
1235 ACE_DEADLINE_TIME, // absolute time to deadline
1237 db->data_block_allocator (),
1238 old_message_block->message_block_allocator_);
1241 if (new_message_block == nullptr)
1243 db->release ();
1244 return nullptr;
1247 // Set the read and write pointers in the new <Message_Block> to the
1248 // same relative offset as in the existing <Message_Block>.
1249 new_message_block->rd_ptr (old_message_block->rd_ptr_);
1250 new_message_block->wr_ptr (old_message_block->wr_ptr_);
1251 // save the root message block to return
1252 if (new_root_message_block == nullptr)
1253 new_root_message_block = new_message_block;
1254 if (new_previous_message_block != nullptr)
1255 // we're a continuation of the previous block, add ourself to its chain
1256 new_previous_message_block->cont_ = new_message_block;
1257 new_previous_message_block = new_message_block;
1258 old_message_block = old_message_block->cont ();
1260 while (old_message_block != nullptr);
1262 return new_root_message_block;
1265 // This is private.
1266 ACE_Message_Block &
1267 ACE_Message_Block::operator= (const ACE_Message_Block &)
1269 ACE_TRACE ("ACE_Message_Block::operator=");
1270 return *this;
1273 void
1274 ACE_Data_Block::base (char *msg_data,
1275 size_t msg_length,
1276 ACE_Message_Block::Message_Flags msg_flags)
1278 if (ACE_BIT_DISABLED (this->flags_,
1279 ACE_Message_Block::DONT_DELETE))
1280 this->allocator_strategy_->free (this->base_);
1282 this->max_size_ = msg_length;
1283 this->cur_size_ = msg_length;
1284 this->base_ = msg_data;
1285 this->flags_ = msg_flags;
1288 ACE_END_VERSIONED_NAMESPACE_DECL