Changes in / [c7d8100c:ca54499]


Ignore:
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • doc/bibliography/pl.bib

    rc7d8100c rca54499  
    137137
    138138@article{Nierstrasz87,
    139     keywords    = {Hybrid, active objects, object-oriented languages, object-based languages, delegation, concurrency},
     139    keywords    = {Hybrid, active objects, object-oriented languages,
     140                  object-based languages, delegation, concurrency},
    140141    contributer = {pabuhr@plg},
    141142    author      = {O. M. Nierstrasz},
     
    907908    howpublished= {\href{https://plg.uwaterloo.ca/~cforall/evaluation.zip}{https://plg.uwaterloo.ca/\-\-$\sim$cforall/\-StackEvaluation.zip}},
    908909    optnote     = {[Accessed May 2018]},
    909 }
    910 
    911 @article{Moss18,
    912     keywords    = {concurrency, C++},
    913     contributer = {pabuhr@plg},
    914     author      = {Aaron Moss and Robert Schluntz and Peter A. Buhr},
    915     title       = {\textsf{C}$\mathbf{\forall}$ : Adding Modern Programming Language Features to C},
    916     year        = 2018,
    917     journal     = spe,
    918     note        = {Accepted, to appear},
    919910}
    920911
  • doc/papers/concurrency/Paper.tex

    rc7d8100c rca54499  
    7373% \def\{{\ttfamily\upshape\myCHarFont \char`\}}}%
    7474
    75 \renewcommand*{\thefootnote}{\Alph{footnote}} % hack because fnsymbol does not work
    76 %\renewcommand*{\thefootnote}{\fnsymbol{footnote}}
    77 
    7875\makeatletter
    7976% parindent is relative, i.e., toggled on/off in environments like itemize, so store the value for
     
    9087\setlength{\gcolumnposn}{3.5in}
    9188\setlength{\columnposn}{\gcolumnposn}
    92 
    9389\newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}}
    9490\newcommand{\CRT}{\global\columnposn=\gcolumnposn}
     
    176172literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1
    177173        {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 % {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    178         {<}{\textrm{\textless}}1 {>}{\textrm{\textgreater}}1
    179         {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.5ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex{\textrm{\textgreater}}}2,
     174        {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex{\textgreater}}2,
    180175moredelim=**[is][\color{red}]{`}{`},
    181176}% lstset
     
    219214\lstMakeShortInline@%
    220215
    221 \let\OLDthebibliography\thebibliography
    222 \renewcommand\thebibliography[1]{
    223   \OLDthebibliography{#1}
    224   \setlength{\parskip}{0pt}
    225   \setlength{\itemsep}{4pt plus 0.3ex}
    226 }
    227216
    228217\title{\texorpdfstring{Concurrency in \protect\CFA}{Concurrency in Cforall}}
     
    241230\CFA is a modern, polymorphic, \emph{non-object-oriented} extension of the C programming language.
    242231This paper discusses the design of the concurrency and parallelism features in \CFA, and the concurrent runtime-system.
    243 These features are created from scratch as ISO C lacks concurrency, relying largely on the pthreads library.
     232These features are created from scratch as ISO C lacks concurrency, relying largely on pthreads library.
    244233Coroutines and lightweight (user) threads are introduced into the language.
    245234In addition, monitors are added as a high-level mechanism for mutual exclusion and synchronization.
     
    266255Examples of high-level approaches are task (work) based~\cite{TBB}, implicit threading~\cite{OpenMP}, monitors~\cite{Java}, channels~\cite{CSP,Go}, and message passing~\cite{Erlang,MPI}.
    267256
    268 The following terminology is used.
     257This paper uses the following terminology.
    269258A \newterm{thread} is a fundamental unit of execution that runs a sequence of code and requires a stack to maintain state.
    270259Multiple simultaneous threads give rise to \newterm{concurrency}, which requires locking to ensure safe communication and access to shared data.
    271260% Correspondingly, concurrency is defined as the concepts and challenges that occur when multiple independent (sharing memory, timing dependencies, \etc) concurrent threads are introduced.
    272 \newterm{Locking}, and by extension \newterm{locks}, are defined as a mechanism to prevent progress of threads to provide safety.
     261\newterm{Locking}, and by extension locks, are defined as a mechanism to prevent progress of threads to provide safety.
    273262\newterm{Parallelism} is running multiple threads simultaneously.
    274263Parallelism implies \emph{actual} simultaneous execution, where concurrency only requires \emph{apparent} simultaneous execution.
    275 As such, parallelism only affects performance, which is observed through differences in space and/or time at runtime.
    276 
    277 Hence, there are two problems to be solved: concurrency and parallelism.
     264As such, parallelism only affects performance, which is observed through differences in space and/or time.
     265
     266Hence, there are two problems to be solved in the design of concurrency for a programming language: concurrency and parallelism.
    278267While these two concepts are often combined, they are distinct, requiring different tools~\cite[\S~2]{Buhr05a}.
    279268Concurrency tools handle synchronization and mutual exclusion, while parallelism tools handle performance, cost and resource utilization.
    280269
    281270The proposed concurrency API is implemented in a dialect of C, called \CFA.
    282 The paper discusses how the language features are added to the \CFA translator with respect to parsing, semantic, and type checking, and the corresponding high-performance runtime-library to implement the concurrency features.
     271The paper discusses how the language features are added to the \CFA translator with respect to parsing, semantic, and type checking, and the corresponding high-perforamnce runtime-library to implement the concurrency features.
    283272
    284273
     
    286275
    287276The following is a quick introduction to the \CFA language, specifically tailored to the features needed to support concurrency.
    288 Extended versions and explanation of the following code examples are available at the \CFA website~\cite{Cforall} or in Moss~\etal~\cite{Moss18}.
     277Extended versions of the following code examples are available at the \CFA website~\cite{Cforall} or Moss~\etal~\cite{XXX}.
    289278
    290279\CFA is an extension of ISO-C, and hence, supports all C paradigms.
     
    293282Virtually all of the code generated by the \CFA translator respects C memory layouts and calling conventions.
    294283While \CFA is not an object-oriented language, lacking the concept of a receiver (\eg @this@) and nominal inheritance-relationships, C does have a notion of objects: ``region of data storage in the execution environment, the contents of which can represent values''~\cite[3.15]{C11}.
    295 While some \CFA features are common in object-oriented programming-languages, they are an independent capability allowing \CFA to adopt them while retaining a procedural paradigm.
    296284
    297285
     
    308296r1 =  3;     r2 = 3;      r3 = 3;        // change x: implicit dereferences *r1, **r2, ***r3
    309297**p3 = &y; *p3 = &p4;                // change p1, p2
    310 `&`r3 = &y; `&&`r3 = &`&`r4;             // change r1, r2: cancel implicit dereferences (&*)**r3, (&(&*)*)*r3, &(&*)r4
     298`&`r3 = &y; `&&`r3 = &`&`r4;             // change r1, r2: cancel implicit deferences (&*)**r3, (&(&*)*)*r3, &(&*)r4
    311299\end{cfa}
    312300A reference is a handle to an object, like a pointer, but is automatically dereferenced the specified number of levels.
     
    317305\label{s:WithStatement}
    318306
    319 Heterogeneous data is aggregated into a structure/union.
     307Heterogeneous data is often aggregated into a structure/union.
    320308To reduce syntactic noise, \CFA provides a @with@ statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate field-qualification by opening a scope containing the field identifiers.
    321309\begin{cquote}
     
    327315// multiple aggregate parameters
    328316\end{cfa}
    329 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}|@{\hspace{2\parindentlnth}}l@{}}
     317\begin{tabular}{@{}l@{\hspace{\parindentlnth}}|@{\hspace{\parindentlnth}}l@{}}
    330318\begin{cfa}
    331319void f( S & s, T & t ) {
     
    369357// selection based on type
    370358\end{cfa}
    371 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}|@{\hspace{2\parindentlnth}}l@{}}
    372 \begin{cfa}
    373 const short int `MIN` = -32768;
    374 const int `MIN` = -2147483648;
    375 const long int `MIN` = -9223372036854775808L;
     359\begin{tabular}{@{}l@{\hspace{\parindentlnth}}|@{\hspace{\parindentlnth}}l@{}}
     360\begin{cfa}
     361const short int MIN = -32768;
     362const int MIN = -2147483648;
     363const long int MIN = -9223372036854775808L;
    376364\end{cfa}
    377365&
    378366\begin{cfa}
    379 short int si = `MIN`;
    380 int i = `MIN`;
    381 long int li = `MIN`;
     367short int si = MIN;
     368int i = MIN;
     369long int li = MIN;
    382370\end{cfa}
    383371\end{tabular}
     
    385373// selection based on type and number of parameters
    386374\end{cfa}
    387 \begin{tabular}{@{}l@{\hspace{2.7\parindentlnth}}|@{\hspace{2\parindentlnth}}l@{}}
    388 \begin{cfa}
    389 void `f`( void );
    390 void `f`( char );
    391 void `f`( int, double );
     375\begin{tabular}{@{}l@{\hspace{1.7\parindentlnth}}|@{\hspace{\parindentlnth}}l@{}}
     376\begin{cfa}
     377void f( void );
     378void f( char );
     379void f( int, double );
    392380\end{cfa}
    393381&
    394382\begin{cfa}
    395 `f`();
    396 `f`( 'a' );
    397 `f`( 3, 5.2 );
     383f();
     384f( 'a' );
     385f( 3, 5.2 );
    398386\end{cfa}
    399387\end{tabular}
     
    401389// selection based on type and number of returns
    402390\end{cfa}
    403 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}|@{\hspace{2\parindentlnth}}l@{}}
    404 \begin{cfa}
    405 char `f`( int );
    406 double `f`( int );
    407 [char, double] `f`( int );
     391\begin{tabular}{@{}l@{\hspace{\parindentlnth}}|@{\hspace{\parindentlnth}}l@{}}
     392\begin{cfa}
     393char f( int );
     394double f( int );
     395[char, double] f( int );
    408396\end{cfa}
    409397&
    410398\begin{cfa}
    411 char c = `f`( 3 );
    412 double d = `f`( 3 );
    413 [d, c] = `f`( 3 );
     399char c = f( 3 );
     400double d = f( 3 );
     401[d, c] = f( 3 );
    414402\end{cfa}
    415403\end{tabular}
     
    417405\end{cquote}
    418406Overloading is important for \CFA concurrency since the runtime system relies on creating different types to represent concurrency objects.
    419 Therefore, overloading is necessary to prevent the need for long prefixes and other naming conventions to prevent name clashes.
     407Therefore, overloading is necessary to prevent the need for long prefixes and other naming conventions that prevent name clashes.
    420408As seen in Section~\ref{basics}, function @main@ is heavily overloaded.
    421409
     
    426414with ( s, t ) {
    427415        j + k;                                                                  $\C{// unambiguous, s.j + t.k}$
    428         m = 5.0;                                                                $\C{// unambiguous, s.m = 5.0}$
    429         m = 1;                                                                  $\C{// unambiguous, t.m = 1}$
    430         int a = m;                                                              $\C{// unambiguous, a = t.m }$
    431         double b = m;                                                   $\C{// unambiguous, b = s.m}$
     416        m = 5.0;                                                                $\C{// unambiguous, t.m = 5.0}$
     417        m = 1;                                                                  $\C{// unambiguous, s.m = 1}$
     418        int a = m;                                                              $\C{// unambiguous, a = s.i }$
     419        double b = m;                                                   $\C{// unambiguous, b = t.m}$
    432420        int c = `s.i` + `t.i`;                                  $\C{// unambiguous, qualification}$
    433         (double)m;                                                              $\C{// unambiguous, cast s.m}$
    434 }
    435 \end{cfa}
    436 For parallel semantics, both @s.i@ and @t.i@ are visible the same type, so only @i@ is ambiguous without qualification.
     421        (double)m;                                                              $\C{// unambiguous, cast}$
     422}
     423\end{cfa}
     424For parallel semantics, both @s.i@ and @t.i@ are visible with the same type, so only @i@ is ambiguous without qualification.
    437425
    438426
     
    526514\begin{cfa}
    527515struct VLA { int len, * data; };                        $\C{// variable length array of integers}$
    528 void ?{}( VLA & vla ) with ( vla ) { len = 10;  data = alloc( len ); }  $\C{// default constructor}$
     516void ?{}( VLA & vla ) with ( vla ) { len = 10;  data = alloc( len ); }  // default constructor
    529517void ?{}( VLA & vla, int size, char fill ) with ( vla ) { len = size;  data = alloc( len, fill ); } // initialization
    530 void ?{}( VLA & vla, VLA other ) { vla.len = other.len;  vla.data = other.data; } $\C{// copy, shallow}$
     518void ?{}( VLA & vla, VLA other ) { vla.len = other.len;  vla.data = other.data; } // copy, shallow
    531519void ^?{}( VLA & vla ) with ( vla ) { free( data ); } $\C{// destructor}$
    532520{
    533521        VLA  x,            y = { 20, 0x01 },     z = y; $\C{// z points to y}$
    534         //    x{};         y{ 20, 0x01 };          z{ z, y };
     522        //    ?{}( x );   ?{}( y, 20, 0x01 );   ?{}( z, y );
    535523        ^x{};                                                                   $\C{// deallocate x}$
    536524        x{};                                                                    $\C{// reallocate x}$
     
    539527        y{ x };                                                                 $\C{// reallocate y, points to x}$
    540528        x{};                                                                    $\C{// reallocate x, not pointing to y}$
    541         //  ^z{};  ^y{};  ^x{};
     529        // ^?{}(z);  ^?{}(y);  ^?{}(x);
    542530}
    543531\end{cfa}
     
    558546\section{Concurrency Basics}\label{basics}
    559547
    560 At its core, concurrency is based on multiple call-stacks and scheduling threads executing on these stacks.
    561 Multiple call stacks (or contexts) and a single thread of execution, called \newterm{coroutining}~\cite{Conway63,Marlin80}, does \emph{not} imply concurrency~\cite[\S~2]{Buhr05a}.
    562 In coroutining, the single thread is self-scheduling across the stacks, so execution is deterministic, \ie given fixed inputs, the execution path to the outputs is fixed and predictable.
    563 A \newterm{stackless} coroutine executes on the caller's stack~\cite{Python} but this approach is restrictive, \eg preventing modularization and supporting only iterator/generator-style programming;
    564 a \newterm{stackfull} coroutine executes on its own stack, allowing full generality.
    565 Only stackfull coroutines are a stepping-stone to concurrency.
    566 
    567 The transition to concurrency, even for execution with a single thread and multiple stacks, occurs when coroutines also context switch to a scheduling oracle, introducing non-determinism from the coroutine perspective~\cite[\S~3]{Buhr05a}.
    568 Therefore, a minimal concurrency system is possible using coroutines (see Section \ref{coroutine}) in conjunction with a scheduler to decide where to context switch next.
    569 The resulting execution system now follows a cooperative threading-model, called \newterm{non-preemptive scheduling}.
    570 
    571 Because the scheduler is special, it can either be a stackless or stackfull coroutine.
    572 For stackless, the scheduler performs scheduling on the stack of the current coroutine and switches directly to the next coroutine, so there is one context switch.
    573 For stackfull, the current coroutine switches to the scheduler, which performs scheduling, and it then switches to the next coroutine, so there are two context switches.
    574 A stackfull scheduler is often used for simplicity and security, even through there is a slightly higher runtime-cost.
    575 
    576 Regardless of the approach used, a subset of concurrency related challenges start to appear.
    577 For the complete set of concurrency challenges to occur, the missing feature is \newterm{preemption}, where context switching occurs randomly between any two instructions, often based on a timer interrupt, called \newterm{preemptive scheduling}.
    578 While a scheduler introduces uncertainty in the order of execution, preemption introduces uncertainty where context switches occur.
    579 Interestingly, uncertainty is necessary for the runtime (operating) system to give the illusion of parallelism on a single processor and increase performance on multiple processors.
    580 The reason is that only the runtime has complete knowledge about resources and how to best utilized them.
    581 However, the introduction of unrestricted non-determinism results in the need for \newterm{mutual exclusion} and \newterm{synchronization} to restrict non-determinism for correctness;
    582 otherwise, it is impossible to write meaningful programs.
     548At its core, concurrency is based on multiple call-stacks and scheduling among threads executing on these stacks.
     549Multiple call stacks (or contexts) and a single thread of execution does \emph{not} imply concurrency.
     550Execution with a single thread and multiple stacks where the thread is deterministically self-scheduling across the stacks is called \newterm{coroutining};
     551execution with a single thread and multiple stacks but where the thread is scheduled by an oracle (non-deterministic from the thread's perspective) across the stacks is called concurrency~\cite[\S~3]{Buhr05a}.
     552Therefore, a minimal concurrency system can be achieved using coroutines (see Section \ref{coroutine}), which instead of context-switching among each other, always defer to an oracle for where to context-switch next.
     553
     554While coroutines can execute on the caller's stack-frame, stack-full coroutines allow full generality and are sufficient as the basis for concurrency.
     555The aforementioned oracle is a scheduler and the whole system now follows a cooperative threading-model (a.k.a., non-preemptive scheduling).
     556The oracle/scheduler can either be a stack-less or stack-full entity and correspondingly require one or two context-switches to run a different coroutine.
     557In any case, a subset of concurrency related challenges start to appear.
     558For the complete set of concurrency challenges to occur, the only feature missing is preemption.
     559
     560A scheduler introduces order of execution uncertainty, while preemption introduces uncertainty about where context switches occur.
     561Mutual exclusion and synchronization are ways of limiting non-determinism in a concurrent system.
     562Now it is important to understand that uncertainty is desirable; uncertainty can be used by runtime systems to significantly increase performance and is often the basis of giving a user the illusion that tasks are running in parallel.
    583563Optimal performance in concurrent applications is often obtained by having as much non-determinism as correctness allows.
    584564
     
    586566\subsection{\protect\CFA's Thread Building Blocks}
    587567
    588 An important missing feature in C is threading\footnote{While the C11 standard defines a ``threads.h'' header, it is minimal and defined as optional.
     568One of the important features that are missing in C is threading\footnote{While the C11 standard defines a ``threads.h'' header, it is minimal and defined as optional.
    589569As such, library support for threading is far from widespread.
    590570At the time of writing the paper, neither \protect\lstinline|gcc| nor \protect\lstinline|clang| support ``threads.h'' in their standard libraries.}.
    591 On modern architectures, a lack of threading is unacceptable~\cite{Sutter05, Sutter05b}, and therefore existing and new programming languages must have tools for writing efficient concurrent programs to take advantage of parallelism.
     571On modern architectures, a lack of threading is unacceptable~\cite{Sutter05, Sutter05b}, and therefore modern programming languages must have the proper tools to allow users to write efficient concurrent programs to take advantage of parallelism.
    592572As an extension of C, \CFA needs to express these concepts in a way that is as natural as possible to programmers familiar with imperative languages.
    593 Furthermore, because C is a system-level language, programmers expect to choose precisely which features they need and which cost they are willing to pay.
    594 Hence, concurrent programs should be written using high-level mechanisms, and only step down to lower-level mechanisms when performance bottlenecks are encountered.
     573And being a system-level language means programmers expect to choose precisely which features they need and which cost they are willing to pay.
    595574
    596575
    597576\subsection{Coroutines: A Stepping Stone}\label{coroutine}
    598577
    599 While the focus of this discussion is concurrency and parallelism, it is important to address coroutines, which are a significant building block of a concurrency system.
    600 Coroutines are generalized routines allowing execution to be temporarily suspend and later resumed.
    601 Hence, unlike a normal routine, a coroutine may not terminate when it returns to its caller, allowing it to be restarted with the values and execution location present at the point of suspension.
    602 This capability is accomplish via the coroutine's stack, where suspend/resume context switch among stacks.
    603 Because threading design-challenges are present in coroutines, their design effort is relevant, and this effort can be easily exposed to programmers giving them a useful new programming paradigm because a coroutine handles the class of problems that need to retain state between calls, \eg plugins, device drivers, and finite-state machines.
    604 Therefore, the core \CFA coroutine-API for has two fundamental features: independent call-stacks and @suspend@/@resume@ operations.
    605 
    606 For example, a problem made easier with coroutines is unbounded generators, \eg generating an infinite sequence of Fibonacci numbers, where Figure~\ref{f:C-fibonacci} shows conventional approaches for writing a Fibonacci generator in C.
     578While the focus of this proposal is concurrency and parallelism, it is important to address coroutines, which are a significant building block of a concurrency system.
     579\newterm{Coroutine}s are generalized routines with points where execution is suspended and resumed at a later time.
     580Suspend/resume is a context switche and coroutines have other context-management operations.
     581Many design challenges of threads are partially present in designing coroutines, which makes the design effort relevant.
     582The core \textbf{api} of coroutines has two features: independent call-stacks and @suspend@/@resume@.
     583
     584A coroutine handles the class of problems that need to retain state between calls (\eg plugin, device driver, finite-state machine).
     585For example, a problem made easier with coroutines is unbounded generators, \eg generating an infinite sequence of Fibonacci numbers:
    607586\begin{displaymath}
    608 \mathsf{fib}(n) = \left \{
     587f(n) = \left \{
    609588\begin{array}{ll}
    610 0                                       & n = 0         \\
    611 1                                       & n = 1         \\
    612 \mathsf{fib}(n-1) + \mathsf{fib}(n-2)   & n \ge 2       \\
     5890                               & n = 0         \\
     5901                               & n = 1         \\
     591f(n-1) + f(n-2) & n \ge 2       \\
    613592\end{array}
    614593\right.
    615594\end{displaymath}
     595Figure~\ref{f:C-fibonacci} shows conventional approaches for writing a Fibonacci generator in C.
     596
    616597Figure~\ref{f:GlobalVariables} illustrates the following problems:
    617 unique unencapsulated global variables necessary to retain state between calls;
    618 only one Fibonacci generator;
    619 execution state must be explicitly retained via explicit state variables.
     598unencapsulated global variables necessary to retain state between calls;
     599only one fibonacci generator can run at a time;
     600execution state must be explicitly retained.
    620601Figure~\ref{f:ExternalState} addresses these issues:
    621602unencapsulated program global variables become encapsulated structure variables;
    622 unique global variables are replaced by multiple Fibonacci objects;
    623 explicit execution state is removed by precomputing the first two Fibonacci numbers and returning $\mathsf{fib}(n-2)$.
     603multiple fibonacci generators can run at a time by declaring multiple fibonacci objects;
     604explicit execution state is removed by precomputing the first two Fibonacci numbers and returning $f(n-2)$.
    624605
    625606\begin{figure}
     
    681662\begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
    682663`coroutine` Fib { int fn; };
    683 void main( Fib & fib ) with( fib ) {
     664void ?{}( Fibonacci & fib ) with( fib ) { fn = 0; }
     665void main( Fib & f ) with( f ) {
    684666        int f1, f2;
    685667        fn = 0;  f1 = fn;  `suspend()`;
     
    705687\begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
    706688`coroutine` Fib { int ret; };
    707 void main( Fib & f ) with( fib ) {
     689void main( Fib & f ) with( f ) {
    708690        int fn, f1 = 1, f2 = 0;
    709691        for ( ;; ) {
     
    732714\end{figure}
    733715
    734 Using a coroutine, it is possible to express the Fibonacci formula directly without any of the C problems.
    735 Figure~\ref{f:Coroutine3States} creates a @coroutine@ type:
    736 \begin{cfa}
    737 `coroutine` Fib { int fn; };
    738 \end{cfa}
    739 which provides communication, @fn@, for the \newterm{coroutine main}, @main@, which runs on the coroutine stack, and possibly multiple interface functions, @next@.
    740 Like the structure in Figure~\ref{f:ExternalState}, the coroutine type allows multiple instances, where instances of this type are passed to the (overloaded) coroutine main.
    741 The coroutine main's stack holds the state for the next generation, @f1@ and @f2@, and the code has the three suspend points, representing the three states in the Fibonacci formula, to context switch back to the caller's resume.
    742 The interface function, @next@, takes a Fibonacci instance and context switches to it using @resume@;
    743 on return, the Fibonacci field, @fn@, contains the next value in the sequence, which is returned.
    744 The first @resume@ is special because it cocalls the coroutine at its coroutine main and allocates the stack;
    745 when the coroutine main returns, its stack is deallocated.
    746 Hence, @Fib@ is an object at creation, transitions to a coroutine on its first resume, and transitions back to an object when the coroutine main finishes.
    747 Figure~\ref{f:Coroutine1State} shows the coroutine version of the C version in Figure~\ref{f:ExternalState}.
    748 Coroutine generators are called \newterm{output coroutines} because values are returned by the coroutine.
    749 
    750 Figure~\ref{f:CFAFmt} shows an \newterm{input coroutine}, @Format@, for restructuring text into groups of character blocks of fixed size.
    751 For example, the input of the left is reformatted into the output on the right.
    752 \begin{quote}
    753 \tt
    754 \begin{tabular}{@{}l|l@{}}
    755 \multicolumn{1}{c|}{\textbf{\textrm{input}}} & \multicolumn{1}{c}{\textbf{\textrm{output}}} \\
    756 abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
    757 &
    758 \begin{tabular}[t]{@{}lllll@{}}
    759 abcd    & efgh  & ijkl  & mnop  & qrst  \\
    760 uvwx    & yzab  & cdef  & ghij  & klmn  \\
    761 opqr    & stuv  & wxyz  &               &
    762 \end{tabular}
    763 \end{tabular}
    764 \end{quote}
    765 The example takes advantage of resuming coroutines in the constructor to prime the coroutine loops so the first character sent for formatting appears inside the nested loops.
    766 The destruction provides a newline if formatted text ends with a full line.
    767 Figure~\ref{f:CFmt} shows the C equivalent formatter, where the loops of the coroutine are flatten (linearized) and rechecked on each call because execution location is not retained between calls.
     716Figure~\ref{f:Coroutine3States} creates a @coroutine@ type, which provides communication for multiple interface functions, and the \newterm{coroutine main}, which runs on the coroutine stack.
     717\begin{cfa}
     718`coroutine C { char c; int i; _Bool s; };`      $\C{// used for communication}$
     719void ?{}( C & c ) { s = false; }                        $\C{// constructor}$
     720void main( C & cor ) with( cor ) {                      $\C{// actual coroutine}$
     721        while ( ! s ) // process c
     722        if ( v == ... ) s = false;
     723}
     724// interface functions
     725char cont( C & cor, char ch ) { c = ch; resume( cor ); return c; }
     726_Bool stop( C & cor, int v ) { s = true; i = v; resume( cor ); return s; }
     727\end{cfa}
     728
     729encapsulates the Fibonacci state in the  shows is an example of a solution to the Fibonacci problem using \CFA coroutines, where the coroutine stack holds sufficient state for the next generation.
     730This solution has the advantage of having very strong decoupling between how the sequence is generated and how it is used.
     731Indeed, this version is as easy to use as the @fibonacci_state@ solution, while the implementation is very similar to the @fibonacci_func@ example.
     732
     733Figure~\ref{f:fmt-line} shows the @Format@ coroutine for restructuring text into groups of character blocks of fixed size.
     734The example takes advantage of resuming coroutines in the constructor to simplify the code and highlights the idea that interesting control flow can occur in the constructor.
    768735
    769736\begin{figure}
    770 \centering
    771 \newbox\myboxA
    772 \begin{lrbox}{\myboxA}
    773 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
     737\begin{cfa}[xleftmargin=4\parindentlnth]
    774738`coroutine` Format {
    775         char ch;   // used for communication
    776         int g, b;  // global because used in destructor
     739        char ch;                                                                $\C{// used for communication}$
     740        int g, b;                                                               $\C{// global because used in destructor}$
    777741};
     742void ?{}( Format & fmt ) { `resume( fmt );` } $\C{// prime (start) coroutine}$
     743void ^?{}( Format & fmt ) with( fmt ) { if ( g != 0 || b != 0 ) sout | endl; }
    778744void main( Format & fmt ) with( fmt ) {
    779         for ( ;; ) {   
    780                 for ( g = 0; g < 5; g += 1 ) {  // group
    781                         for ( b = 0; b < 4; b += 1 ) { // block
     745        for ( ;; ) {                                                    $\C{// for as many characters}$
     746                for ( g = 0; g < 5; g += 1 ) {          $\C{// groups of 5 blocks}$
     747                        for ( b = 0; b < 4; b += 1 ) {  $\C{// blocks of 4 characters}$
    782748                                `suspend();`
    783                                 sout | ch;              // separator
     749                                sout | ch;                                      $\C{// print character}$
    784750                        }
    785                         sout | "  ";               // separator
     751                        sout | "  ";                                    $\C{// print block separator}$
    786752                }
    787                 sout | endl;
     753                sout | endl;                                            $\C{// print group separator}$
    788754        }
    789755}
    790 void ?{}( Format & fmt ) { `resume( fmt );` }
    791 void ^?{}( Format & fmt ) with( fmt ) {
    792         if ( g != 0 || b != 0 ) sout | endl;
    793 }
    794 void format( Format & fmt ) {
     756void prt( Format & fmt, char ch ) {
     757        fmt.ch = ch;
    795758        `resume( fmt );`
    796759}
    797760int main() {
    798761        Format fmt;
    799         eof: for ( ;; ) {
    800                 sin | fmt.ch;
    801           if ( eof( sin ) ) break eof;
    802                 format( fmt );
     762        char ch;
     763        for ( ;; ) {                                                    $\C{// read until end of file}$
     764                sin | ch;                                                       $\C{// read one character}$
     765          if ( eof( sin ) ) break;                              $\C{// eof ?}$
     766                prt( fmt, ch );                                         $\C{// push character for formatting}$
    803767        }
    804768}
    805 \end{lstlisting}
    806 \end{lrbox}
    807 
    808 \newbox\myboxB
    809 \begin{lrbox}{\myboxB}
    810 \begin{lstlisting}[aboveskip=0pt,belowskip=0pt]
    811 struct Format {
    812         char ch;
    813         int g, b;
    814 };
    815 void format( struct Format * fmt ) {
    816         if ( fmt->ch != -1 ) { // not EOF
    817                 printf( "%c", fmt->ch );
    818                 fmt->b += 1;
    819                 if ( fmt->b == 4 ) {  // block
    820                         printf( "  " );      // separator
    821                         fmt->b = 0;
    822                         fmt->g += 1;
    823                 }
    824                 if ( fmt->g == 5 ) {  // group
    825                         printf( "\n" );      // separator
    826                         fmt->g = 0;
    827                 }
    828         } else {
    829                 if ( fmt->g != 0 || fmt->b != 0 ) printf( "\n" );
    830         }
    831 }
    832 int main() {
    833         struct Format fmt = { 0, 0, 0 };
    834         for ( ;; ) {
    835                 scanf( "%c", &fmt.ch );
    836           if ( feof( stdin ) ) break;
    837                 format( &fmt );
    838         }
    839         fmt.ch = -1;
    840         format( &fmt );
    841 }
    842 \end{lstlisting}
    843 \end{lrbox}
    844 \subfloat[\CFA Coroutine]{\label{f:CFAFmt}\usebox\myboxA}
    845 \qquad
    846 \subfloat[C Linearized]{\label{f:CFmt}\usebox\myboxB}
     769\end{cfa}
    847770\caption{Formatting text into lines of 5 blocks of 4 characters.}
    848771\label{f:fmt-line}
    849772\end{figure}
    850773
    851 The previous examples are \newterm{asymmetric (semi) coroutine}s because one coroutine always calls a resuming function for another coroutine, and the resumed coroutine always suspends back to its last resumer, similar to call/return for normal functions.
    852 However, there is no stack growth because @resume@/@suspend@ context switch to an existing stack frames rather than create a new one.
    853 \newterm{Symmetric (full) coroutine}s have a coroutine call a resuming function for another coroutine, which eventually forms a cycle.
    854 (The trivial cycle is a coroutine resuming itself.)
    855 This control flow is similar to recursion for normal routines, but again there is no stack growth from the context switch.
    856 
    857774\begin{figure}
    858775\centering
    859 \lstset{language=CFA,escapechar={},moredelim=**[is][\protect\color{red}]{`}{`}}% allow $
     776\lstset{language=CFA,escapechar={},moredelim=**[is][\protect\color{red}]{`}{`}}
    860777\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    861778\begin{cfa}
     
    889806        Prod prod;
    890807        Cons cons = { prod };
     808        srandom( getpid() );
    891809        start( prod, 5, cons );
    892810}
     
    925843        `resume( cons );`
    926844}
     845
    927846\end{cfa}
    928847\end{tabular}
     
    930849\label{f:ProdCons}
    931850\end{figure}
    932 
    933 Figure~\ref{f:ProdCons} shows a producer/consumer symmetric-coroutine performing bi-directional communication.
    934 Since the solution involves a full-coroutining cycle, the program main creates one coroutine in isolation, passes this coroutine to its partner, and closes the cycle at the call to @start@.
    935 The @start@ function communicates both the number of elements to be produced and the consumer into the producer's coroutine structure.
    936 Then the @resume@ to @prod@ creates @prod@'s stack with a frame for @prod@'s coroutine main at the top, and context switches to it.
    937 @prod@'s coroutine main starts, creates local variables that are retained between coroutine activations, and executes $N$ iterations, each generating two random vales, calling the consumer to deliver the values, and printing the status returned from the consumer.
    938 
    939 The producer call to @delivery@ transfers values into the consumer's communication variables, resumes the consumer, and returns the consumer status.
    940 For the first resume, @cons@'s stack is initialized, creating local variables retained between subsequent activations of the coroutine.
    941 The consumer iterates until the @done@ flag is set, prints, increments status, and calls back to the producer's @payment@ member, and on return prints the receipt from the producer and increments the money for the next payment.
    942 The call from the consumer to the producer's @payment@ member introduces the cycle between producer and consumer.
    943 When @payment@ is called, the consumer copies values into the producer's communication variable and a resume is executed.
    944 The context switch restarts the producer at the point where it was last context switched and it continues in member @delivery@ after the resume.
    945 
    946 The @delivery@ member returns the status value in @prod@'s @main@ member, where the status is printed.
    947 The loop then repeats calling @delivery@, where each call resumes the consumer coroutine.
    948 The context switch to the consumer continues in @payment@.
    949 The consumer increments and returns the receipt to the call in @cons@'s @main@ member.
    950 The loop then repeats calling @payment@, where each call resumes the producer coroutine.
    951 
    952 After iterating $N$ times, the producer calls @stop@.
    953 The @done@ flag is set to stop the consumer's execution and a resume is executed.
    954 The context switch restarts @cons@ in @payment@ and it returns with the last receipt.
    955 The consumer terminates its loops because @done@ is true, its @main@ terminates, so @cons@ transitions from a coroutine back to an object, and @prod@ reactivates after the resume in @stop@.
    956 The @stop@ member returns and @prod@'s @main@ member terminates.
    957 The program main restarts after the resume in @start@.
    958 The @start@ member returns and the program main terminates.
    959851
    960852
     
    36013493\bibliography{pl,local}
    36023494
    3603 
    36043495\end{document}
    36053496
  • doc/papers/general/Paper.tex

    rc7d8100c rca54499  
    5353%\newcommand{\TODO}[1]{\textbf{TODO}: {\itshape #1}} % TODO included
    5454\newcommand{\TODO}[1]{} % TODO elided
    55 
    56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    5755
    5856% Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
     
    165163literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1
    166164        {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 % {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    167         {<}{\textrm{\textless}}1 {>}{\textrm{\textgreater}}1
    168         {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.5ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex{\textrm{\textgreater}}}2,
     165        {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex{\textgreater}}2,
    169166moredelim=**[is][\color{red}]{`}{`},
    170167}% lstset
     
    206203
    207204The goal of the \CFA project (pronounced ``C-for-all'') is to create an extension of C that provides modern safety and productivity features while still ensuring strong backwards compatibility with C and its programmers.
    208 Prior projects have attempted similar goals but failed to honour C programming-style;
    209 for instance, adding object-oriented or functional programming with garbage collection is a non-starter for many C developers.
     205Prior projects have attempted similar goals but failed to honour C programming-style; for instance, adding object-oriented or functional programming with garbage collection is a non-starter for many C developers.
    210206Specifically, \CFA is designed to have an orthogonal feature-set based closely on the C programming paradigm, so that \CFA features can be added \emph{incrementally} to existing C code-bases, and C programmers can learn \CFA extensions on an as-needed basis, preserving investment in existing code and programmers.
    211207This paper presents a quick tour of \CFA features showing how their design avoids shortcomings of similar features in C and other C-like languages.
     
    223219
    224220\section{Introduction}
    225 
    226221The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from commercial operating-systems to hobby projects.
    227222This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more.
     
    20052000Destruction parameters are useful for specifying storage-management actions, such as de-initialize but not deallocate.}.
    20062001\begin{cfa}
    2007 struct VLA { int len, * data; };                        $\C{// variable length array of integers}$
     2002struct VLA { int len, * data; };
    20082003void ?{}( VLA & vla ) with ( vla ) { len = 10;  data = alloc( len ); }  $\C{// default constructor}$
    20092004void ^?{}( VLA & vla ) with ( vla ) { free( data ); } $\C{// destructor}$
  • doc/user/user.tex

    rc7d8100c rca54499  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sun May  6 10:33:53 2018
    14 %% Update Count     : 3319
     13%% Last Modified On : Sat Apr 14 19:04:30 2018
     14%% Update Count     : 3318
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    16421642\begin{itemize}
    16431643\item
    1644 if ©R© is an \Index{rvalue} of type ©T &$_1$...&$_r$© where $r \ge 1$ references (©&© symbols) then ©&R© has type ©T ®*®&$_{\color{red}2}$...&$_{\color{red}r}$©, \ie ©T© pointer with $r-1$ references (©&© symbols).
     1644if ©R© is an \Index{rvalue} of type ©T &$_1$...&$_r$© where $r \ge 1$ references (©&© symbols) than ©&R© has type ©T ®*®&$_{\color{red}2}$...&$_{\color{red}r}$©, \ie ©T© pointer with $r-1$ references (©&© symbols).
    16451645
    16461646\item
  • src/Common/SemanticError.cc

    rc7d8100c rca54499  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May 16 15:01:20 2018
    13 // Update Count     : 9
     12// Last Modified On : Wed May  2 18:13:37 2018
     13// Update Count     : 8
    1414//
    1515
     
    7070//-----------------------------------------------------------------------------
    7171// Semantic Error
    72 bool SemanticErrorThrow = false;
    73 
    7472SemanticErrorException::SemanticErrorException( CodeLocation location, std::string error ) {
    7573        append( location, error );
     
    9694
    9795void SemanticError( CodeLocation location, std::string error ) {
    98         SemanticErrorThrow = true;
    9996        throw SemanticErrorException(location, error);
    10097}
  • src/Common/SemanticError.h

    rc7d8100c rca54499  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May 16 15:01:23 2018
    13 // Update Count     : 30
     12// Last Modified On : Wed May  2 18:13:15 2018
     13// Update Count     : 29
    1414//
    1515
     
    2121//-----------------------------------------------------------------------------
    2222// Errors
    23 
    24 extern bool SemanticErrorThrow;
    2523
    2624__attribute__((noreturn)) void SemanticError( CodeLocation location, std::string error );
Note: See TracChangeset for help on using the changeset viewer.