|
A mailbox allows for
the synchronous exchange of data between
CSIM processes. Any process may send a
message to any mailbox, and any process
may attempt to receive a message from
any mailbox.
A mailbox is comprised
of two FIFO queues: a queue of unreceived
messages and a queue of waiting processes.
At least one of the queues will be empty
at any time. When a process sends a message,
the message is given to a waiting process
(if one exists) or it is placed in the
message queue. When a process attempts
to receive a message, it is either given
a message from the message queue (if one
exists) or it is added to the queue of
waiting processes.
A message can be either
a single long integer or a pointer to
some other data object. If a process sends
a pointer, it is the responsibility of
that process to maintain the integrity
of the referenced data until it is received
and processed.
A pointer to a dynamic
mailbox is declared in a CSIM program
as follows:
Dynamic
Example: mailbox
*md;
Before a dynamic mailbox can be used,
it must be initialized by invoking the
new mailbox
constructor.
Prototype:
mailbox::mailbox(char*name)
Static Example:
mailbox ms("request");
Dynamic Example:
md = new mailbox("requests");
A newly created mailbox
contains no messages. The mailbox name
is used only to identify the mailbox in
output reports and trace messages.
A mailbox that is initialized
in the first CSIM process (sim) exists
during the entire simulation run and is
called a global mailbox. A mailbox initialized
in any other process is called a local
mailbox. A local mailbox is deleted when
the process in which it was constructed
terminates.
A process sends a message
by calling the send
function.
Prototype:
void mailbox::send(long
message)
Dynamic Example:
md->send((long)
buffer);
If one or more processes
are waiting on this mailbox, the process
at the head of the process queue will
resume execution and will be given this
message. If no processes are waiting,
this message will be appended to the tail
of the message queue. No simulation time
passes during this method call.
A process receives a
message by calling the receive
function.
Prototype:
void mailbox::receive(long*
message)
Dynamic Example:
md->receive((long*)
&ptr);
If one or more messages
are queued at this mailbox, the calling
process is given the message at the head
of the queue and continues executing.
If no messages are queued, the process
is suspended from further execution and
is added to the tail of the process queue
for this mailbox.
Sometimes a process
must not wait indefinitely to receive
a message. If a process calls the timed_receive
function, it will be suspended until either
a message is received or the specified
amount of time has passed.
Prototype:
long mailbox::timed_receive(long*
message, double timeout)
Example:
result = md->timed_receive((long*)&ptr,
100.0);
if (result ! =
TIMED_OUT) ...
The calling process
can check the functional value to determine
the circumstances under which it was resumed.
If the value EVENT_OCCURRED is returned,
the process was activated because a message
was received; if the value TIMED_OUT is
returned, the specified amount of time
passed without the process being activated
by the receipt of a message.
A process can also send
a message with a synchronous send operation
(as opposed to a normal send operation
as described above). With a synchronous
send, the send process waits until the
sent message has been received by another
process.
Prototype:
void mailbox::synchronous_send(long
message)
Dynamic Example:
mb->synchronous_send(msg,);
A process can also do
a synchronous_send operation with a time-out
interval:
Prototype:
long mailbox::timed_synchronous_send(long
message, double timeout)
Dynamic Example:
result = mb->timed_synchronous_send(msg,
100.0);
if (result ! = TIMED_OUT)
The calling process
can check the functional value to determine
the circumstances under which it was resumed.
If the value EVENT_OCCURRED is returned,
the process was activated because a message
was received; if the value TIMED_OUT is
returned, the specified amount of time
passed without the process being activated
by the receipt of a message by another
process.
A set of statistics
on the usage can be collected for specified
mailboxes. Statistics collection for a
mailbox is initiated by executing the
mailbox_monitor statement.
Prototype:
void mailbox::monitor()
Dynamic Example:
mb->mailbox_monitor();
The standard report
function automatically proceeds to "print"
a report for each monitored mailbox. This
report is as follows:
A separate report for
all monitored mailboxes is produced by
the report_mailboxes() procedure:
Prototype:
void report_mailboxes()
Example: report_mailboxes();
In some cases, it is
necessary to reset the statistics counters
for a specific mailbox.
Prototype:
void reset_mailbox(MBOX
mb)
Example:
reset_mailbox(mb);
Executing this statement
does not affect the state of the mailbox.
The "reset" and the reset_mailboxes
statements each call reset_mailbox() for
all mailboxes in the model.
All of the events in
an mailbox_set (see below) can be monitored
as well.
Prototype:
void mailbox_set_monitor(MBOX
mbs[])
Example:
mailbox_set_monitor(mbs);
A mailbox set is an
array of related mailboxes for which some
special operations are provided. A mailbox
set is declared using the C array construct.
Example:
MBOX mb_set[10];
All mailboxes in a mailbox
set are initialized with a single call
to the mailbox_set
function.
Prototype:
void mailbox_set(MBOX
mb_set[], char *name,
long number_of_mailboxes)
Example: mailbox_set(mb_set,
"mboxes", 10);
As with any C array,
the mailboxes in an mailbox set are indexed
from 0
to num_mailboxes
- 1. Individual mailboxes in the
mailbox set can be manipulated using any
of normal mailbox functions (e.g.,
send, and receive).
Example:
send(mb_set[3],
1);
A process can wait for
the occurrence of any mailbox in an mailbox
set by calling the receive_any
function.
Prototype:
long receive_any(MBOX mb_set[], (long*)
msg)
Example: mb_index
= receive_any(mb_set, &m);
This function returns
the index of the mailboxthat caused the
calling process to proceed. If multiple
mailboxes in the set have received messages,
the lowest numbered mailbox is the one
recognized by the calling process.
A process can also do a timed_receive_any()
operation at an mailbox_set.
Prototype:
long timed_receive_any(MBOX mb_set[],
(long*)&ptr)
Example:
result = time_receive_any(mb_set,
&m);
if(result != TIMED_OUT) . . .
If the result is not
equal to TIMED_OUT, then it is the index
of the mailbox which received the message
and caused the process to continue.
An entire mailbox set
is deleted by calling the delete_mailbox_set
function.
Prototype:
void delete_mailbox_set(MBOX mb_set[])
Example:
delete_mailbox_set(mb_set);
The delete_mailbox
function must not be called on individual
members of an mailbox set.
The name of a mailbox
can be changed at any time using the set_name_mailbox
function.
Prototype:
void mailbox::set_name(char
*new_name)
Static Example:
ms.set_name("responses");
Only the first ten characters
of the mailbox's name are stored.
When a dynamic mailbox
is no longer needed, its storage can be
reclaimed as follows:
Example:
delete md;
If a mailbox is local,
only the process that created the mailbox
can delete it. Once a mailbox has been
deleted, it must not be further referenced.
Deleting a mailbox causes any unreceived
messages to be lost. It is an error to
attempt to delete a mailbox on which processes
are waiting.
8.12. Inspector Methods
The following methods
return information about the specified
mailbox at the time they are called.
| Prototype: |
Functional
value: |
| char
*mailbox::name() |
pointer
to name of mailbox |
| long mailbox::msg_cnt() |
if positive, number
of unreceived messages
if negative, magnitude is number of
waiting
processes |
long mailbox::queue_cnt |
number of processes
queued at mailbox |
| long mailbox_set::num_msgs |
number of messages
in a mailbox set |
| double mailbox::proc_sum |
sum of process
queue lengths |
| long mailbox::proc_delay_count |
number of processes
delayed |
| long mailbox::proc_count |
number of process
receiving messages |
| double mailbox::proc_length |
average process
queue length |
| double mailbox::proc_time
|
average process
delay time |
| double mailbox::msg_sum
|
sum of message
queue lengths |
| long mailbox::msg_delay_count
|
number of messages
delayed |
| long mailbox::msg_count |
number of messages
sent |
| double mailbox::msg_length |
average message
queue length |
| double mailbox::msg_time |
average message delay time |
The
status_mailboxes
function prints a report of the status
of all mailboxes in the model.
Prototype:
void status_mailboxes(void)
Example:
status_mailboxes();
For
each mailbox, the report includes the
number of unreceived messages, the number
of waiting processes, and the name and
id of all waiting processes. The report
is written to the default output stream
or the stream specified in the last call
to set_output_file.
Next
Section
|