A mailbox allows for the asynchronous
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 mailbox is declared in a CSIM program
using the built-in type MBOX.
Example:
MBOX m;
Before a mailbox can be used, it must
be initialized by calling the mailbox
function.
Prototype:
MBOX mailbox(char*
name)
Example:
m = 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 initialized
terminates.
A process sends a message by calling
the send
function.
Prototype:
void send(MBOX m, long message)
Example:
send(m, (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 function call.
A process can also send a message and
then suspend until the message is received
by another process; this is called a
synchronous_send operation:
Prototype:
void synchronous_send(MBOX
m, long message)
Example:
synchronous_send(m,
(long) buffer);
A process receives a message by calling
the receive
function.
Prototype:
void receive(MBOX m, long* message)
Example:
receive(m,(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 timed_receive(MBOX m,
long* message,
double timeout)
Example:
result = timed_receive(m,(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 synchronous_send(MBOX
mb,
long message)
Example:
synchronous_send(mb,
msg,);
A process can also do a synchronous_send
operation with a time-out interval:
Prototype:
long timed_synchronous_send(MBOX
mb,
long message, double timeout)
Example:
result = timed_synchronous_send
(mb, 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(MBOX
mb)
Example:
mailbox_monitor(mb);
The standard report function automatically
proceeds to "print" a report
for each monitored mailbox. This report
is as follows:
A report for all of the monitored mailboxes
can be generated as follows:
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 a 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 recieve_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 set_name_mailbox(MBOX m, char *new_name)
Example:
set_name_mailbox(m,
"responses");
Only the first ten characters of the
mailbox's name are stored.
When a mailbox is no longer needed,
its storage can be reclaimed using the
delete_mailbox
function.
Prototype:
void delete_mailbox(MBOX
m)
Example:
delete_mailbox(m);
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.
The following functions return information
about the specified mailbox at the time
they are called.
| Prototype:
|
Functional
value: |
| char* mailbox_name
(MBOX m) |
pointer to name
of mailbox |
| long msg_cnt
(MBOX m) |
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.