%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -*- Mode: Latex -*- %%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo %% %% The contents of this file are covered under the licence agreement in the %% file "LICENCE" distributed with Cforall. %% %% user.tex -- %% %% Author : Peter A. Buhr %% Created On : Wed Apr 6 14:53:29 2016 %% Last Modified By : Peter A. Buhr %% Last Modified On : Mon Sep 8 18:10:30 2025 %% Update Count : 6534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \documentclass[11pt]{article} \makeatletter \def\@maketitle{% \newpage \null % \vskip 2em% \begin{center}% \let \footnote \thanks {\LARGE\bf \@title \par}% \@ifundefined{@author}{} { \ifx\@empty\@author \else \vskip 1.5em% {\large \lineskip .5em% \begin{tabular}[t]{c}% \@author \end{tabular}% \par }% \fi }% \ifx\@empty\@date \else \vskip 1em% {\large \@date}% \fi \end{center}% \par % \vskip 1.5em }%maketitle \makeatother %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Latex packages used in the document. %\usepackage[T1]{fontenc} % allow Latin1 (extended ASCII) characters %\usepackage{textcomp} %\usepackage[latin1]{inputenc} \usepackage{fullpage,times,comment} \usepackage{epic,eepic} \usepackage{upquote} % switch curled `'" to straight \usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt]{subfig} \renewcommand{\thesubfigure}{\alph{subfigure})} \usepackage{latexsym} % \Box glyph \usepackage{mathptmx} % better math font with "times" \usepackage[usenames]{color} \usepackage[pagewise]{lineno} \renewcommand{\linenumberfont}{\scriptsize\sffamily} \input{common} % common CFA document macros \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref} \usepackage{breakurl} \renewcommand\footnoterule{\kern -3pt\rule{0.3\linewidth}{0.15pt}\kern 2pt} \newcommand{\uC}{$\mu$\CC} % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR % AFTER HYPERREF. \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}} \setlength{\topmargin}{-0.45in} % move running title into header \setlength{\headsep}{0.25in} \setlength{\tabcolsep}{15pt} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \setlength{\gcolumnposn}{3in} \CFAStyle % use default CFA format-style \lstset{language=CFA} % CFA default lnaguage \lstnewenvironment{C++}[1][] % use C++ style {\lstset{language=C++,escapechar=\$,mathescape=false,moredelim=**[is][\protect\color{red}]{@}{@},#1}}{} \lstnewenvironment{uC++}[1][] {\lstset{language=uC++,escapechar=\$,mathescape=false,moredelim=**[is][\protect\color{red}]{@}{@},#1}}{} \newsavebox{\myboxA} \newsavebox{\myboxB} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Names used in the document. \newcommand{\Version}{\input{build/version}} \newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}} \newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}} \newcommand{\R}[1]{{\color{red}#1}} \newcommand{\RB}[1]{\Textbf{#1}} \newcommand{\B}[1]{{\Textbf[blue]{#1}}} \newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}} \newcommand{\Sp}{\R{\textvisiblespace}} \newcommand{\KWC}{K-W C\xspace} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \setcounter{secnumdepth}{3} % number subsubsections \setcounter{tocdepth}{3} % subsubsections in table of contents \makeindex %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \title{\vspace*{-0.5in} \uC to \CFA Cheat Sheet} %\author{Peter A. Buhr} \date{} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{document} \pagestyle{headings} % changed after setting pagestyle \renewcommand{\sectionmark}[1]{\markboth{\thesection\quad #1}{\thesection\quad #1}} \renewcommand{\subsectionmark}[1]{\markboth{\thesubsection\quad #1}{\thesubsection\quad #1}} %\linenumbers % comment out to turn off line numbering \maketitle \vspace*{-0.65in} \section{Introduction} \CFA is an extension of the C programming with a trait-style type-system rather then templates and objects as in \CC. \CFA allows overloading of variables and routines using the left-hand assignment type to precisely select among overloaded names. \begin{cfa} int x; char x; double x; // overload name x int x(); double x(); char x(); \end{cfa} \vspace*{-8pt} \begin{cquote} \begin{tabular}{@{}l@{\hspace{1in}}|l@{}} \begin{cfa} x += 42; $\C[1in]{// int x}$ x += 42.2; $\C{// double x}$ x += 'a'; $\C{// char x}\CRT$ \end{cfa} & \begin{cfa} int j = x(); $\C[1in]{// int x()}$ double j = x(); $\C{// double x();}$ char j = x(); $\C{// char x()}\CRT$ \end{cfa} \end{tabular} \end{cquote} \CFA generalizes reference types, allowing multiple and rebindable references (like pointers). \begin{cquote} \begin{tabular}{@{}l|l@{}} \multicolumn{2}{@{}l}{\lstinline{ int x = 1, y = 2, * p1x = &x, * p1y = &y, ** p2i = &p1x,}} \\ \multicolumn{2}{@{}l}{\lstinline{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ & r1x = x, & r1y = y, && r2i = r1x;}} \\ \begin{uC++} **p2i = 3; p2i = &p1y; **p2i = 3; p1x = p1y; **p2i = 4; p1x = @nullptr@; \end{uC++} & \begin{cfa} r2i = 3; $\C[0.875in]{// change x}$ &r2i = &r1y; $\C{// change p2i / r2i}$ r2i = 3; $\C{// change y}$ &r1x = &r1y; $\C{// change p1x / r1x}$ r2i = 4; $\C{// change y}$ &r1x = @0p@; $\C{// reset}\CRT$ \end{cfa} \end{tabular} \end{cquote} Non-rebindable reference (\CC reference) is a @const@ reference (@const@ pointer). \begin{cfa} int & @const@ cr = x; // must initialize, no null pointer int & @const@ & @const@ crcr = cr; // generalize \end{cfa} \section{Control Flow} The @choose@ statement provides an implicit @break@ after the @case@ clause for safety. It is possible to @break default@ in a @case@ clause to transfer to common code in the @default@ clause. \begin{cquote} \begin{tabular}{@{}l|l@{}} \begin{uC++} switch ( i ) { case 1: ... @break@; // explicit break case 2: ... @break@; // explicit break default: ... ; } \end{uC++} & \begin{cfa} choose ( i ) { case 1: ... ; // implicit break case 2: ... ; // implicit break default: ... ; } \end{cfa} \end{tabular} \end{cquote} To simplify creating an infinite loop, the loop condition in optional. \begin{cquote} \begin{tabular}{@{}l|l@{}} \begin{uC++} while ( true ) ... for ( ;; ) ... do ... while ( true ) \end{uC++} & \begin{uC++} while ($\,$) ... for ($\,$) ... do ... while ($\,$) \end{uC++} \end{tabular} \end{cquote} To simplify loop iteration a range is provided, from low to high, and a traversal direction, ascending (@+@) or descending (@-@). The following is the syntax for the loop range, where @[@\,@]@ means optional. \begin{cfa}[deletekeywords=default] [ @index ;@ ] [ [ @min@ (default 0) ] [ direction @+@/@-@ (default +) ] @~@ [ @=@ (include endpoint) ] ] @max@ [ @~ increment@ ] \end{cfa} For @=@, the range includes the endpoint (@max@/@min@) depending on the direction (@+@/@-@). \begin{cquote} \begin{tabular}{@{}l|l@{}} \begin{uC++} for ( int i = 0; i < @10@; i += 1 ) { ... } for ( int i = @5@; i < @15@; i += @2@ ) { ... } for ( int i = -2; i <@=@ 10; i += 3 ) { ... } for ( int i = 10; i > -3; i @-@= 1 ) { ... } for ( int i = 10; i >@=@ 0; i @-@= 1 ) { ... } \end{uC++} & \begin{cfa} for ( @10@ ) { ... } / for ( i; @10@ ) { ... } // 0 to 9 by 1 for ( i; @5@ ~ @15@ ~ @2@ ) { ... } // 5 to 14 by 2 for ( i; -2 ~@=@ 10 ~ 3 ) { ... } // -2 to 10 by 3 for ( i; -3 @-@~ 10 ) { ... } // not 10 -~= -3, 10 to -2 by -1 for ( i; 0 @-@~@=@ 10 ) { ... } // not 10 -~= 0, 10 to 0 by -1 \end{cfa} \end{tabular} \end{cquote} A terminating loop @else@ (like Python) is executed if the loop terminates normally, \ie the loop conditional becomes false, which is safer than retesting after the loop. The loop index is available in the @else@ clause. \begin{cquote} \begin{tabular}{@{}l|l@{}} \begin{uC++} int i = 0 for ( i = 0; i < 10; i += 1 ) { ... } @if ( i == 10 )@ { ... } \end{uC++} & \begin{cfa} for ( i; 10 ) { ... } @else@ { ... } // i == 10 because of post increment \end{cfa} \end{tabular} \end{cquote} Single/multiple-level loop exit/continue is provided by the labelled @break@/@continue@. (First example is \CC.) \begin{cquote} \begin{tabular}{@{}l|l|l@{}} \begin{C++} @L1:@ for ( ;; ) { for ( ;; ) { ... if ( ... ) @goto L1@; ... ... if ( ... ) @goto L2@; ... } @L2: ;@ } \end{C++} & \begin{cfa} @L1:@ for () { @L2:@ for () { ... if ( ... ) @continue L1@; ... ... if ( ... ) @break L2@; ... } } \end{cfa} & \begin{cfa} @L1:@ for () { @L2:@ for () { ... if ( ... ) @continue L1@; ... ... if ( ... ) @break L2@; ... } } \end{cfa} \end{tabular} \end{cquote} \section{Exception} Currently, \CFA uses macros @ExceptionDecl@ and @ExceptionInst@ to declare and instantiate an exception. \begin{cquote} \setlength{\tabcolsep}{5pt} \begin{tabular}{@{}l|ll@{}} \begin{uC++} @_Exception@ E { // local or global scope ... // exception fields }; try { ... if ( ... ) @_Resume@ E( /* initialization */ ); ... ... if ( ... ) @_Throw@ E( /* initialization */ ); ... } @_CatchResume@( E & /* reference */ ) { ... } catch( E & ) { ... } catch( ... /* catch any */ ) { ... } _Finally { ... } \end{uC++} & \begin{cfa} #include @ExceptionDecl@( E, // must be global scope ... // exception fields ); try { ... if ( ... ) @throwResume@ @ExceptionInst@( E, /* intialization */ ); ... ... if ( ... ) @throw@ @ExceptionInst@( E, /* intialization */ ); ... } @catchResume@( E @*@ /* pointer */ ) { ... } catch( E * ) { ... } catch( exception_t @*@ /* catch any */ ) { ... } finally { ... } \end{cfa} \end{tabular} \end{cquote} \section{Non-local Exception} \begin{cquote} \begin{tabular}{@{}l|ll@{}} \begin{uC++} void main() { try { _Enable { ... suspend(); ... } } @_CatchResume@( E & /* reference */ ) { ... } catch( E & ) { ... } } \end{uC++} & \begin{cfa} #define resumePoll( coroutine ) resume( coroutine ); poll() #define suspendPoll suspend; poll() void main() { try { enable_ehm(); ... suspendPoll ... disable_ehm(); } @catchResume@( E * ) { ... } catch( E & ) { ... } } \end{cfa} \end{tabular} \end{cquote} \section{Stream I/O} \CFA output streams automatically separate values and insert a newline at the end of the print. \begin{cquote} \begin{tabular}{@{}l|l@{}} \begin{uC++} #include <@iostream@> using namespace std; int i; double d; char c; cin >> i >> d >> c; cout << i << ' ' << d << ' ' << c << endl; \end{uC++} & \begin{cfa} #include <@fstream.hfa@> int i; double d; char c; sin | i | d | c; sout | i | d | c \end{cfa} \end{tabular} \end{cquote} To disable/enable automatic newline at the end of printing, use @nlOff@/@nlOn@ and @nl@. \begin{cquote} \begin{tabular}{@{}l|l@{}} \begin{uC++} for ( int i = 0; i < 5; i += 1 ) cout << i << ' '; cout << @endl@; 0 1 2 3 4 \end{uC++} & \begin{cfa} sout | @nlOff@; // disable auto nl for ( i; 5 ) sout | i; sout | @nl@; sout | @nlOn@; // enable auto nl 0 1 2 3 4 \end{cfa} \end{tabular} \end{cquote} Floating-point numbers without a fraction print with a decimal point, which can be disabled with @nodp@. \begin{cquote} \begin{tabular}{@{}l|l@{}} \begin{uC++} cout << 3.0 << ' ' << showpoint << setprecision(0) << 3.0 << endl; 3 3. \end{uC++} & \begin{cfa} sout | @nodp( 3.0 )@ | 3.0; 3 3. \end{cfa} \end{tabular} \end{cquote} \section{String} The @string@ type in \CFA is very similar to that in \CC. \begin{cquote} \begin{tabular}{@{}l|l@{}} \multicolumn{2}{@{}l@{}}{\lstinline{string s1, s2;}} \\ \begin{uC++} s1 = "abcdefg"; s2 = s1; s1 += s2; s1 == s2; s1 != s2; s1 < s2; s1 <= s2; s1 > s2; s1 >= s2; s1.length(); s1[3]; s1.substr( 2 ); s1.substr( 2, 3 ); s1.replace( 2, 5, s2 ); s1.find( s2 ); s1.find_first_of( "cd" ); s1.find_first_not_of( "cd" ); getline( cin, s1 ); cout << s1 << endl; \end{uC++} & \begin{cfa} s1 = "abcdefg"; s2 = s1; s1 += s2; s1 == s2; s1 != s2; s1 < s2; s1 <= s2; s1 > s2; s1 >= s2; len( s1 ); // like C strlen( s1 ) s1[3]; s1( 2 ); s1( 2, 3 ); s1( 2, 5 ) = s2; find( s1, s2 ); exclude( s1, "cd" ); // longest sequence excluding "c" and "d" include( s1, "cd" ); // longest sequence including "c" and "d" sin | getline( s1 ); sout | s1; \end{cfa} \end{tabular} \end{cquote} \section{\texorpdfstring{\lstinline{uArray}}{uArray}} \begin{cquote} \setlength{\tabcolsep}{5pt} \begin{tabular}{@{}l|l@{}} \begin{uC++} #include using namespace std; struct S { int i; S( int i ) { S::i = i; } }; void f( @uArrayRef( S, parm )@ ); int main() { enum { N = 5 }; @uArray( S, s, N );@ // stack, no ctor calls for ( int i = 0; i < N; i += 1 ) @s[i]( i )@; // ctor calls for ( int i = 0; i < N; i += 1 ) cout << s[i]@->@i << endl; f( s ); @uArrayPtr( S, sp, N );@ // heap, no ctor calls for ( int i = 0; i < N; i += 1 ) @sp[i]( i )@; // ctor calls for ( int i = 0; i < N; i += 1 ) cout << sp[i]@->@i << endl; f( sp ); } // delete s, sp \end{uC++} & \begin{cfa} #include #include #include struct S { int i; }; void ?{}( S & s, int i ) { s.i = i; } @forall( [N] )@ void f( @array( S, N ) & parm@ ) {} int main() { enum { N = 5 }; @array( S, N ) s = { delay_init };@ // no ctor calls for ( i; N ) @s[i]{ i }@; // ctor calls for ( i; N ) sout | s[i]@.@i; f( s ); @unique_ptr( array( S, N ) )@ sp = { delay_init }; // heap for ( int i = 0; i < N; i += 1 ) @(*sp)@[i]{ i }; // ctor calls for ( int i = 0; i < N; i += 1 ) sout | @(*sp)@[i].i; f( @*sp@ ); } // delete s, sp \end{cfa} \end{tabular} \end{cquote} \section{\texorpdfstring{Structures (object-oriented \protect\vs routine style)}{Structures (object-oriented vs. routine style)}} \CFA is NOT an object-oriented programming-language, so there is no receiver (\lstinline[language=c++]{this}) or nested structure routines. The equivalent of a \emph{member} routine has an explicit structure parameter in any parameter position (often the first). \begin{cquote} \begin{tabular}{@{}l|l@{}} \begin{uC++} struct S { int i = 0; // cheat, implicit default constructor int setter( int j ) { int t = i; i = j; return t; } int getter() { return i; } }; S s; @s.@setter( 3 ); // object calls int k = @s.@getter(); \end{uC++} & \begin{cfa} struct S { int i; }; void ?{}( S & s ) { s.i = 0; } // explicit default constructor int setter( @S & s,@ int j ) @with( s )@ { int t = i; i = j; return t; } int getter( @S & s@ ) @with( s )@ { return i; } S s; setter( @s,@ 3 ); // normal calls int k = getter( @s@ ); \end{cfa} \end{tabular} \end{cquote} Aggregate qualification is reduced or eliminated by opening scopes using the @with@ clause. \begin{cfa} struct S { int i; int j; double m; }; // field i has same type in structures S and T struct T { int i; int k; int m; }; void foo( S s, T t ) @with( s, t )@ { // open structure scope s and t in parallel j + k; $\C[1.6in]{// unambiguous, s.j + t.k}$ m = 5.0; $\C{// unambiguous, s.m = 5.0}$ m = 1; $\C{// unambiguous, t.m = 1}$ int a = m; $\C{// unambiguous, a = t.m}$ double b = m; $\C{// unambiguous, b = s.m}$ int c = s.i + t.i; $\C{// unambiguous with qualification}$ (double)m; $\C{// unambiguous with cast s.m}\CRT$ } \end{cfa} \noindent In subsequent code examples, the left example is \CC/\uC and the right example is \CFA. \section{Constructor / Destructor} A constructor/destructor must have its structure type as the first parameter and be a reference. \begin{cquote} \begin{tabular}{@{}l|l@{}} \begin{uC++} struct S { int i, j; @S@() { i = j = 3; } @S@( int i, int j ) { S::i = i; S::j = j; } @S@( const S & s ) { *this = s; } @~S@() {} }; S s0; S s1 = { 1, 2 }; S * s2 = new S{ 1, 2 }; delete s2; s2 = new S{ 1, 2 }; delete s2; S & s3 = *new S{ 1, 2 }; delete &s3; s3 = *new S{ 1, 2 }; delete &s3; \end{uC++} & \begin{cfa} #include // new (malloc) struct S { int i, j; }; void @?{}@( @S & s@ ) { s.i = s.j = 3; } $\C[3in]{// default}$ void @?{}@( @S & s@, int i, int j ) { s.i = i; s.j = j; } $\C{// initializer}$ void @?{}@( @S & s@, const S rhs ) { ?{}( s, rhs.i, rhs.j ); } $\C{// copy}$ void @^?{}@( @S & s@ ) { s.i = 0; s.j = 0; } $\C{// destructor}\CRT$ S s0; S s1 = { 1, 2 }; // bug, cannot use 0/1 (zero_t/one_t) with "new" S * s2 = new( 0@n@, 2 ); // suffix n => (natural int) delete( s2 ); s2 = new( 1@n@, 2 ); delete( s2 ); S & s3 = *new( 2, 2 ); delete( &s3 ); &s3 = &*new( 3, 2 ); delete( &s3 ); \end{cfa} \end{tabular} \end{cquote} \section{Coroutine} \begin{cquote} \begin{tabular}{@{}l|ll@{}} \begin{uC++} @_Coroutine@ C { // private coroutine fields void main() { ... @suspend();@ ... ... @_Resume E( ... ) _At partner;@ ... @uThisCoroutine();@ ... } public: void mem( ... ) { ... @resume();@ ... } }; \end{uC++} & \begin{cfa} #include <$coroutine$.hfa> @coroutine@ C { // private coroutine fields }; void main( C & c ) { ... @suspend;@ ... // keyword not routine ... @resumeAt( partner, ExceptionInst( E, ... ) );@ ... @active_coroutine();@ ... } void mem( C & c, ... ) { ... @resume( c );@ ... } \end{cfa} \\ \multicolumn{2}{@{}l@{}}{\lstinline{C c;}} \end{tabular} \end{cquote} \section{\lstinline{COBEGIN}/\lstinline{COFOR}} \begin{cquote} \begin{tabular}{@{}l|ll@{}} \begin{uC++} #include int main() { @COBEGIN@ BEGIN osacquire( cout ) << "A" << endl; END BEGIN osacquire( cout ) << "B" << endl; END BEGIN osacquire( cout ) << "C" << endl; END BEGIN osacquire( cout ) << "D" << endl; END @COEND@ @COFOR@( i, 1, 10, osacquire( cout ) << i << endl; ) } \end{uC++} & \begin{cfa} #include #include <$cofor$.hfa> int main() { { @corun@ { mutex( sout ) sout | "A"; } corun { mutex( sout ) sout | "B"; } corun { mutex( sout ) sout | "C"; } corun { mutex( sout ) sout | "D"; } } @cofor@( i; 10 ) { mutex( sout ) sout | i; } } \end{cfa} \end{tabular} \end{cquote} \section{Actor} \begin{cquote} \begin{tabular}{@{}l|ll@{}} \begin{uC++} #include using namespace std; #include struct StrMsg : @public uActor::Message@ { const char * val; // string message StrMsg( const char * val ) : @Message( uActor::Delete )@, // delete after use val( val ) {} }; \end{uC++} & \begin{cfa} #include #include #include struct StrMsg { @inline message;@ // derived message const char * val; // string message }; void ?{}( StrMsg & msg, const char * str ) { @set_allocation( msg, Delete );@ // delete after use msg.val = str; } \end{cfa} \end{tabular} \begin{tabular}{@{}l|ll@{}} \begin{uC++} _Actor Hello { ${\color{red}\LstCommentStyle{// : public uActor}}$ Allocation receive( Message & msg ) { Case( @StartMsg@, msg ) { // discriminate } else Case( StrMsg, msg ) { osacquire( cout ) << msg_d->val << endl; } else Case( @StopMsg@, msg ) return Delete; // delete actor return Nodelete; // reuse actor } }; int main() { @uActor::start();@ // start actor system *new Hello() | uActor::startMsg | *new StrMsg( "hello" ) | uActor::stopMsg; *new Hello() | uActor::startMsg | *new StrMsg( "bonjour" ) | uActor::stopMsg; @uActor::stop();@ // wait for actors to terminate } \end{uC++} & \begin{cfa} struct Hello { @inline actor;@ }; // derived actor allocation receive( Hello & receiver, @start_msg_t@ & ) { return Nodelete; } allocation receive( Hello & receiver, StrMsg & msg ) { mutex( sout ) sout | msg.val; return Nodelete; // reuse actor } allocation receive( Hello & receiver, @stop_msg_t@ & ) { return Delete; // delete actor } int main() { @actor_start();@ // start actor system *(Hello *)new() | start_msg | *(StrMsg *)new( "hello" ) | stop_msg; *(Hello *)new() | start_msg | *(StrMsg *)new( "bonjour" ) | stop_msg; @actor_stop();@ // wait for actors to terminate } \end{cfa} \end{tabular} \end{cquote} \section{Thread} \begin{cquote} \begin{tabular}{@{}l|ll@{}} \begin{uC++} @_Task@ T { // private task fields void main() { ... @_Resume E( ... ) _At partner@; ... @uThisTask();@ ... } public: }; \end{uC++} & \begin{cfa} #include <$thread$.hfa> @thread@ T { // private task fields }; void main( @T & t@ ) { ... @resumeAt( partner, ExceptionInst( E, ... )@ ); ... @active_thread();@ ... } \end{cfa} \\ \multicolumn{2}{@{}l@{}}{\lstinline{T t; // start thread in main routine}} \end{tabular} \end{cquote} \section{Locks} \begin{cquote} \begin{tabular}{@{}l|ll@{}} \begin{uC++} uOwnerLock m; uCondLock s; m.acquire(); if ( ! s.empty() ) s.wait( m ); else { m.release(); } @osacquire( cout )@ << i << endl; \end{uC++} & \begin{cfa} #include owner_lock m; cond_lock( owner_lock ) s; // generic type on mutex lock lock( m ); if ( ! empty( s ) ) wait( s, m ); else { unlock( m ); } @mutex( sout )@ sout | i; // thread safe I/O \end{cfa} \end{tabular} \end{cquote} \section{Barrier} \begin{cquote} \begin{tabular}{@{}l|ll@{}} \begin{uC++} #include using namespace std; #include @_Cormonitor@ Barrier : @public uBarrier@ { // inheritance int total; void @last@() { cout << total << endl; } public: Barrier( unsigned int group ) : @uBarrier( group )@ { total = 0; } void @block@( int subtotal ) { total += subtotal; @uBarrier::block();@ } }; enum { N = 3 }; Barrier b{ N }; \end{uC++} & \begin{cfa} #include #include <$thread$.hfa> #include #include struct Barrier { @barrier b;@ // containment int total; }; void ?{}( Barrier & B, unsigned int group ) with(B) { @?{}( b, group );@ // initialize barrier total = 0; } unsigned int block( Barrier & B, int subtotal ) with(B) { void @last@() { sout | total; } // called by Gth arriving thread @mutex( b )@ { // use barrier's mutual exclusion total += subtotal; return @block@( b, last ); // wait for barrier trigger } } enum { N = 3 }; Barrier b{ N }; \end{cfa} \end{tabular} \end{cquote} \enlargethispage{1000pt} \section{Monitor} Internal Scheduling \begin{cquote} \begin{tabular}{@{}l|ll@{}} \begin{uC++} @_Monitor@ BoundedBufferI { @uCondition@ full, empty; int front = 0, back = 0, count = 0; int elements[20]; public: @_Nomutex@ int query() const { return count; } void insert( int elem ) { if ( count == 20 ) @empty.wait();@ elements[back] = elem; back = ( back + 1 ) % 20; count += 1; @full.signal();@ } int remove() { if ( count == 0 ) @full.wait();@ int elem = elements[front]; front = ( front + 1 ) % 20; count -= 1; @empty.signal();@ return elem; } }; \end{uC++} & \begin{cfa} #include <$monitor$.hfa> @monitor@ BoundedBufferI { @condition@ full, empty; int front, back, count; int elements[20]; }; void ?{}( BoundedBufferI & buf ) with( buf ) { front = back = count = 0; } int query( BoundedBufferI & buf ) { return buf.count; } int remove( BoundedBufferI & @mutex@ buf ); // forward void insert( BoundedBufferI & @mutex@ buf, int elem ) with( buf ) { if ( count == 20 ) @wait( empty );@ elements[back] = elem; back = ( back + 1 ) % 20; count += 1 @signal( full );@ } int remove( BoundedBufferI & @mutex@ buf ) with( buf ) { if ( count == 0 ) @wait( full );@ int elem = elements[front]; front = ( front + 1 ) % 20; count -= 1; @signal( empty );@ return elem; } \end{cfa} \end{tabular} \end{cquote} \newpage \noindent External Scheduling \begin{cquote} \begin{tabular}{@{}l|ll@{}} \begin{uC++} _Monitor BoundedBuffer { int front = 0, back = 0, count = 0; int elements[20]; public: _Nomutex int query() const { return count; } void insert( int elem ); int remove(); }; void BoundedBuffer::insert( int elem ) { if ( count == 20 ) @_Accept( remove );@ elements[back] = elem; back = ( back + 1 ) % 20; count += 1; } int BoundedBuffer::remove() { if ( count == 0 ) @_Accept( insert );@ int elem = elements[front]; front = ( front + 1 ) % 20; count -= 1; return elem; } \end{uC++} & \begin{cfa} #include <$monitor$.hfa> monitor BoundedBuffer { int front, back, count; int elements[20]; }; void ?{}( BoundedBuffer & buf ) with( buf ) { front = back = count = 0; } int query( BoundedBuffer & buf ) { return buf.count; } int remove( BoundedBuffer & @mutex@ buf ); // forward void insert( BoundedBuffer & @mutex@ buf, int elem ) with( buf ) { if ( count == 20 ) @waitfor( remove : buf );@ elements[back] = elem; back = ( back + 1 ) % 20; count += 1; } int remove( BoundedBuffer & @mutex@ buf ) with( buf ) { if ( count == 0 ) @waitfor( insert : buf );@ int elem = elements[front]; front = ( front + 1 ) % 20; count -= 1; return elem; } \end{cfa} \end{tabular} \end{cquote} \input{uC++toCFA.ind} % \bibliographystyle{plain} % \bibliography{pl} \end{document} % Local Variables: % % tab-width: 4 % % fill-column: 100 % % compile-command: "make" % % End: %