ACE_Message_Queue
).
#include <ace/Message_Block.h>
class ACE_Message_Block {
public:
friend class ACE_Data_Block;
enum{ MB_DATA = 0x01, MB_PROTO = 0x02, MB_BREAK = 0x03, MB_PASSFP = 0x04, MB_EVENT = 0x05, MB_SIG = 0x06, MB_IOCTL = 0x07, MB_SETOPTS = 0x08, MB_IOCACK = 0x81, MB_IOCNAK = 0x82, MB_PCPROTO = 0x83, MB_PCSIG = 0x84, MB_READ = 0x85, MB_FLUSH = 0x86, MB_STOP = 0x87, MB_START = 0x88, MB_HANGUP = 0x89, MB_ERROR = 0x8a, MB_PCEVENT = 0x8b, MB_NORMAL = 0x00, MB_PRIORITY = 0x80, MB_USER = 0x200 };typedef int ACE_Message_Type;
typedef u_long Message_Flags;
enum{ DONT_DELETE = 01, USER_FLAGS = 0x1000 };
ACE_Message_Block (ACE_Allocator *message_block_allocator = 0);
ACE_Message_Block ( ACE_Data_Block *, ACE_Allocator *message_block_allocator = 0 );
ACE_Message_Block ( const char *data, size_t size = 0, u_long priority = ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY );
ACE_Message_Block ( size_t size, ACE_Message_Type type = MB_DATA, ACE_Message_Block *cont = 0, const char *data = 0, ACE_Allocator *allocator_strategy = 0, ACE_Lock *locking_strategy = 0, u_long priority = ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY, const ACE_Time_Value &execution_time = ACE_Time_Value::zero, const ACE_Time_Value &deadline_time = ACE_Time_Value::max_time, ACE_Allocator *data_block_allocator = 0, ACE_Allocator *message_block_allocator = 0 );
int init (const char *data, size_t size = 0);
int init ( size_t size, ACE_Message_Type type = MB_DATA, ACE_Message_Block *cont = 0, const char *data = 0, ACE_Allocator *allocator_strategy = 0, ACE_Lock *locking_strategy = 0, u_long priority = ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY, const ACE_Time_Value &execution_time = ACE_Time_Value::zero, const ACE_Time_Value &deadline_time = ACE_Time_Value::max_time, ACE_Allocator *data_block_allocator = 0, ACE_Allocator *message_block_allocator = 0 );
virtual ~ACE_Message_Block (void);
ACE_Message_Type msg_type (void) const;
void msg_type (ACE_Message_Type type);
int is_data_msg (void) const;
ACE_Message_Type msg_class (void) const;
Message_Flags set_flags (Message_Flags more_flags);
Message_Flags clr_flags (Message_Flags less_flags);
Message_Flags flags (void) const;
u_long msg_priority (void) const;
void msg_priority (u_long priority);
const ACE_Time_Value &msg_execution_time (void) const;
void msg_execution_time (const ACE_Time_Value &et);
const ACE_Time_Value &msg_deadline_time (void) const;
void msg_deadline_time (const ACE_Time_Value &dt);
virtual ACE_Message_Block *clone (Message_Flags mask = 0) const;
ACE_Message_Block *duplicate (void) const;
static ACE_Message_Block *duplicate (const ACE_Message_Block *mb);
ACE_Message_Block *release (void);
static ACE_Message_Block *release (ACE_Message_Block *mb);
int copy (const char *buf, size_t n);
int copy (const char *buf);
void crunch (void);
void reset (void);
char *base (void) const;
void base (char *data, size_t size, Message_Flags = DONT_DELETE);
char *end (void) const;
char *mark (void) const;
char *rd_ptr (void) const;
void rd_ptr (char *ptr);
void rd_ptr (size_t n);
char *wr_ptr (void) const;
void wr_ptr (char *ptr);
void wr_ptr (size_t n);
size_t length (void) const;
void length (size_t n);
size_t total_length (void) const;
size_t total_size (void) const;
size_t size (void) const;
int size (size_t length);
size_t total_capacity (void) const;
size_t capacity (void) const;
size_t space (void) const;
ACE_Data_Block *data_block (void) const;
void data_block (ACE_Data_Block *);
ACE_Data_Block *replace_data_block (ACE_Data_Block*);
ACE_Message_Block *cont (void) const;
void cont (ACE_Message_Block *);
ACE_Message_Block *next (void) const;
void next (ACE_Message_Block *);
ACE_Message_Block *prev (void) const;
void prev (ACE_Message_Block *);
ACE_Lock *locking_strategy (void);
ACE_Lock *locking_strategy (ACE_Lock *);
int reference_count (void) const;
void dump (void) const;
ACE_ALLOC_HOOK_DECLARE;
protected:
ACE_Message_Block ( size_t size, ACE_Message_Type type, ACE_Message_Block *cont, const char *data, ACE_Allocator *allocator_strategy, ACE_Lock *locking_strategy, Message_Flags flags, u_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 );
int release_i (ACE_Lock *lock);
int init_i ( size_t size, ACE_Message_Type type, ACE_Message_Block *cont, const char *data, ACE_Allocator *allocator_strategy, ACE_Lock *locking_strategy, Message_Flags flags, u_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 );
size_t rd_ptr_;
size_t wr_ptr_;
u_long priority_;
ACE_Time_Value execution_time_;
ACE_Time_Value deadline_time_;
ACE_Message_Block *cont_;
ACE_Message_Block *next_;
ACE_Message_Block *prev_;
ACE_Data_Block *data_block_;
ACE_Allocator *message_block_allocator_;
private:
ACE_Message_Block &operator= (const ACE_Message_Block &);
ACE_Message_Block (const ACE_Message_Block &);
};
ACE_Message_Block
is modeled after the message data
structures used in System V STREAMS. Its purpose is to
enable efficient manipulation of arbitrarily-large messages
without much incurring memory copying overhead. Here are the
main characteristics of an ACE_Message_Block
:
1. Contains a pointer to a reference-counted
ACE_Data_Block
, which in turn points to the actual data
buffer. This allows very flexible and efficient sharing of
data by multiple ACE_Message_Block
s.
2. One or more ACE_Message_Blocks
can be linked to form a
``fragment chain.''
3. ACE_Message_Blocks
can be linked together by prev_
and
next_
pointers to form a queue of messages (e.g., this is how
ACE_Message_Queue
works).
ACE_Message_Block (ACE_Allocator *message_block_allocator = 0);
ACE_Message_Block (
ACE_Data_Block *,
ACE_Allocator *message_block_allocator = 0
);
ACE_Message_Block
that owns the ACE_Data_Block
*.
ACE_Message_Block (
const char *data,
size_t size = 0,
u_long priority = ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY
);
data
without
copying it (i.e., we don't delete it since we don't malloc it!).
Note that the size
of the Message_Block
will be size
, but
the length
will be 0 until wr_ptr
is set.
ACE_Message_Block (
size_t size,
ACE_Message_Type type = MB_DATA,
ACE_Message_Block *cont = 0,
const char *data = 0,
ACE_Allocator *allocator_strategy = 0,
ACE_Lock *locking_strategy = 0,
u_long priority = ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY,
const ACE_Time_Value &execution_time = ACE_Time_Value::zero,
const ACE_Time_Value &deadline_time = ACE_Time_Value::max_time,
ACE_Allocator *data_block_allocator = 0,
ACE_Allocator *message_block_allocator = 0
);
type
containing size
bytes. The cont
argument initializes the continuation field in
the Message_Block
. If data
== 0 then we create and own the
data
, using allocator
to get the data if it's non-0. If
data
!= 0 we assume ownership of the data
(and don't delete
it). If locking_strategy
is non-0 then this is used to protect
regions of code that access shared state (e.g., reference
counting) from race conditions. Note that the size
of the
Message_Block
will be size
, but the length
will be 0 until
wr_ptr
is set.
The data_block_allocator
is use to allocate the data blocks
while the allocator_strategy
is used to allocate the buffers
contained by those.
The message_block_allocator
is used to allocate new
Message_Block
objects when a duplicate method is called. If
a message_block_allocator
is given, this Message_Block
and
future Message_Block
objects created by duplicate will be free'ed
into this allocator when they are released. Note: if you use this
allocator, the Message_Block
you created should have been created
using this allocator because it will be released to the same allocator.
int init (const char *data, size_t size = 0);
data
(i.e.,
doesn't delete it since it didn't malloc it!). Note that the
size
of the Message_Block
will be size
, but the length
will be 0 until wr_ptr
is set.
int init (
size_t size,
ACE_Message_Type type = MB_DATA,
ACE_Message_Block *cont = 0,
const char *data = 0,
ACE_Allocator *allocator_strategy = 0,
ACE_Lock *locking_strategy = 0,
u_long priority = ACE_DEFAULT_MESSAGE_BLOCK_PRIORITY,
const ACE_Time_Value &execution_time = ACE_Time_Value::zero,
const ACE_Time_Value &deadline_time = ACE_Time_Value::max_time,
ACE_Allocator *data_block_allocator = 0,
ACE_Allocator *message_block_allocator = 0
);
type
containing size
bytes. The cont
argument initializes the continuation field in
the Message_Block
. If data
== 0 then we create and own the
data
, using allocator
to get the data if it's non-0. If
data
!= 0 we assume ownership of the data
(and don't delete
it). If locking_strategy
is non-0 then this is used to protect
regions of code that access shared state (e.g., reference
counting) from race conditions. Note that the size
of the
Message_Block
will be size
, but the length
will be 0 until
wr_ptr
is set.
The data_block_allocator
is use to allocate the data blocks
while the allocator_strategy
is used to allocate the buffers
contained by those.
virtual ~ACE_Message_Block (void);
Note that release
is designed to release the continuation
chain; the destructor is not. See release
for details.
ACE_Message_Type msg_type (void) const;
void msg_type (ACE_Message_Type type);
int is_data_msg (void) const;
ACE_Message_Type msg_class (void) const;
normal
messages and high-priority
messages).
Message_Flags set_flags (Message_Flags more_flags);
more_flags
into the existing message flags and
return the new value.
Message_Flags clr_flags (Message_Flags less_flags);
less_flags
and return
the new value.
Message_Flags flags (void) const;
u_long msg_priority (void) const;
void msg_priority (u_long priority);
const ACE_Time_Value &msg_execution_time (void) const;
void msg_execution_time (const ACE_Time_Value &et);
const ACE_Time_Value &msg_deadline_time (void) const;
void msg_deadline_time (const ACE_Time_Value &dt);
virtual ACE_Message_Block *clone (Message_Flags mask = 0) const;
ACE_Message_Block *duplicate (void) const;
static ACE_Message_Block *duplicate (const ACE_Message_Block *mb);
_duplicate
method, which is useful
if you want to eliminate lots of checks for NULL mb
pointers
before calling _duplicate
on them.
ACE_Message_Block *release (void);
release
is designed to release the continuation chain; the
destructor is not. If we make the destructor release the
continuation chain by calling release
or delete on the message
blocks in the continuation chain, the following code will not
work since the message block in the continuation chain is not off
the heap:
ACE_Message_Block mb1 (1024); ACE_Message_Block mb2 (1024);
mb1.cont (&mb2);
And hence, call release
on a dynamically allocated message
block. This will release all the message blocks in the
continuation chain. If you call delete or let the message block
fall off the stack, cleanup of the message blocks in the
continuation chain becomes the responsibility of the user.
static ACE_Message_Block *release (ACE_Message_Block *mb);
release
, except that it
checks if mb
is 0. This is similar to CORBA::release
, which
is useful if you want to eliminate lots of checks for NULL
pointers before calling release
on them. Returns mb
.
int copy (const char *buf, size_t n);
n
bytes from buf
into the Message_Block starting at
the wr_ptr
offset. Return 0 and increment wr_ptr
by n
if
the method succeeds. Returns -1 if the size of the message is
too small, i.e., for this to work correct, end
must be =
wr_ptr
.
int copy (const char *buf);
buf
into the Message_Block starting at the wr_ptr
offset. This call assumees that buf
is NUL-terminated. Return
0 and increment wr_ptr
by ACE_OS::strlen (buf) + 1
if the
method succeeds. Returns -1 if the size of the message is too
small, i.e., for this to work correct, end
must be = wr_ptr
.
void crunch (void);
Message_Block
to align with the base.
void reset (void);
char *base (void) const;
void base (char *data, size_t size, Message_Flags = DONT_DELETE);
char *end (void) const;
char *mark (void) const;
char *rd_ptr (void) const;
void rd_ptr (char *ptr);
ptr
.
void rd_ptr (size_t n);
n
bytes.
char *wr_ptr (void) const;
void wr_ptr (char *ptr);
ptr
.
void wr_ptr (size_t n);
n
bytes. This is used to compute
the length
of a message.
= Message length is wr_ptr
- rd_ptr
.
size_t length (void) const;
void length (size_t n);
size_t total_length (void) const;
Message_Block
s, including chained
Message_Block
s.
= Set/get Message_Block
size info.
size_t total_size (void) const;
Message_Block
s, including
chained Message_Block
s.
size_t size (void) const;
Message_Block
(i.e.,
does not consider the bytes in chained Message_Block
s).
int size (size_t length);
Message_Block
,
reallocating space if necessary. However, the rd_ptr_
and
wr_ptr_
remain at the original offsets into the buffer, even if
it is reallocated. Returns 0 if successful, else -1.
size_t total_capacity (void) const;
Message_Block
, including
chained Message_Block
s.
size_t capacity (void) const;
Message_Block
.
size_t space (void) const;
wr_ptr_
in the
top-level Message_Block
.
= ACE_Data_Block
methods.
ACE_Data_Block *data_block (void) const;
ACE_Message_Block
still references the block; this call does not change the reference
count.
void data_block (ACE_Data_Block *);
ACE_Data_Block
is released
as a result of this call. If you need to keep the original block, call
replace_data_block
instead. Upon return, this ACE_Message_Block
holds a pointer to the new ACE_Data_Block
, taking over the reference
you held on it prior to the call.
ACE_Data_Block *replace_data_block (ACE_Data_Block*);
ACE_Data_Block
is returned, and not released (as it is with data_block
).
ACE_Message_Block *cont (void) const;
void cont (ACE_Message_Block *);
= Pointer to the Message_Block
directly ahead in the ACE_Message_Queue
.
ACE_Message_Block *next (void) const;
void next (ACE_Message_Block *);
= Pointer to the Message_Block
directly behind in the ACE_Message_Queue
.
ACE_Message_Block *prev (void) const;
void prev (ACE_Message_Block *);
ACE_Lock *locking_strategy (void);
ACE_Lock *locking_strategy (ACE_Lock *);
int reference_count (void) const;
void dump (void) const;
ACE_ALLOC_HOOK_DECLARE;
ACE_Message_Block (
size_t size,
ACE_Message_Type type,
ACE_Message_Block *cont,
const char *data,
ACE_Allocator *allocator_strategy,
ACE_Lock *locking_strategy,
Message_Flags flags,
u_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
);
int release_i (ACE_Lock *lock);
int init_i (
size_t size,
ACE_Message_Type type,
ACE_Message_Block *cont,
const char *data,
ACE_Allocator *allocator_strategy,
ACE_Lock *locking_strategy,
Message_Flags flags,
u_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
);
size_t rd_ptr_;
size_t wr_ptr_;
u_long priority_;
ACE_Time_Value execution_time_;
ACE_Time_Value deadline_time_;
ACE_Message_Block *cont_;
ACE_Message_Block *next_;
ACE_Message_Block *prev_;
ACE_Data_Block *data_block_;
ACE_Allocator *message_block_allocator_;
schmidt@cs.wustl.edu