📄 node56.html
字号:
<html><!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
<!Converted with LaTeX2HTML 95.1 (Fri Jan 20 1995) by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds >
<HEAD>
<TITLE>5.5 Communication</TITLE>
</HEAD>
<BODY>
<meta name="description" value="5.5 Communication">
<meta name="keywords" value="book">
<meta name="resource-type" value="document">
<meta name="distribution" value="global">
<P>
<BR> <HR><a href="msgs0.htm#2" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/tppmsgs/msgs0.htm#2"><img ALIGN=MIDDLE src="asm_color_tiny.gif" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/asm_color_tiny.gif" alt="[DBPP]"></a> <A NAME=tex2html2607 HREF="node55.html" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node55.html"><IMG ALIGN=MIDDLE ALT="previous" SRC="previous_motif.gif" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/previous_motif.gif"></A> <A NAME=tex2html2615 HREF="node57.html" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node57.html"><IMG ALIGN=MIDDLE ALT="next" SRC="next_motif.gif" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/next_motif.gif"></A> <A NAME=tex2html2613 HREF="node51.html" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node51.html"><IMG ALIGN=MIDDLE ALT="up" SRC="up_motif.gif" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/up_motif.gif"></A> <A NAME=tex2html2617 HREF="node1.html" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node1.html"><IMG ALIGN=MIDDLE ALT="contents" SRC="contents_motif.gif" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/contents_motif.gif"></A> <A NAME=tex2html2618 HREF="node133.html" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node133.html"><IMG ALIGN=MIDDLE ALT="index" SRC="index_motif.gif" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/index_motif.gif"></A> <a href="msgs0.htm#3" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/tppmsgs/msgs0.htm#3"><img ALIGN=MIDDLE src="search_motif.gif" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/search_motif.gif" alt="[Search]"></a> <BR>
<B> Next:</B> <A NAME=tex2html2616 HREF="node57.html" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node57.html">5.6 Asynchronous Communication</A>
<B>Up:</B> <A NAME=tex2html2614 HREF="node51.html" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node51.html">5 Compositional C++
</A>
<B> Previous:</B> <A NAME=tex2html2608 HREF="node55.html" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node55.html">5.4 Locality</A>
<BR><HR><P>
<H1><A NAME=SECTION03250000000000000000>5.5 Communication</A></H1>
<P>
<A NAME=seccccomm> </A>
<P>
<A NAME=7056> </A>
CC++
does not provide low-level primitives for directly sending and
<A NAME=7057> </A>
receiving data between threads. Instead, threads communicate by
operating on shared data structures. For example, one thread may
append items to a shared list structure, from which another thread
removes items; this implements a form of channel communication.
CC++
mechanisms can be used to implement a wide variety of such
communication structures.
<P>
In this section, we first explain how global pointers are used to
communicate data between processor objects. Then, we explain how sync
variables and atomic functions are used to provide synchronization and
mutual exclusion. Finally, we show how data transfer functions are
used to communicate more complex data structures.
<P>
<H2><A NAME=SECTION03251000000000000000>5.5.1 Remote Operations</A></H2>
<P>
<P><A NAME=8163> </A><IMG BORDER=0 ALIGN=BOTTOM ALT="" SRC="img839.gif" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/img839.gif">
<BR><STRONG>Figure 5.1:</STRONG> <em> Remote read and write operations. At the top of the
figure, we show a global pointer <tt> gp</tt> located in processor object
<tt> pobj1</tt> referencing an integer <tt> length</tt> in processor object
<tt> pobj2</tt>. The rest of the figure is a timeline depicting the
activity in these two processor objects as a thread in <tt> pobj1</tt>
first writes and then reads <tt> length</tt>. The thread in <tt> pobj1</tt>
is shown as a solid line when active and as a dashed line when
suspended waiting for a remote operation. The diagonal dashed lines
represent communications.</em><A NAME=figcclen> </A><BR>
<P>
<P>
CC++
global pointers are used in the same way as C++
local pointers;
<A NAME=7069> </A>
the only difference is that we use them to operate on data or to
invoke functions that may be located in other processor objects.
Hence, the following code fragment first assigns to and then reads
from the remote location referenced by the global pointer <tt> gp</tt>.
<P>
<PRE>global int *gp;
int len2;
*gp = 5;
len2 = (*gp) * 2;
</PRE>
<P>
As illustrated in Figure <A HREF="node56.html#figcclen" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node56.html#figcclen">5.1</A>, these read and write
operations result in communication.
<P>
If we invoke a member function of an object referenced by a global
<A NAME=7080> </A>
pointer, we perform what is called a remote procedure call (RPC). An
RPC has the general form
<P>
<PRE><type> *global gp;
result = gp->p(...)
</PRE>
<P>
where <tt> gp</tt> is a global pointer of an arbitrary <tt> <type></tt>, <tt>
p(...)</tt> is a call to a function defined in the object referenced by
that global pointer, and <tt> result</tt> is a variable that will be set
to the value returned by <tt> p(...)</tt>. An RPC proceeds in
three stages:
<OL><LI>
The arguments to the function <tt> p(...)</tt> are packed into a message,
communicated to the remote processor object, and unpacked. The
calling thread suspends execution.
<P>
<LI>
A new thread is created in the remote processor object to execute the
called function.
<P>
<LI>
Upon termination of the remote function, the function return value is
transferred back to the calling thread, which resumes execution.
</OL>
<P>
Basic integer types (<tt> char</tt>, <tt> short</tt>, <tt> int</tt>, <tt> long</tt>,
and the unsigned variants of these), floats, doubles, and global
pointers can be transferred as RPC arguments or return values without
any user intervention. Structures, regular pointers, and arrays can
be transferred with the aid of transfer functions, to be discussed
later in this section.
<P>
<P><A NAME=progccrw> </A><IMG BORDER=0 ALIGN=BOTTOM ALT="" SRC="img840.gif" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/img840.gif"><P>
<P>
Program <A HREF="node56.html#progccrw" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node56.html#progccrw">5.5</A> uses RPCs to access a variable <tt> length</tt>
located in another processor object; contrast this with the code
fragment given at the beginning of this section, in which read and
write operations were used for the same purpose. The communication
that results is illustrated in Figure <A HREF="node56.html#figccrpc1" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node56.html#figccrpc1">5.2</A>.
<P>
<P><A NAME=8205> </A><IMG BORDER=0 ALIGN=BOTTOM ALT="" SRC="img841.gif" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/img841.gif">
<BR><STRONG>Figure 5.2:</STRONG> <em> Using remote procedure calls to read and write a remote
variable. At the top of the figure, we show a global pointer <tt> lp</tt>
located in processor object <tt> pobj1</tt> referencing processor object
<tt> pobj2</tt>. The rest of the figure is a timeline depicting the
activity in these two processor objects as a thread in <tt> pobj1</tt>
issues RPCs first to read and then to write the remote variable <tt>
length</tt>. The thread in <tt> pobj1</tt> is shown as a vertical solid or
dashed line when active or suspended, waiting for a remote operation;
the diagonal dashed lines represent communications. The solid
vertical lines in <tt> pobj2</tt> represent the threads created to execute
the remote procedure calls.</em><A NAME=figccrpc1> </A><BR>
<P><H2><A NAME=SECTION03252000000000000000>5.5.2 Synchronization</A></H2>
<P>
<A NAME=secccsync> </A>
<P>
<P><A NAME=8222> </A><IMG BORDER=0 ALIGN=BOTTOM ALT="" SRC="img842.gif" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/img842.gif">
<BR><STRONG>Figure 5.3:</STRONG> <em> Alternative synchronization mechanisms. On the left, the
<A NAME=8216> </A>
channel: a receiver blocks until a message is in the channel. On the
right, the <tt> sync</tt> variable: a receiver blocks until the variable
has a value.</em><A NAME=figccsync> </A><BR>
<P>
<P>
A producer thread can use an RPC to move data to a processor object in
which a consumer thread is executing, hence effecting communication.
<A NAME=7131> </A>
However, we also require a mechanism for synchronizing the execution
<A NAME=7132> </A>
of these two threads, so that the consumer does not read the data
<A NAME=7133> </A>
before it is communicated by the producer. In the task/channel model
of Part I, synchronization is achieved by making a consumer requiring
data from a channel block until a producer makes data available.
CC++
uses a different but analogous mechanism, the single
assignment or <em> sync
</em> variable (Figure <A HREF="node56.html#figccsync" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node56.html#figccsync">5.3</A>). A
sync variable is identified by the type modifier <tt> sync</tt>, which
indicates that the variable has the following properties:
<OL><LI>
It initially has a special value, ``undefined.''
<P>
<LI>
It can be assigned a value at most once, and once assigned is treated
as a constant (ANSI C and C++
<tt> const</tt>).
<P>
<LI>
An attempt to read an undefined variable causes the thread that
performs the read to block until the variable is assigned a value.
<P>
</OL>
We might think of a sync variable as an empty box with its interior
coated with glue; an object cannot be removed once it has been placed
inside.
<P>
Any regular C++
type can be declared <tt> sync</tt>, as can a
CC++
global pointer. Hence, we can write the following.
<P>
<PRE>sync int i; // i is a sync integer
sync int *j; // j is a pointer to a sync integer
int *sync k; // k is a sync pointer to an integer
sync int *sync l; // l is a sync pointer to a sync integer
</PRE>
<P>
<A NAME=7157> </A>
We use the following code fragment to illustrate the use of <tt> sync</tt>
variables. This code makes two concurrent RPCs to functions defined
in Program <A HREF="node56.html#progccrw" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node56.html#progccrw">5.5</A>: one to read the variable <tt> length</tt> and
one to write that variable.
<P>
<PRE>Length *global lp;
int val;
par {
val = lp->read_len();
lp->write_len(42);
}
</PRE>
<P>
What is the value of the variable <tt> val</tt> at the end of the parallel
block? Because the read and write operations are not synchronized,
the value is not known. If the read operation executes before the
write, <tt> val</tt> will have some arbitrary value. (The <tt> Length</tt>
class does not initialize the variable <tt> length</tt>.) If the
execution order is reversed, <tt> val</tt> will have the value 42.
<P>
This nondeterminism can be avoided by modifying
Program <A HREF="node56.html#progccrw" tppabs="http://www.dit.hcmut.edu.vn/books/system/par_anl/node56.html#progccrw">5.5</A> to make the variable <tt> length</tt> a <tt>
sync</tt> variable. That is, we change its definition to the following.
<tt> sync int length;</tt>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -