source: doc/papers/concurrency/Paper.tex @ d5ccbe9

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerwith_gc
Last change on this file since d5ccbe9 was d5ccbe9, checked in by Peter A. Buhr <pabuhr@…>, 4 years ago

modify for SPE macros

  • Property mode set to 100644
File size: 146.6 KB
Line 
1% inline code ©...© (copyright symbol) emacs: C-q M-)
2% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
3% blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
4% green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
5% LaTex escape §...§ (section symbol) emacs: C-q M-'
6% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
7% math escape $...$ (dollar symbol)
8
9\documentclass[AMA,STIX1COL]{WileyNJD-v2}
10
11\articletype{RESEARCH ARTICLE}%
12
13\received{26 April 2016}
14\revised{6 June 2016}
15\accepted{6 June 2016}
16
17\raggedbottom
18
19%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
20
21% Latex packages used in the document.
22
23\usepackage[T1]{fontenc}                                        % allow Latin1 (extended ASCII) characters
24\usepackage{textcomp}
25\usepackage[latin1]{inputenc}
26
27\usepackage{epic,eepic}
28\usepackage{xspace}
29\usepackage{comment}
30\usepackage{upquote}                                            % switch curled `'" to straight
31\usepackage{listings}                                           % format program code
32\usepackage[labelformat=simple]{subfig}
33\renewcommand{\thesubfigure}{(\alph{subfigure})}
34\usepackage{siunitx}
35\sisetup{ binary-units=true }
36\input{style}                                                           % bespoke macros used in the document
37
38\hypersetup{breaklinks=true}
39\definecolor{OliveGreen}{cmyk}{0.64 0 0.95 0.40}
40\definecolor{Mahogany}{cmyk}{0 0.85 0.87 0.35}
41\definecolor{Plum}{cmyk}{0.50 1 0 0}
42
43\usepackage[pagewise]{lineno}
44\renewcommand{\linenumberfont}{\scriptsize\sffamily}
45
46\lefthyphenmin=4                                                        % hyphen only after 4 characters
47\righthyphenmin=4
48
49%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
50
51% Names used in the document.
52
53\newcommand{\CS}{C\raisebox{-0.9ex}{\large$^\sharp$}\xspace}
54
55\newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}}
56\newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}}
57\newcommand{\R}[1]{\Textbf{#1}}
58\newcommand{\B}[1]{{\Textbf[blue]{#1}}}
59\newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}}
60\newcommand{\uC}{$\mu$\CC}
61\newcommand{\cit}{\textsuperscript{[Citation Needed]}\xspace}
62\newcommand{\TODO}{{\Textbf{TODO}}}
63
64
65\newsavebox{\LstBox}
66
67%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
68
69\title{\texorpdfstring{Concurrency in \protect\CFA}{Concurrency in Cforall}}
70
71\author[1]{Thierry Delisle}
72\author[1]{Peter A. Buhr*}
73\authormark{Thierry Delisle \textsc{et al}}
74
75\address[1]{\orgdiv{David R. Cheriton School of Computer Science}, \orgname{University of Waterloo}, \orgaddress{\state{Ontario}, \country{Canada}}}
76
77\corres{*Peter A. Buhr, \email{pabuhr{\char`\@}uwaterloo.ca}}
78\presentaddress{David R. Cheriton School of Computer Science, University of Waterloo, Waterloo, ON, N2L 3G1, Canada}
79
80
81\abstract[Summary]{
82\CFA is a modern, polymorphic, \emph{non-object-oriented} extension of the C programming language.
83This paper discusses the design of the concurrency and parallelism features in \CFA, and the concurrent runtime-system that supports them.
84These features are created from scratch as ISO C lacks concurrency, relying largely on pthreads.
85Coroutines and lightweight (user) threads are introduced into the language.
86In addition, monitors are added as a high-level mechanism for mutual exclusion and synchronization.
87A unique contribution is allowing multiple monitors to be safely acquired simultaneously.
88All features respect the expectations of C programmers, while being fully integrate with the \CFA polymorphic type-system and other language features.
89Finally, experimental results are presented to validate several of the new features with other concurrent programming-languages.
90}%
91
92\keywords{concurrency, runtime, coroutines, threads, C, Cforall}
93
94
95\begin{document}
96\linenumbers                                            % comment out to turn off line numbering
97
98\maketitle
99
100% ======================================================================
101% ======================================================================
102\section{Introduction}
103% ======================================================================
104% ======================================================================
105
106This paper provides a minimal concurrency \textbf{api} that is simple, efficient and can be reused to build higher-level features.
107The simplest possible concurrency system is a thread and a lock but this low-level approach is hard to master.
108An easier approach for users is to support higher-level constructs as the basis of concurrency.
109Indeed, for highly productive concurrent programming, high-level approaches are much more popular~\cite{HPP:Study}.
110Examples are task based, message passing and implicit threading.
111The high-level approach and its minimal \textbf{api} are tested in a dialect of C, called \CFA.
112Furthermore, the proposed \textbf{api} doubles as an early definition of the \CFA language and library.
113This paper also provides an implementation of the concurrency library for \CFA as well as all the required language features added to the source-to-source translator.
114
115There are actually two problems that need to be solved in the design of concurrency for a programming language: which concurrency and which parallelism tools are available to the programmer.
116While these two concepts are often combined, they are in fact distinct, requiring different tools~\cite{Buhr05a}.
117Concurrency tools need to handle mutual exclusion and synchronization, while parallelism tools are about performance, cost and resource utilization.
118
119In the context of this paper, a \textbf{thread} is a fundamental unit of execution that runs a sequence of code, generally on a program stack.
120Having multiple simultaneous threads gives rise to concurrency and generally requires some kind of locking mechanism to ensure proper execution.
121Correspondingly, \textbf{concurrency} is defined as the concepts and challenges that occur when multiple independent (sharing memory, timing dependencies, etc.) concurrent threads are introduced.
122Accordingly, \textbf{locking} (and by extension locks) are defined as a mechanism that prevents the progress of certain threads in order to avoid problems due to concurrency.
123Finally, in this paper \textbf{parallelism} is distinct from concurrency and is defined as running multiple threads simultaneously.
124More precisely, parallelism implies \emph{actual} simultaneous execution as opposed to concurrency which only requires \emph{apparent} simultaneous execution.
125As such, parallelism is only observable in the differences in performance or, more generally, differences in timing.
126
127% ======================================================================
128% ======================================================================
129\section{\CFA Overview}
130% ======================================================================
131% ======================================================================
132
133The following is a quick introduction to the \CFA language, specifically tailored to the features needed to support concurrency.
134
135\CFA is an extension of ISO-C and therefore supports all of the same paradigms as C.
136It is a non-object-oriented system-language, meaning most of the major abstractions have either no runtime overhead or can be opted out easily.
137Like C, the basics of \CFA revolve around structures and routines, which are thin abstractions over machine code.
138The vast majority of the code produced by the \CFA translator respects memory layouts and calling conventions laid out by C.
139Interestingly, while \CFA is not an object-oriented language, lacking the concept of a receiver (e.g., {\tt this}), it does have some notion of objects\footnote{C defines the term objects as : ``region of data storage in the execution environment, the contents of which can represent
140values''~\cite[3.15]{C11}}, most importantly construction and destruction of objects.
141Most of the following code examples can be found on the \CFA website~\cite{www-cfa}.
142
143% ======================================================================
144\subsection{References}
145
146Like \CC, \CFA introduces rebind-able references providing multiple dereferencing as an alternative to pointers.
147In regards to concurrency, the semantic difference between pointers and references are not particularly relevant, but since this document uses mostly references, here is a quick overview of the semantics:
148\begin{cfacode}
149int x, *p1 = &x, **p2 = &p1, ***p3 = &p2,
150        &r1 = x,    &&r2 = r1,   &&&r3 = r2;
151***p3 = 3;                                                      //change x
152r3    = 3;                                                      //change x, ***r3
153**p3  = ...;                                            //change p1
154*p3   = ...;                                            //change p2
155int y, z, & ar[3] = {x, y, z};          //initialize array of references
156typeof( ar[1]) p;                                       //is int, referenced object type
157typeof(&ar[1]) q;                                       //is int &, reference type
158sizeof( ar[1]) == sizeof(int);          //is true, referenced object size
159sizeof(&ar[1]) == sizeof(int *);        //is true, reference size
160\end{cfacode}
161The important take away from this code example is that a reference offers a handle to an object, much like a pointer, but which is automatically dereferenced for convenience.
162
163% ======================================================================
164\subsection{Overloading}
165
166Another important feature of \CFA is function overloading as in Java and \CC, where routines with the same name are selected based on the number and type of the arguments.
167As well, \CFA uses the return type as part of the selection criteria, as in Ada~\cite{Ada}.
168For routines with multiple parameters and returns, the selection is complex.
169\begin{cfacode}
170//selection based on type and number of parameters
171void f(void);                   //(1)
172void f(char);                   //(2)
173void f(int, double);    //(3)
174f();                                    //select (1)
175f('a');                                 //select (2)
176f(3, 5.2);                              //select (3)
177
178//selection based on  type and number of returns
179char   f(int);                  //(1)
180double f(int);                  //(2)
181char   c = f(3);                //select (1)
182double d = f(4);                //select (2)
183\end{cfacode}
184This feature is particularly important for concurrency since the runtime system relies on creating different types to represent concurrency objects.
185Therefore, overloading is necessary to prevent the need for long prefixes and other naming conventions that prevent name clashes.
186As seen in section \ref{basics}, routine \code{main} is an example that benefits from overloading.
187
188% ======================================================================
189\subsection{Operators}
190Overloading also extends to operators.
191The syntax for denoting operator-overloading is to name a routine with the symbol of the operator and question marks where the arguments of the operation appear, e.g.:
192\begin{cfacode}
193int ++? (int op);                       //unary prefix increment
194int ?++ (int op);                       //unary postfix increment
195int ?+? (int op1, int op2);             //binary plus
196int ?<=?(int op1, int op2);             //binary less than
197int ?=? (int & op1, int op2);           //binary assignment
198int ?+=?(int & op1, int op2);           //binary plus-assignment
199
200struct S {int i, j;};
201S ?+?(S op1, S op2) {                           //add two structures
202        return (S){op1.i + op2.i, op1.j + op2.j};
203}
204S s1 = {1, 2}, s2 = {2, 3}, s3;
205s3 = s1 + s2;                                           //compute sum: s3 == {2, 5}
206\end{cfacode}
207While concurrency does not use operator overloading directly, this feature is more important as an introduction for the syntax of constructors.
208
209% ======================================================================
210\subsection{Constructors/Destructors}
211Object lifetime is often a challenge in concurrency. \CFA uses the approach of giving concurrent meaning to object lifetime as a means of synchronization and/or mutual exclusion.
212Since \CFA relies heavily on the lifetime of objects, constructors and destructors is a core feature required for concurrency and parallelism. \CFA uses the following syntax for constructors and destructors:
213\begin{cfacode}
214struct S {
215        size_t size;
216        int * ia;
217};
218void ?{}(S & s, int asize) {    //constructor operator
219        s.size = asize;                         //initialize fields
220        s.ia = calloc(size, sizeof(S));
221}
222void ^?{}(S & s) {                              //destructor operator
223        free(ia);                                       //de-initialization fields
224}
225int main() {
226        S x = {10}, y = {100};          //implicit calls: ?{}(x, 10), ?{}(y, 100)
227        ...                                                     //use x and y
228        ^x{}^y{};                            //explicit calls to de-initialize
229        x{20};  y{200};                         //explicit calls to reinitialize
230        ...                                                     //reuse x and y
231}                                                               //implicit calls: ^?{}(y), ^?{}(x)
232\end{cfacode}
233The language guarantees that every object and all their fields are constructed.
234Like \CC, construction of an object is automatically done on allocation and destruction of the object is done on deallocation.
235Allocation and deallocation can occur on the stack or on the heap.
236\begin{cfacode}
237{
238        struct S s = {10};      //allocation, call constructor
239        ...
240}                                               //deallocation, call destructor
241struct S * s = new();   //allocation, call constructor
242...
243delete(s);                              //deallocation, call destructor
244\end{cfacode}
245Note that like \CC, \CFA introduces \code{new} and \code{delete}, which behave like \code{malloc} and \code{free} in addition to constructing and destructing objects, after calling \code{malloc} and before calling \code{free}, respectively.
246
247% ======================================================================
248\subsection{Parametric Polymorphism}
249\label{s:ParametricPolymorphism}
250Routines in \CFA can also be reused for multiple types.
251This capability is done using the \code{forall} clauses, which allow separately compiled routines to support generic usage over multiple types.
252For example, the following sum function works for any type that supports construction from 0 and addition:
253\begin{cfacode}
254//constraint type, 0 and +
255forall(otype T | { void ?{}(T *, zero_t); T ?+?(T, T); })
256T sum(T a[ ], size_t size) {
257        T total = 0;                            //construct T from 0
258        for(size_t i = 0; i < size; i++)
259                total = total + a[i];   //select appropriate +
260        return total;
261}
262
263S sa[5];
264int i = sum(sa, 5);                             //use S's 0 construction and +
265\end{cfacode}
266
267Since writing constraints on types can become cumbersome for more constrained functions, \CFA also has the concept of traits.
268Traits are named collection of constraints that can be used both instead and in addition to regular constraints:
269\begin{cfacode}
270trait summable( otype T ) {
271        void ?{}(T *, zero_t);          //constructor from 0 literal
272        T ?+?(T, T);                            //assortment of additions
273        T ?+=?(T *, T);
274        T ++?(T *);
275        T ?++(T *);
276};
277forall( otype T | summable(T) ) //use trait
278T sum(T a[], size_t size);
279\end{cfacode}
280
281Note that the type use for assertions can be either an \code{otype} or a \code{dtype}.
282Types declared as \code{otype} refer to ``complete'' objects, i.e., objects with a size, a default constructor, a copy constructor, a destructor and an assignment operator.
283Using \code{dtype,} on the other hand, has none of these assumptions but is extremely restrictive, it only guarantees the object is addressable.
284
285% ======================================================================
286\subsection{with Clause/Statement}
287Since \CFA lacks the concept of a receiver, certain functions end up needing to repeat variable names often.
288To remove this inconvenience, \CFA provides the \code{with} statement, which opens an aggregate scope making its fields directly accessible (like Pascal).
289\begin{cfacode}
290struct S { int i, j; };
291int mem(S & this) with (this)           //with clause
292        i = 1;                                                  //this->i
293        j = 2;                                                  //this->j
294}
295int foo() {
296        struct S1 { ... } s1;
297        struct S2 { ... } s2;
298        with (s1)                                               //with statement
299        {
300                //access fields of s1 without qualification
301                with (s2)                                       //nesting
302                {
303                        //access fields of s1 and s2 without qualification
304                }
305        }
306        with (s1, s2)                                   //scopes open in parallel
307        {
308                //access fields of s1 and s2 without qualification
309        }
310}
311\end{cfacode}
312
313For more information on \CFA see \cite{cforall-ug,rob-thesis,www-cfa}.
314
315% ======================================================================
316% ======================================================================
317\section{Concurrency Basics}\label{basics}
318% ======================================================================
319% ======================================================================
320Before any detailed discussion of the concurrency and parallelism in \CFA, it is important to describe the basics of concurrency and how they are expressed in \CFA user code.
321
322\section{Basics of concurrency}
323At its core, concurrency is based on having multiple call-stacks and scheduling among threads of execution executing on these stacks.
324Concurrency without parallelism only requires having multiple call stacks (or contexts) for a single thread of execution.
325
326Execution with a single thread and multiple stacks where the thread is self-scheduling deterministically across the stacks is called coroutining.
327Execution with a single 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.
328
329Therefore, a minimal concurrency system can be achieved by creating coroutines (see Section \ref{coroutine}), which instead of context-switching among each other, always ask an oracle where to context-switch next.
330While coroutines can execute on the caller's stack-frame, stack-full coroutines allow full generality and are sufficient as the basis for concurrency.
331The aforementioned oracle is a scheduler and the whole system now follows a cooperative threading-model (a.k.a., non-preemptive scheduling).
332The 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.
333In any case, a subset of concurrency related challenges start to appear.
334For the complete set of concurrency challenges to occur, the only feature missing is preemption.
335
336A scheduler introduces order of execution uncertainty, while preemption introduces uncertainty about where context switches occur.
337Mutual exclusion and synchronization are ways of limiting non-determinism in a concurrent system.
338Now 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.
339Optimal performance in concurrent applications is often obtained by having as much non-determinism as correctness allows.
340
341\section{\protect\CFA's Thread Building Blocks}
342One 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.
343As such, library support for threading is far from widespread.
344At the time of writing the paper, neither \texttt{gcc} nor \texttt{clang} support ``threads.h'' in their respective standard libraries.}.
345On 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.
346As 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.
347And being a system-level language means programmers expect to choose precisely which features they need and which cost they are willing to pay.
348
349\section{Coroutines: A Stepping Stone}\label{coroutine}
350While the main focus of this proposal is concurrency and parallelism, it is important to address coroutines, which are actually a significant building block of a concurrency system. \textbf{Coroutine}s are generalized routines which have predefined points where execution is suspended and can be resumed at a later time.
351Therefore, they need to deal with context switches and other context-management operations.
352This proposal includes coroutines both as an intermediate step for the implementation of threads, and a first-class feature of \CFA.
353Furthermore, many design challenges of threads are at least partially present in designing coroutines, which makes the design effort that much more relevant.
354The core \textbf{api} of coroutines revolves around two features: independent call-stacks and \code{suspend}/\code{resume}.
355
356\begin{table}
357\begin{center}
358\begin{tabular}{c @{\hskip 0.025in}|@{\hskip 0.025in} c @{\hskip 0.025in}|@{\hskip 0.025in} c}
359\begin{ccode}[tabsize=2]
360//Using callbacks
361void fibonacci_func(
362        int n,
363        void (*callback)(int)
364) {
365        int first = 0;
366        int second = 1;
367        int next, i;
368        for(i = 0; i < n; i++)
369        {
370                if(i <= 1)
371                        next = i;
372                else {
373                        next = f1 + f2;
374                        f1 = f2;
375                        f2 = next;
376                }
377                callback(next);
378        }
379}
380
381int main() {
382        void print_fib(int n) {
383                printf("%d\n", n);
384        }
385
386        fibonacci_func(
387                10, print_fib
388        );
389
390
391
392}
393\end{ccode}&\begin{ccode}[tabsize=2]
394//Using output array
395void fibonacci_array(
396        int n,
397        int* array
398) {
399        int f1 = 0; int f2 = 1;
400        int next, i;
401        for(i = 0; i < n; i++)
402        {
403                if(i <= 1)
404                        next = i;
405                else {
406                        next = f1 + f2;
407                        f1 = f2;
408                        f2 = next;
409                }
410                array[i] = next;
411        }
412}
413
414
415int main() {
416        int a[10];
417
418        fibonacci_func(
419                10, a
420        );
421
422        for(int i=0;i<10;i++){
423                printf("%d\n", a[i]);
424        }
425
426}
427\end{ccode}&\begin{ccode}[tabsize=2]
428//Using external state
429typedef struct {
430        int f1, f2;
431} Iterator_t;
432
433int fibonacci_state(
434        Iterator_t* it
435) {
436        int f;
437        f = it->f1 + it->f2;
438        it->f2 = it->f1;
439        it->f1 = max(f,1);
440        return f;
441}
442
443
444
445
446
447
448
449int main() {
450        Iterator_t it={0,0};
451
452        for(int i=0;i<10;i++){
453                printf("%d\n",
454                        fibonacci_state(
455                                &it
456                        );
457                );
458        }
459
460}
461\end{ccode}
462\end{tabular}
463\end{center}
464\caption{Different implementations of a Fibonacci sequence generator in C.}
465\label{lst:fibonacci-c}
466\end{table}
467
468A good example of a problem made easier with coroutines is generators, e.g., generating the Fibonacci sequence.
469This problem comes with the challenge of decoupling how a sequence is generated and how it is used.
470Listing \ref{lst:fibonacci-c} shows conventional approaches to writing generators in C.
471All three of these approach suffer from strong coupling.
472The left and centre approaches require that the generator have knowledge of how the sequence is used, while the rightmost approach requires holding internal state between calls on behalf of the generator and makes it much harder to handle corner cases like the Fibonacci seed.
473
474Listing \ref{lst:fibonacci-cfa} is an example of a solution to the Fibonacci problem using \CFA coroutines, where the coroutine stack holds sufficient state for the next generation.
475This solution has the advantage of having very strong decoupling between how the sequence is generated and how it is used.
476Indeed, this version is as easy to use as the \code{fibonacci_state} solution, while the implementation is very similar to the \code{fibonacci_func} example.
477
478\begin{figure}
479\begin{cfacode}[caption={Implementation of Fibonacci using coroutines},label={lst:fibonacci-cfa}]
480coroutine Fibonacci {
481        int fn; //used for communication
482};
483
484void ?{}(Fibonacci& this) { //constructor
485        this.fn = 0;
486}
487
488//main automatically called on first resume
489void main(Fibonacci& this) with (this) {
490        int fn1, fn2;           //retained between resumes
491        fn  = 0;
492        fn1 = fn;
493        suspend(this);          //return to last resume
494
495        fn  = 1;
496        fn2 = fn1;
497        fn1 = fn;
498        suspend(this);          //return to last resume
499
500        for ( ;; ) {
501                fn  = fn1 + fn2;
502                fn2 = fn1;
503                fn1 = fn;
504                suspend(this);  //return to last resume
505        }
506}
507
508int next(Fibonacci& this) {
509        resume(this); //transfer to last suspend
510        return this.fn;
511}
512
513void main() { //regular program main
514        Fibonacci f1, f2;
515        for ( int i = 1; i <= 10; i += 1 ) {
516                sout | next( f1 ) | next( f2 ) | endl;
517        }
518}
519\end{cfacode}
520\end{figure}
521
522Listing \ref{lst:fmt-line} shows the \code{Format} coroutine for restructuring text into groups of character blocks of fixed size.
523The 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.
524
525\begin{figure}
526\begin{cfacode}[tabsize=3,caption={Formatting text into lines of 5 blocks of 4 characters.},label={lst:fmt-line}]
527//format characters into blocks of 4 and groups of 5 blocks per line
528coroutine Format {
529        char ch;                                                                        //used for communication
530        int g, b;                                                               //global because used in destructor
531};
532
533void  ?{}(Format& fmt) {
534        resume( fmt );                                                  //prime (start) coroutine
535}
536
537void ^?{}(Format& fmt) with fmt {
538        if ( fmt.g != 0 || fmt.b != 0 )
539        sout | endl;
540}
541
542void main(Format& fmt) with fmt {
543        for ( ;; ) {                                                    //for as many characters
544                for(g = 0; g < 5; g++) {                //groups of 5 blocks
545                        for(b = 0; b < 4; fb++) {       //blocks of 4 characters
546                                suspend();
547                                sout | ch;                                      //print character
548                        }
549                        sout | "  ";                                    //print block separator
550                }
551                sout | endl;                                            //print group separator
552        }
553}
554
555void prt(Format & fmt, char ch) {
556        fmt.ch = ch;
557        resume(fmt);
558}
559
560int main() {
561        Format fmt;
562        char ch;
563        Eof: for ( ;; ) {                                               //read until end of file
564                sin | ch;                                                       //read one character
565                if(eof(sin)) break Eof;                 //eof ?
566                prt(fmt, ch);                                           //push character for formatting
567        }
568}
569\end{cfacode}
570\end{figure}
571
572\subsection{Construction}
573One important design challenge for implementing coroutines and threads (shown in section \ref{threads}) is that the runtime system needs to run code after the user-constructor runs to connect the fully constructed object into the system.
574In the case of coroutines, this challenge is simpler since there is no non-determinism from preemption or scheduling.
575However, the underlying challenge remains the same for coroutines and threads.
576
577The runtime system needs to create the coroutine's stack and, more importantly, prepare it for the first resumption.
578The timing of the creation is non-trivial since users expect both to have fully constructed objects once execution enters the coroutine main and to be able to resume the coroutine from the constructor.
579There are several solutions to this problem but the chosen option effectively forces the design of the coroutine.
580
581Furthermore, \CFA faces an extra challenge as polymorphic routines create invisible thunks when cast to non-polymorphic routines and these thunks have function scope.
582For example, the following code, while looking benign, can run into undefined behaviour because of thunks:
583
584\begin{cfacode}
585//async: Runs function asynchronously on another thread
586forall(otype T)
587extern void async(void (*func)(T*), T* obj);
588
589forall(otype T)
590void noop(T*) {}
591
592void bar() {
593        int a;
594        async(noop, &a); //start thread running noop with argument a
595}
596\end{cfacode}
597
598The generated C code\footnote{Code trimmed down for brevity} creates a local thunk to hold type information:
599
600\begin{ccode}
601extern void async(/* omitted */, void (*func)(void*), void* obj);
602
603void noop(/* omitted */, void* obj){}
604
605void bar(){
606        int a;
607        void _thunk0(int* _p0){
608                /* omitted */
609                noop(/* omitted */, _p0);
610        }
611        /* omitted */
612        async(/* omitted */, ((void (*)(void*))(&_thunk0)), (&a));
613}
614\end{ccode}
615The problem in this example is a storage management issue, the function pointer \code{_thunk0} is only valid until the end of the block, which limits the viable solutions because storing the function pointer for too long causes undefined behaviour; i.e., the stack-based thunk being destroyed before it can be used.
616This challenge is an extension of challenges that come with second-class routines.
617Indeed, GCC nested routines also have the limitation that nested routine cannot be passed outside of the declaration scope.
618The case of coroutines and threads is simply an extension of this problem to multiple call stacks.
619
620\subsection{Alternative: Composition}
621One solution to this challenge is to use composition/containment, where coroutine fields are added to manage the coroutine.
622
623\begin{cfacode}
624struct Fibonacci {
625        int fn; //used for communication
626        coroutine c; //composition
627};
628
629void FibMain(void*) {
630        //...
631}
632
633void ?{}(Fibonacci& this) {
634        this.fn = 0;
635        //Call constructor to initialize coroutine
636        (this.c){myMain};
637}
638\end{cfacode}
639The downside of this approach is that users need to correctly construct the coroutine handle before using it.
640Like any other objects, the user must carefully choose construction order to prevent usage of objects not yet constructed.
641However, in the case of coroutines, users must also pass to the coroutine information about the coroutine main, like in the previous example.
642This opens the door for user errors and requires extra runtime storage to pass at runtime information that can be known statically.
643
644\subsection{Alternative: Reserved keyword}
645The next alternative is to use language support to annotate coroutines as follows:
646
647\begin{cfacode}
648coroutine Fibonacci {
649        int fn; //used for communication
650};
651\end{cfacode}
652The \code{coroutine} keyword means the compiler can find and inject code where needed.
653The downside of this approach is that it makes coroutine a special case in the language.
654Users wanting to extend coroutines or build their own for various reasons can only do so in ways offered by the language.
655Furthermore, implementing coroutines without language supports also displays the power of the programming language used.
656While this is ultimately the option used for idiomatic \CFA code, coroutines and threads can still be constructed by users without using the language support.
657The reserved keywords are only present to improve ease of use for the common cases.
658
659\subsection{Alternative: Lambda Objects}
660
661For coroutines as for threads, many implementations are based on routine pointers or function objects~\cite{Butenhof97, C++14, MS:VisualC++, BoostCoroutines15}.
662For example, Boost implements coroutines in terms of four functor object types:
663\begin{cfacode}
664asymmetric_coroutine<>::pull_type
665asymmetric_coroutine<>::push_type
666symmetric_coroutine<>::call_type
667symmetric_coroutine<>::yield_type
668\end{cfacode}
669Often, the canonical threading paradigm in languages is based on function pointers, \texttt{pthread} being one of the most well-known examples.
670The main problem of this approach is that the thread usage is limited to a generic handle that must otherwise be wrapped in a custom type.
671Since the custom type is simple to write in \CFA and solves several issues, added support for routine/lambda based coroutines adds very little.
672
673A variation of this would be to use a simple function pointer in the same way \texttt{pthread} does for threads:
674\begin{cfacode}
675void foo( coroutine_t cid, void* arg ) {
676        int* value = (int*)arg;
677        //Coroutine body
678}
679
680int main() {
681        int value = 0;
682        coroutine_t cid = coroutine_create( &foo, (void*)&value );
683        coroutine_resume( &cid );
684}
685\end{cfacode}
686This semantics is more common for thread interfaces but coroutines work equally well.
687As discussed in section \ref{threads}, this approach is superseded by static approaches in terms of expressivity.
688
689\subsection{Alternative: Trait-Based Coroutines}
690
691Finally, the underlying approach, which is the one closest to \CFA idioms, is to use trait-based lazy coroutines.
692This approach defines a coroutine as anything that satisfies the trait \code{is_coroutine} (as defined below) and is used as a coroutine.
693
694\begin{cfacode}
695trait is_coroutine(dtype T) {
696      void main(T& this);
697      coroutine_desc* get_coroutine(T& this);
698};
699
700forall( dtype T | is_coroutine(T) ) void suspend(T&);
701forall( dtype T | is_coroutine(T) ) void resume (T&);
702\end{cfacode}
703This ensures that an object is not a coroutine until \code{resume} is called on the object.
704Correspondingly, any object that is passed to \code{resume} is a coroutine since it must satisfy the \code{is_coroutine} trait to compile.
705The advantage of this approach is that users can easily create different types of coroutines, for example, changing the memory layout of a coroutine is trivial when implementing the \code{get_coroutine} routine.
706The \CFA keyword \code{coroutine} simply has the effect of implementing the getter and forward declarations required for users to implement the main routine.
707
708\begin{center}
709\begin{tabular}{c c c}
710\begin{cfacode}[tabsize=3]
711coroutine MyCoroutine {
712        int someValue;
713};
714\end{cfacode} & == & \begin{cfacode}[tabsize=3]
715struct MyCoroutine {
716        int someValue;
717        coroutine_desc __cor;
718};
719
720static inline
721coroutine_desc* get_coroutine(
722        struct MyCoroutine& this
723) {
724        return &this.__cor;
725}
726
727void main(struct MyCoroutine* this);
728\end{cfacode}
729\end{tabular}
730\end{center}
731
732The combination of these two approaches allows users new to coroutining and concurrency to have an easy and concise specification, while more advanced users have tighter control on memory layout and initialization.
733
734\section{Thread Interface}\label{threads}
735The basic building blocks of multithreading in \CFA are \textbf{cfathread}.
736Both user and kernel threads are supported, where user threads are the concurrency mechanism and kernel threads are the parallel mechanism.
737User threads offer a flexible and lightweight interface.
738A thread can be declared using a struct declaration \code{thread} as follows:
739
740\begin{cfacode}
741thread foo {};
742\end{cfacode}
743
744As for coroutines, the keyword is a thin wrapper around a \CFA trait:
745
746\begin{cfacode}
747trait is_thread(dtype T) {
748      void ^?{}(T & mutex this);
749      void main(T & this);
750      thread_desc* get_thread(T & this);
751};
752\end{cfacode}
753
754Obviously, for this thread implementation to be useful it must run some user code.
755Several other threading interfaces use a function-pointer representation as the interface of threads (for example \Csharp~\cite{Csharp} and Scala~\cite{Scala}).
756However, this proposal considers that statically tying a \code{main} routine to a thread supersedes this approach.
757Since the \code{main} routine is already a special routine in \CFA (where the program begins), it is a natural extension of the semantics to use overloading to declare mains for different threads (the normal main being the main of the initial thread).
758As such the \code{main} routine of a thread can be defined as
759\begin{cfacode}
760thread foo {};
761
762void main(foo & this) {
763        sout | "Hello World!" | endl;
764}
765\end{cfacode}
766
767In this example, threads of type \code{foo} start execution in the \code{void main(foo &)} routine, which prints \code{"Hello World!".} While this paper encourages this approach to enforce strongly typed programming, users may prefer to use the routine-based thread semantics for the sake of simplicity.
768With the static semantics it is trivial to write a thread type that takes a function pointer as a parameter and executes it on its stack asynchronously.
769\begin{cfacode}
770typedef void (*voidFunc)(int);
771
772thread FuncRunner {
773        voidFunc func;
774        int arg;
775};
776
777void ?{}(FuncRunner & this, voidFunc inFunc, int arg) {
778        this.func = inFunc;
779        this.arg  = arg;
780}
781
782void main(FuncRunner & this) {
783        //thread starts here and runs the function
784        this.func( this.arg );
785}
786
787void hello(/*unused*/ int) {
788        sout | "Hello World!" | endl;
789}
790
791int main() {
792        FuncRunner f = {hello, 42};
793        return 0?
794}
795\end{cfacode}
796
797A consequence of the strongly typed approach to main is that memory layout of parameters and return values to/from a thread are now explicitly specified in the \textbf{api}.
798
799Of course, for threads to be useful, it must be possible to start and stop threads and wait for them to complete execution.
800While using an \textbf{api} such as \code{fork} and \code{join} is relatively common in the literature, such an interface is unnecessary.
801Indeed, the simplest approach is to use \textbf{raii} principles and have threads \code{fork} after the constructor has completed and \code{join} before the destructor runs.
802\begin{cfacode}
803thread World;
804
805void main(World & this) {
806        sout | "World!" | endl;
807}
808
809void main() {
810        World w;
811        //Thread forks here
812
813        //Printing "Hello " and "World!" are run concurrently
814        sout | "Hello " | endl;
815
816        //Implicit join at end of scope
817}
818\end{cfacode}
819
820This semantic has several advantages over explicit semantics: a thread is always started and stopped exactly once, users cannot make any programming errors, and it naturally scales to multiple threads meaning basic synchronization is very simple.
821
822\begin{cfacode}
823thread MyThread {
824        //...
825};
826
827//main
828void main(MyThread& this) {
829        //...
830}
831
832void foo() {
833        MyThread thrds[10];
834        //Start 10 threads at the beginning of the scope
835
836        DoStuff();
837
838        //Wait for the 10 threads to finish
839}
840\end{cfacode}
841
842However, one of the drawbacks of this approach is that threads always form a tree where nodes must always outlive their children, i.e., they are always destroyed in the opposite order of construction because of C scoping rules.
843This restriction is relaxed by using dynamic allocation, so threads can outlive the scope in which they are created, much like dynamically allocating memory lets objects outlive the scope in which they are created.
844
845\begin{cfacode}
846thread MyThread {
847        //...
848};
849
850void main(MyThread& this) {
851        //...
852}
853
854void foo() {
855        MyThread* long_lived;
856        {
857                //Start a thread at the beginning of the scope
858                MyThread short_lived;
859
860                //create another thread that will outlive the thread in this scope
861                long_lived = new MyThread;
862
863                DoStuff();
864
865                //Wait for the thread short_lived to finish
866        }
867        DoMoreStuff();
868
869        //Now wait for the long_lived to finish
870        delete long_lived;
871}
872\end{cfacode}
873
874
875% ======================================================================
876% ======================================================================
877\section{Concurrency}
878% ======================================================================
879% ======================================================================
880Several tools can be used to solve concurrency challenges.
881Since many of these challenges appear with the use of mutable shared state, some languages and libraries simply disallow mutable shared state (Erlang~\cite{Erlang}, Haskell~\cite{Haskell}, Akka (Scala)~\cite{Akka}).
882In these paradigms, interaction among concurrent objects relies on message passing~\cite{Thoth,Harmony,V-Kernel} or other paradigms closely relate to networking concepts (channels~\cite{CSP,Go} for example).
883However, in languages that use routine calls as their core abstraction mechanism, these approaches force a clear distinction between concurrent and non-concurrent paradigms (i.e., message passing versus routine calls).
884This distinction in turn means that, in order to be effective, programmers need to learn two sets of design patterns.
885While this distinction can be hidden away in library code, effective use of the library still has to take both paradigms into account.
886
887Approaches based on shared memory are more closely related to non-concurrent paradigms since they often rely on basic constructs like routine calls and shared objects.
888At the lowest level, concurrent paradigms are implemented as atomic operations and locks.
889Many such mechanisms have been proposed, including semaphores~\cite{Dijkstra68b} and path expressions~\cite{Campbell74}.
890However, for productivity reasons it is desirable to have a higher-level construct be the core concurrency paradigm~\cite{HPP:Study}.
891
892An approach that is worth mentioning because it is gaining in popularity is transactional memory~\cite{Herlihy93}.
893While this approach is even pursued by system languages like \CC~\cite{Cpp-Transactions}, the performance and feature set is currently too restrictive to be the main concurrency paradigm for system languages, which is why it was rejected as the core paradigm for concurrency in \CFA.
894
895One of the most natural, elegant, and efficient mechanisms for synchronization and communication, especially for shared-memory systems, is the \emph{monitor}.
896Monitors were first proposed by Brinch Hansen~\cite{Hansen73} and later described and extended by C.A.R.~Hoare~\cite{Hoare74}.
897Many programming languages---e.g., Concurrent Pascal~\cite{ConcurrentPascal}, Mesa~\cite{Mesa}, Modula~\cite{Modula-2}, Turing~\cite{Turing:old}, Modula-3~\cite{Modula-3}, NeWS~\cite{NeWS}, Emerald~\cite{Emerald}, \uC~\cite{Buhr92a} and Java~\cite{Java}---provide monitors as explicit language constructs.
898In addition, operating-system kernels and device drivers have a monitor-like structure, although they often use lower-level primitives such as semaphores or locks to simulate monitors.
899For these reasons, this project proposes monitors as the core concurrency construct.
900
901\section{Basics}
902Non-determinism requires concurrent systems to offer support for mutual-exclusion and synchronization.
903Mutual-exclusion is the concept that only a fixed number of threads can access a critical section at any given time, where a critical section is a group of instructions on an associated portion of data that requires the restricted access.
904On the other hand, synchronization enforces relative ordering of execution and synchronization tools provide numerous mechanisms to establish timing relationships among threads.
905
906\subsection{Mutual-Exclusion}
907As mentioned above, mutual-exclusion is the guarantee that only a fix number of threads can enter a critical section at once.
908However, many solutions exist for mutual exclusion, which vary in terms of performance, flexibility and ease of use.
909Methods range from low-level locks, which are fast and flexible but require significant attention to be correct, to  higher-level concurrency techniques, which sacrifice some performance in order to improve ease of use.
910Ease of use comes by either guaranteeing some problems cannot occur (e.g., being deadlock free) or by offering a more explicit coupling between data and corresponding critical section.
911For example, the \CC \code{std::atomic<T>} offers an easy way to express mutual-exclusion on a restricted set of operations (e.g., reading/writing large types atomically).
912Another challenge with low-level locks is composability.
913Locks have restricted composability because it takes careful organizing for multiple locks to be used while preventing deadlocks.
914Easing composability is another feature higher-level mutual-exclusion mechanisms often offer.
915
916\subsection{Synchronization}
917As with mutual-exclusion, low-level synchronization primitives often offer good performance and good flexibility at the cost of ease of use.
918Again, higher-level mechanisms often simplify usage by adding either better coupling between synchronization and data (e.g., message passing) or offering a simpler solution to otherwise involved challenges.
919As mentioned above, synchronization can be expressed as guaranteeing that event \textit{X} always happens before \textit{Y}.
920Most of the time, synchronization happens within a critical section, where threads must acquire mutual-exclusion in a certain order.
921However, it may also be desirable to guarantee that event \textit{Z} does not occur between \textit{X} and \textit{Y}.
922Not satisfying this property is called \textbf{barging}.
923For example, where event \textit{X} tries to effect event \textit{Y} but another thread acquires the critical section and emits \textit{Z} before \textit{Y}.
924The classic example is the thread that finishes using a resource and unblocks a thread waiting to use the resource, but the unblocked thread must compete to acquire the resource.
925Preventing or detecting barging is an involved challenge with low-level locks, which can be made much easier by higher-level constructs.
926This challenge is often split into two different methods, barging avoidance and barging prevention.
927Algorithms that use flag variables to detect barging threads are said to be using barging avoidance, while algorithms that baton-pass locks~\cite{Andrews89} between threads instead of releasing the locks are said to be using barging prevention.
928
929% ======================================================================
930% ======================================================================
931\section{Monitors}
932% ======================================================================
933% ======================================================================
934A \textbf{monitor} is a set of routines that ensure mutual-exclusion when accessing shared state.
935More precisely, a monitor is a programming technique that associates mutual-exclusion to routine scopes, as opposed to mutex locks, where mutual-exclusion is defined by lock/release calls independently of any scoping of the calling routine.
936This strong association eases readability and maintainability, at the cost of flexibility.
937Note that both monitors and mutex locks, require an abstract handle to identify them.
938This concept is generally associated with object-oriented languages like Java~\cite{Java} or \uC~\cite{uC++book} but does not strictly require OO semantics.
939The only requirement is the ability to declare a handle to a shared object and a set of routines that act on it:
940\begin{cfacode}
941typedef /*some monitor type*/ monitor;
942int f(monitor & m);
943
944int main() {
945        monitor m;  //Handle m
946        f(m);       //Routine using handle
947}
948\end{cfacode}
949
950% ======================================================================
951% ======================================================================
952\subsection{Call Semantics} \label{call}
953% ======================================================================
954% ======================================================================
955The above monitor example displays some of the intrinsic characteristics.
956First, it is necessary to use pass-by-reference over pass-by-value for monitor routines.
957This semantics is important, because at their core, monitors are implicit mutual-exclusion objects (locks), and these objects cannot be copied.
958Therefore, monitors are non-copy-able objects (\code{dtype}).
959
960Another aspect to consider is when a monitor acquires its mutual exclusion.
961For example, a monitor may need to be passed through multiple helper routines that do not acquire the monitor mutual-exclusion on entry.
962Passthrough can occur for generic helper routines (\code{swap}, \code{sort}, etc.) or specific helper routines like the following to implement an atomic counter:
963
964\begin{cfacode}
965monitor counter_t { /*...see section $\ref{data}$...*/ };
966
967void ?{}(counter_t & nomutex this); //constructor
968size_t ++?(counter_t & mutex this); //increment
969
970//need for mutex is platform dependent
971void ?{}(size_t * this, counter_t & mutex cnt); //conversion
972\end{cfacode}
973This counter is used as follows:
974\begin{center}
975\begin{tabular}{c @{\hskip 0.35in} c @{\hskip 0.35in} c}
976\begin{cfacode}
977//shared counter
978counter_t cnt1, cnt2;
979
980//multiple threads access counter
981thread 1 : cnt1++; cnt2++;
982thread 2 : cnt1++; cnt2++;
983thread 3 : cnt1++; cnt2++;
984        ...
985thread N : cnt1++; cnt2++;
986\end{cfacode}
987\end{tabular}
988\end{center}
989Notice how the counter is used without any explicit synchronization and yet supports thread-safe semantics for both reading and writing, which is similar in usage to the \CC template \code{std::atomic}.
990
991Here, the constructor (\code{?\{\}}) uses the \code{nomutex} keyword to signify that it does not acquire the monitor mutual-exclusion when constructing.
992This semantics is because an object not yet con\-structed should never be shared and therefore does not require mutual exclusion.
993Furthermore, it allows the implementation greater freedom when it initializes the monitor locking.
994The prefix increment operator uses \code{mutex} to protect the incrementing process from race conditions.
995Finally, there is a conversion operator from \code{counter_t} to \code{size_t}.
996This conversion may or may not require the \code{mutex} keyword depending on whether or not reading a \code{size_t} is an atomic operation.
997
998For maximum usability, monitors use \textbf{multi-acq} semantics, which means a single thread can acquire the same monitor multiple times without deadlock.
999For example, listing \ref{fig:search} uses recursion and \textbf{multi-acq} to print values inside a binary tree.
1000\begin{figure}
1001\begin{cfacode}[caption={Recursive printing algorithm using \textbf{multi-acq}.},label={fig:search}]
1002monitor printer { ... };
1003struct tree {
1004        tree * left, right;
1005        char * value;
1006};
1007void print(printer & mutex p, char * v);
1008
1009void print(printer & mutex p, tree * t) {
1010        print(p, t->value);
1011        print(p, t->left );
1012        print(p, t->right);
1013}
1014\end{cfacode}
1015\end{figure}
1016
1017Having both \code{mutex} and \code{nomutex} keywords can be redundant, depending on the meaning of a routine having neither of these keywords.
1018For example, it is reasonable that it should default to the safest option (\code{mutex}) when given a routine without qualifiers \code{void foo(counter_t & this)}, whereas assuming \code{nomutex} is unsafe and may cause subtle errors.
1019On the other hand, \code{nomutex} is the ``normal'' parameter behaviour, it effectively states explicitly that ``this routine is not special''.
1020Another alternative is making exactly one of these keywords mandatory, which provides the same semantics but without the ambiguity of supporting routines with neither keyword.
1021Mandatory keywords would also have the added benefit of being self-documented but at the cost of extra typing.
1022While there are several benefits to mandatory keywords, they do bring a few challenges.
1023Mandatory keywords in \CFA would imply that the compiler must know without doubt whether or not a parameter is a monitor or not.
1024Since \CFA relies heavily on traits as an abstraction mechanism, the distinction between a type that is a monitor and a type that looks like a monitor can become blurred.
1025For this reason, \CFA only has the \code{mutex} keyword and uses no keyword to mean \code{nomutex}.
1026
1027The next semantic decision is to establish when \code{mutex} may be used as a type qualifier.
1028Consider the following declarations:
1029\begin{cfacode}
1030int f1(monitor & mutex m);
1031int f2(const monitor & mutex m);
1032int f3(monitor ** mutex m);
1033int f4(monitor * mutex m []);
1034int f5(graph(monitor *) & mutex m);
1035\end{cfacode}
1036The problem is to identify which object(s) should be acquired.
1037Furthermore, each object needs to be acquired only once.
1038In the case of simple routines like \code{f1} and \code{f2} it is easy to identify an exhaustive list of objects to acquire on entry.
1039Adding indirections (\code{f3}) still allows the compiler and programmer to identify which object is acquired.
1040However, adding in arrays (\code{f4}) makes it much harder.
1041Array lengths are not necessarily known in C, and even then, making sure objects are only acquired once becomes none-trivial.
1042This problem can be extended to absurd limits like \code{f5}, which uses a graph of monitors.
1043To make the issue tractable, this project imposes the requirement that a routine may only acquire one monitor per parameter and it must be the type of the parameter with at most one level of indirection (ignoring potential qualifiers).
1044Also note that while routine \code{f3} can be supported, meaning that monitor \code{**m} is acquired, passing an array to this routine would be type-safe and yet result in undefined behaviour because only the first element of the array is acquired.
1045However, this ambiguity is part of the C type-system with respects to arrays.
1046For this reason, \code{mutex} is disallowed in the context where arrays may be passed:
1047\begin{cfacode}
1048int f1(monitor & mutex m);    //Okay : recommended case
1049int f2(monitor * mutex m);    //Not Okay : Could be an array
1050int f3(monitor mutex m []);  //Not Okay : Array of unknown length
1051int f4(monitor ** mutex m);   //Not Okay : Could be an array
1052int f5(monitor * mutex m []); //Not Okay : Array of unknown length
1053\end{cfacode}
1054Note that not all array functions are actually distinct in the type system.
1055However, even if the code generation could tell the difference, the extra information is still not sufficient to extend meaningfully the monitor call semantic.
1056
1057Unlike object-oriented monitors, where calling a mutex member \emph{implicitly} acquires mutual-exclusion of the receiver object, \CFA uses an explicit mechanism to specify the object that acquires mutual-exclusion.
1058A consequence of this approach is that it extends naturally to multi-monitor calls.
1059\begin{cfacode}
1060int f(MonitorA & mutex a, MonitorB & mutex b);
1061
1062MonitorA a;
1063MonitorB b;
1064f(a,b);
1065\end{cfacode}
1066While OO monitors could be extended with a mutex qualifier for multiple-monitor calls, no example of this feature could be found.
1067The capability to acquire multiple locks before entering a critical section is called \emph{\textbf{bulk-acq}}.
1068In practice, writing multi-locking routines that do not lead to deadlocks is tricky.
1069Having language support for such a feature is therefore a significant asset for \CFA.
1070In the case presented above, \CFA guarantees that the order of acquisition is consistent across calls to different routines using the same monitors as arguments.
1071This consistent ordering means acquiring multiple monitors is safe from deadlock when using \textbf{bulk-acq}.
1072However, users can still force the acquiring order.
1073For example, notice which routines use \code{mutex}/\code{nomutex} and how this affects acquiring order:
1074\begin{cfacode}
1075void foo(A& mutex a, B& mutex b) { //acquire a & b
1076        ...
1077}
1078
1079void bar(A& mutex a, B& /*nomutex*/ b) { //acquire a
1080        ... foo(a, b); ... //acquire b
1081}
1082
1083void baz(A& /*nomutex*/ a, B& mutex b) { //acquire b
1084        ... foo(a, b); ... //acquire a
1085}
1086\end{cfacode}
1087The \textbf{multi-acq} monitor lock allows a monitor lock to be acquired by both \code{bar} or \code{baz} and acquired again in \code{foo}.
1088In the calls to \code{bar} and \code{baz} the monitors are acquired in opposite order.
1089
1090However, such use leads to lock acquiring order problems.
1091In the example above, the user uses implicit ordering in the case of function \code{foo} but explicit ordering in the case of \code{bar} and \code{baz}.
1092This subtle difference means that calling these routines concurrently may lead to deadlock and is therefore undefined behaviour.
1093As shown~\cite{Lister77}, solving this problem requires:
1094\begin{enumerate}
1095        \item Dynamically tracking the monitor-call order.
1096        \item Implement rollback semantics.
1097\end{enumerate}
1098While the first requirement is already a significant constraint on the system, implementing a general rollback semantics in a C-like language is still prohibitively complex~\cite{Dice10}.
1099In \CFA, users simply need to be careful when acquiring multiple monitors at the same time or only use \textbf{bulk-acq} of all the monitors.
1100While \CFA provides only a partial solution, most systems provide no solution and the \CFA partial solution handles many useful cases.
1101
1102For example, \textbf{multi-acq} and \textbf{bulk-acq} can be used together in interesting ways:
1103\begin{cfacode}
1104monitor bank { ... };
1105
1106void deposit( bank & mutex b, int deposit );
1107
1108void transfer( bank & mutex mybank, bank & mutex yourbank, int me2you) {
1109        deposit( mybank, -me2you );
1110        deposit( yourbank, me2you );
1111}
1112\end{cfacode}
1113This example shows a trivial solution to the bank-account transfer problem~\cite{BankTransfer}.
1114Without \textbf{multi-acq} and \textbf{bulk-acq}, the solution to this problem is much more involved and requires careful engineering.
1115
1116\subsection{\code{mutex} statement} \label{mutex-stmt}
1117
1118The call semantics discussed above have one software engineering issue: only a routine can acquire the mutual-exclusion of a set of monitor. \CFA offers the \code{mutex} statement to work around the need for unnecessary names, avoiding a major software engineering problem~\cite{2FTwoHardThings}.
1119Table \ref{lst:mutex-stmt} shows an example of the \code{mutex} statement, which introduces a new scope in which the mutual-exclusion of a set of monitor is acquired.
1120Beyond naming, the \code{mutex} statement has no semantic difference from a routine call with \code{mutex} parameters.
1121
1122\begin{table}
1123\begin{center}
1124\begin{tabular}{|c|c|}
1125function call & \code{mutex} statement \\
1126\hline
1127\begin{cfacode}[tabsize=3]
1128monitor M {};
1129void foo( M & mutex m1, M & mutex m2 ) {
1130        //critical section
1131}
1132
1133void bar( M & m1, M & m2 ) {
1134        foo( m1, m2 );
1135}
1136\end{cfacode}&\begin{cfacode}[tabsize=3]
1137monitor M {};
1138void bar( M & m1, M & m2 ) {
1139        mutex(m1, m2) {
1140                //critical section
1141        }
1142}
1143
1144
1145\end{cfacode}
1146\end{tabular}
1147\end{center}
1148\caption{Regular call semantics vs. \code{mutex} statement}
1149\label{lst:mutex-stmt}
1150\end{table}
1151
1152% ======================================================================
1153% ======================================================================
1154\subsection{Data semantics} \label{data}
1155% ======================================================================
1156% ======================================================================
1157Once the call semantics are established, the next step is to establish data semantics.
1158Indeed, until now a monitor is used simply as a generic handle but in most cases monitors contain shared data.
1159This data should be intrinsic to the monitor declaration to prevent any accidental use of data without its appropriate protection.
1160For example, here is a complete version of the counter shown in section \ref{call}:
1161\begin{cfacode}
1162monitor counter_t {
1163        int value;
1164};
1165
1166void ?{}(counter_t & this) {
1167        this.cnt = 0;
1168}
1169
1170int ?++(counter_t & mutex this) {
1171        return ++this.value;
1172}
1173
1174//need for mutex is platform dependent here
1175void ?{}(int * this, counter_t & mutex cnt) {
1176        *this = (int)cnt;
1177}
1178\end{cfacode}
1179
1180Like threads and coroutines, monitors are defined in terms of traits with some additional language support in the form of the \code{monitor} keyword.
1181The monitor trait is:
1182\begin{cfacode}
1183trait is_monitor(dtype T) {
1184        monitor_desc * get_monitor( T & );
1185        void ^?{}( T & mutex );
1186};
1187\end{cfacode}
1188Note that the destructor of a monitor must be a \code{mutex} routine to prevent deallocation while a thread is accessing the monitor.
1189As with any object, calls to a monitor, using \code{mutex} or otherwise, is undefined behaviour after the destructor has run.
1190
1191% ======================================================================
1192% ======================================================================
1193\section{Internal Scheduling} \label{intsched}
1194% ======================================================================
1195% ======================================================================
1196In addition to mutual exclusion, the monitors at the core of \CFA's concurrency can also be used to achieve synchronization.
1197With monitors, this capability is generally achieved with internal or external scheduling as in~\cite{Hoare74}.
1198With \textbf{scheduling} loosely defined as deciding which thread acquires the critical section next, \textbf{internal scheduling} means making the decision from inside the critical section (i.e., with access to the shared state), while \textbf{external scheduling} means making the decision when entering the critical section (i.e., without access to the shared state).
1199Since internal scheduling within a single monitor is mostly a solved problem, this paper concentrates on extending internal scheduling to multiple monitors.
1200Indeed, like the \textbf{bulk-acq} semantics, internal scheduling extends to multiple monitors in a way that is natural to the user but requires additional complexity on the implementation side.
1201
1202First, here is a simple example of internal scheduling:
1203
1204\begin{cfacode}
1205monitor A {
1206        condition e;
1207}
1208
1209void foo(A& mutex a1, A& mutex a2) {
1210        ...
1211        //Wait for cooperation from bar()
1212        wait(a1.e);
1213        ...
1214}
1215
1216void bar(A& mutex a1, A& mutex a2) {
1217        //Provide cooperation for foo()
1218        ...
1219        //Unblock foo
1220        signal(a1.e);
1221}
1222\end{cfacode}
1223There are two details to note here.
1224First, \code{signal} is a delayed operation; it only unblocks the waiting thread when it reaches the end of the critical section.
1225This semantics is needed to respect mutual-exclusion, i.e., the signaller and signalled thread cannot be in the monitor simultaneously.
1226The alternative is to return immediately after the call to \code{signal}, which is significantly more restrictive.
1227Second, in \CFA, while it is common to store a \code{condition} as a field of the monitor, a \code{condition} variable can be stored/created independently of a monitor.
1228Here routine \code{foo} waits for the \code{signal} from \code{bar} before making further progress, ensuring a basic ordering.
1229
1230An important aspect of the implementation is that \CFA does not allow barging, which means that once function \code{bar} releases the monitor, \code{foo} is guaranteed to be the next thread to acquire the monitor (unless some other thread waited on the same condition).
1231This guarantee offers the benefit of not having to loop around waits to recheck that a condition is met.
1232The main reason \CFA offers this guarantee is that users can easily introduce barging if it becomes a necessity but adding barging prevention or barging avoidance is more involved without language support.
1233Supporting barging prevention as well as extending internal scheduling to multiple monitors is the main source of complexity in the design and implementation of \CFA concurrency.
1234
1235% ======================================================================
1236% ======================================================================
1237\subsection{Internal Scheduling - Multi-Monitor}
1238% ======================================================================
1239% ======================================================================
1240It is easy to understand the problem of multi-monitor scheduling using a series of pseudo-code examples.
1241Note that for simplicity in the following snippets of pseudo-code, waiting and signalling is done using an implicit condition variable, like Java built-in monitors.
1242Indeed, \code{wait} statements always use the implicit condition variable as parameters and explicitly name the monitors (A and B) associated with the condition.
1243Note that in \CFA, condition variables are tied to a \emph{group} of monitors on first use (called branding), which means that using internal scheduling with distinct sets of monitors requires one condition variable per set of monitors.
1244The example below shows the simple case of having two threads (one for each column) and a single monitor A.
1245
1246\begin{multicols}{2}
1247thread 1
1248\begin{pseudo}
1249acquire A
1250        wait A
1251release A
1252\end{pseudo}
1253
1254\columnbreak
1255
1256thread 2
1257\begin{pseudo}
1258acquire A
1259        signal A
1260release A
1261\end{pseudo}
1262\end{multicols}
1263One thread acquires before waiting (atomically blocking and releasing A) and the other acquires before signalling.
1264It is important to note here that both \code{wait} and \code{signal} must be called with the proper monitor(s) already acquired.
1265This semantic is a logical requirement for barging prevention.
1266
1267A direct extension of the previous example is a \textbf{bulk-acq} version:
1268\begin{multicols}{2}
1269\begin{pseudo}
1270acquire A & B
1271        wait A & B
1272release A & B
1273\end{pseudo}
1274\columnbreak
1275\begin{pseudo}
1276acquire A & B
1277        signal A & B
1278release A & B
1279\end{pseudo}
1280\end{multicols}
1281\noindent This version uses \textbf{bulk-acq} (denoted using the {\sf\&} symbol), but the presence of multiple monitors does not add a particularly new meaning.
1282Synchronization happens between the two threads in exactly the same way and order.
1283The only difference is that mutual exclusion covers a group of monitors.
1284On the implementation side, handling multiple monitors does add a degree of complexity as the next few examples demonstrate.
1285
1286While deadlock issues can occur when nesting monitors, these issues are only a symptom of the fact that locks, and by extension monitors, are not perfectly composable.
1287For monitors, a well-known deadlock problem is the Nested Monitor Problem~\cite{Lister77}, which occurs when a \code{wait} is made by a thread that holds more than one monitor.
1288For example, the following pseudo-code runs into the nested-monitor problem:
1289\begin{multicols}{2}
1290\begin{pseudo}
1291acquire A
1292        acquire B
1293                wait B
1294        release B
1295release A
1296\end{pseudo}
1297
1298\columnbreak
1299
1300\begin{pseudo}
1301acquire A
1302        acquire B
1303                signal B
1304        release B
1305release A
1306\end{pseudo}
1307\end{multicols}
1308\noindent The \code{wait} only releases monitor \code{B} so the signalling thread cannot acquire monitor \code{A} to get to the \code{signal}.
1309Attempting release of all acquired monitors at the \code{wait} introduces a different set of problems, such as releasing monitor \code{C}, which has nothing to do with the \code{signal}.
1310
1311However, for monitors as for locks, it is possible to write a program using nesting without encountering any problems if nesting is done correctly.
1312For example, the next pseudo-code snippet acquires monitors {\sf A} then {\sf B} before waiting, while only acquiring {\sf B} when signalling, effectively avoiding the Nested Monitor Problem~\cite{Lister77}.
1313
1314\begin{multicols}{2}
1315\begin{pseudo}
1316acquire A
1317        acquire B
1318                wait B
1319        release B
1320release A
1321\end{pseudo}
1322
1323\columnbreak
1324
1325\begin{pseudo}
1326
1327acquire B
1328        signal B
1329release B
1330
1331\end{pseudo}
1332\end{multicols}
1333
1334\noindent However, this simple refactoring may not be possible, forcing more complex restructuring.
1335
1336% ======================================================================
1337% ======================================================================
1338\subsection{Internal Scheduling - In Depth}
1339% ======================================================================
1340% ======================================================================
1341
1342A larger example is presented to show complex issues for \textbf{bulk-acq} and its implementation options are analyzed.
1343Listing \ref{lst:int-bulk-pseudo} shows an example where \textbf{bulk-acq} adds a significant layer of complexity to the internal signalling semantics, and listing \ref{lst:int-bulk-cfa} shows the corresponding \CFA code to implement the pseudo-code in listing \ref{lst:int-bulk-pseudo}.
1344For the purpose of translating the given pseudo-code into \CFA-code, any method of introducing a monitor is acceptable, e.g., \code{mutex} parameters, global variables, pointer parameters, or using locals with the \code{mutex} statement.
1345
1346\begin{figure}[!t]
1347\begin{multicols}{2}
1348Waiting thread
1349\begin{pseudo}[numbers=left]
1350acquire A
1351        //Code Section 1
1352        acquire A & B
1353                //Code Section 2
1354                wait A & B
1355                //Code Section 3
1356        release A & B
1357        //Code Section 4
1358release A
1359\end{pseudo}
1360\columnbreak
1361Signalling thread
1362\begin{pseudo}[numbers=left, firstnumber=10,escapechar=|]
1363acquire A
1364        //Code Section 5
1365        acquire A & B
1366                //Code Section 6
1367                |\label{line:signal1}|signal A & B
1368                //Code Section 7
1369        |\label{line:releaseFirst}|release A & B
1370        //Code Section 8
1371|\label{line:lastRelease}|release A
1372\end{pseudo}
1373\end{multicols}
1374\begin{cfacode}[caption={Internal scheduling with \textbf{bulk-acq}},label={lst:int-bulk-pseudo}]
1375\end{cfacode}
1376\begin{center}
1377\begin{cfacode}[xleftmargin=.4\textwidth]
1378monitor A a;
1379monitor B b;
1380condition c;
1381\end{cfacode}
1382\end{center}
1383\begin{multicols}{2}
1384Waiting thread
1385\begin{cfacode}
1386mutex(a) {
1387        //Code Section 1
1388        mutex(a, b) {
1389                //Code Section 2
1390                wait(c);
1391                //Code Section 3
1392        }
1393        //Code Section 4
1394}
1395\end{cfacode}
1396\columnbreak
1397Signalling thread
1398\begin{cfacode}
1399mutex(a) {
1400        //Code Section 5
1401        mutex(a, b) {
1402                //Code Section 6
1403                signal(c);
1404                //Code Section 7
1405        }
1406        //Code Section 8
1407}
1408\end{cfacode}
1409\end{multicols}
1410\begin{cfacode}[caption={Equivalent \CFA code for listing \ref{lst:int-bulk-pseudo}},label={lst:int-bulk-cfa}]
1411\end{cfacode}
1412\begin{multicols}{2}
1413Waiter
1414\begin{pseudo}[numbers=left]
1415acquire A
1416        acquire A & B
1417                wait A & B
1418        release A & B
1419release A
1420\end{pseudo}
1421
1422\columnbreak
1423
1424Signaller
1425\begin{pseudo}[numbers=left, firstnumber=6,escapechar=|]
1426acquire A
1427        acquire A & B
1428                signal A & B
1429        release A & B
1430        |\label{line:secret}|//Secretly keep B here
1431release A
1432//Wakeup waiter and transfer A & B
1433\end{pseudo}
1434\end{multicols}
1435\begin{cfacode}[caption={Listing \ref{lst:int-bulk-pseudo}, with delayed signalling comments},label={lst:int-secret}]
1436\end{cfacode}
1437\end{figure}
1438
1439The complexity begins at code sections 4 and 8 in listing \ref{lst:int-bulk-pseudo}, which are where the existing semantics of internal scheduling needs to be extended for multiple monitors.
1440The root of the problem is that \textbf{bulk-acq} is used in a context where one of the monitors is already acquired, which is why it is important to define the behaviour of the previous pseudo-code.
1441When the signaller thread reaches the location where it should ``release \code{A & B}'' (listing \ref{lst:int-bulk-pseudo} line \ref{line:releaseFirst}), it must actually transfer ownership of monitor \code{B} to the waiting thread.
1442This ownership transfer is required in order to prevent barging into \code{B} by another thread, since both the signalling and signalled threads still need monitor \code{A}.
1443There are three options:
1444
1445\subsubsection{Delaying Signals}
1446The obvious solution to the problem of multi-monitor scheduling is to keep ownership of all locks until the last lock is ready to be transferred.
1447It can be argued that that moment is when the last lock is no longer needed, because this semantics fits most closely to the behaviour of single-monitor scheduling.
1448This solution has the main benefit of transferring ownership of groups of monitors, which simplifies the semantics from multiple objects to a single group of objects, effectively making the existing single-monitor semantic viable by simply changing monitors to monitor groups.
1449This solution releases the monitors once every monitor in a group can be released.
1450However, since some monitors are never released (e.g., the monitor of a thread), this interpretation means a group might never be released.
1451A more interesting interpretation is to transfer the group until all its monitors are released, which means the group is not passed further and a thread can retain its locks.
1452
1453However, listing \ref{lst:int-secret} shows this solution can become much more complicated depending on what is executed while secretly holding B at line \ref{line:secret}, while avoiding the need to transfer ownership of a subset of the condition monitors.
1454Listing \ref{lst:dependency} shows a slightly different example where a third thread is waiting on monitor \code{A}, using a different condition variable.
1455Because the third thread is signalled when secretly holding \code{B}, the goal  becomes unreachable.
1456Depending on the order of signals (listing \ref{lst:dependency} line \ref{line:signal-ab} and \ref{line:signal-a}) two cases can happen:
1457
1458\paragraph{Case 1: thread $\alpha$ goes first.} In this case, the problem is that monitor \code{A} needs to be passed to thread $\beta$ when thread $\alpha$ is done with it.
1459\paragraph{Case 2: thread $\beta$ goes first.} In this case, the problem is that monitor \code{B} needs to be retained and passed to thread $\alpha$ along with monitor \code{A}, which can be done directly or possibly using thread $\beta$ as an intermediate.
1460\\
1461
1462Note that ordering is not determined by a race condition but by whether signalled threads are enqueued in FIFO or FILO order.
1463However, regardless of the answer, users can move line \ref{line:signal-a} before line \ref{line:signal-ab} and get the reverse effect for listing \ref{lst:dependency}.
1464
1465In both cases, the threads need to be able to distinguish, on a per monitor basis, which ones need to be released and which ones need to be transferred, which means knowing when to release a group becomes complex and inefficient (see next section) and therefore effectively precludes this approach.
1466
1467\subsubsection{Dependency graphs}
1468
1469
1470\begin{figure}
1471\begin{multicols}{3}
1472Thread $\alpha$
1473\begin{pseudo}[numbers=left, firstnumber=1]
1474acquire A
1475        acquire A & B
1476                wait A & B
1477        release A & B
1478release A
1479\end{pseudo}
1480\columnbreak
1481Thread $\gamma$
1482\begin{pseudo}[numbers=left, firstnumber=6, escapechar=|]
1483acquire A
1484        acquire A & B
1485                |\label{line:signal-ab}|signal A & B
1486        |\label{line:release-ab}|release A & B
1487        |\label{line:signal-a}|signal A
1488|\label{line:release-a}|release A
1489\end{pseudo}
1490\columnbreak
1491Thread $\beta$
1492\begin{pseudo}[numbers=left, firstnumber=12, escapechar=|]
1493acquire A
1494        wait A
1495|\label{line:release-aa}|release A
1496\end{pseudo}
1497\end{multicols}
1498\begin{cfacode}[caption={Pseudo-code for the three thread example.},label={lst:dependency}]
1499\end{cfacode}
1500\begin{center}
1501\input{dependency}
1502\end{center}
1503\caption{Dependency graph of the statements in listing \ref{lst:dependency}}
1504\label{fig:dependency}
1505\end{figure}
1506
1507In listing \ref{lst:int-bulk-pseudo}, there is a solution that satisfies both barging prevention and mutual exclusion.
1508If ownership of both monitors is transferred to the waiter when the signaller releases \code{A & B} and then the waiter transfers back ownership of \code{A} back to the signaller when it releases it, then the problem is solved (\code{B} is no longer in use at this point).
1509Dynamically finding the correct order is therefore the second possible solution.
1510The problem is effectively resolving a dependency graph of ownership requirements.
1511Here even the simplest of code snippets requires two transfers and has a super-linear complexity.
1512This complexity can be seen in listing \ref{lst:explosion}, which is just a direct extension to three monitors, requires at least three ownership transfer and has multiple solutions.
1513Furthermore, the presence of multiple solutions for ownership transfer can cause deadlock problems if a specific solution is not consistently picked; In the same way that multiple lock acquiring order can cause deadlocks.
1514\begin{figure}
1515\begin{multicols}{2}
1516\begin{pseudo}
1517acquire A
1518        acquire B
1519                acquire C
1520                        wait A & B & C
1521                release C
1522        release B
1523release A
1524\end{pseudo}
1525
1526\columnbreak
1527
1528\begin{pseudo}
1529acquire A
1530        acquire B
1531                acquire C
1532                        signal A & B & C
1533                release C
1534        release B
1535release A
1536\end{pseudo}
1537\end{multicols}
1538\begin{cfacode}[caption={Extension to three monitors of listing \ref{lst:int-bulk-pseudo}},label={lst:explosion}]
1539\end{cfacode}
1540\end{figure}
1541
1542Given the three threads example in listing \ref{lst:dependency}, figure \ref{fig:dependency} shows the corresponding dependency graph that results, where every node is a statement of one of the three threads, and the arrows the dependency of that statement (e.g., $\alpha1$ must happen before $\alpha2$).
1543The extra challenge is that this dependency graph is effectively post-mortem, but the runtime system needs to be able to build and solve these graphs as the dependencies unfold.
1544Resolving dependency graphs being a complex and expensive endeavour, this solution is not the preferred one.
1545
1546\subsubsection{Partial Signalling} \label{partial-sig}
1547Finally, the solution that is chosen for \CFA is to use partial signalling.
1548Again using listing \ref{lst:int-bulk-pseudo}, the partial signalling solution transfers ownership of monitor \code{B} at lines \ref{line:signal1} to the waiter but does not wake the waiting thread since it is still using monitor \code{A}.
1549Only when it reaches line \ref{line:lastRelease} does it actually wake up the waiting thread.
1550This solution has the benefit that complexity is encapsulated into only two actions: passing monitors to the next owner when they should be released and conditionally waking threads if all conditions are met.
1551This solution has a much simpler implementation than a dependency graph solving algorithms, which is why it was chosen.
1552Furthermore, after being fully implemented, this solution does not appear to have any significant downsides.
1553
1554Using partial signalling, listing \ref{lst:dependency} can be solved easily:
1555\begin{itemize}
1556        \item When thread $\gamma$ reaches line \ref{line:release-ab} it transfers monitor \code{B} to thread $\alpha$ and continues to hold monitor \code{A}.
1557        \item When thread $\gamma$ reaches line \ref{line:release-a}  it transfers monitor \code{A} to thread $\beta$  and wakes it up.
1558        \item When thread $\beta$  reaches line \ref{line:release-aa} it transfers monitor \code{A} to thread $\alpha$ and wakes it up.
1559\end{itemize}
1560
1561% ======================================================================
1562% ======================================================================
1563\subsection{Signalling: Now or Later}
1564% ======================================================================
1565% ======================================================================
1566\begin{table}
1567\begin{tabular}{|c|c|}
1568\code{signal} & \code{signal_block} \\
1569\hline
1570\begin{cfacode}[tabsize=3]
1571monitor DatingService
1572{
1573        //compatibility codes
1574        enum{ CCodes = 20 };
1575
1576        int girlPhoneNo
1577        int boyPhoneNo;
1578};
1579
1580condition girls[CCodes];
1581condition boys [CCodes];
1582condition exchange;
1583
1584int girl(int phoneNo, int ccode)
1585{
1586        //no compatible boy ?
1587        if(empty(boys[ccode]))
1588        {
1589                //wait for boy
1590                wait(girls[ccode]);
1591
1592                //make phone number available
1593                girlPhoneNo = phoneNo;
1594
1595                //wake boy from chair
1596                signal(exchange);
1597        }
1598        else
1599        {
1600                //make phone number available
1601                girlPhoneNo = phoneNo;
1602
1603                //wake boy
1604                signal(boys[ccode]);
1605
1606                //sit in chair
1607                wait(exchange);
1608        }
1609        return boyPhoneNo;
1610}
1611
1612int boy(int phoneNo, int ccode)
1613{
1614        //same as above
1615        //with boy/girl interchanged
1616}
1617\end{cfacode}&\begin{cfacode}[tabsize=3]
1618monitor DatingService
1619{
1620        //compatibility codes
1621        enum{ CCodes = 20 };
1622
1623        int girlPhoneNo;
1624        int boyPhoneNo;
1625};
1626
1627condition girls[CCodes];
1628condition boys [CCodes];
1629//exchange is not needed
1630
1631int girl(int phoneNo, int ccode)
1632{
1633        //no compatible boy ?
1634        if(empty(boys[ccode]))
1635        {
1636                //wait for boy
1637                wait(girls[ccode]);
1638
1639                //make phone number available
1640                girlPhoneNo = phoneNo;
1641
1642                //wake boy from chair
1643                signal(exchange);
1644        }
1645        else
1646        {
1647                //make phone number available
1648                girlPhoneNo = phoneNo;
1649
1650                //wake boy
1651                signal_block(boys[ccode]);
1652
1653                //second handshake unnecessary
1654
1655        }
1656        return boyPhoneNo;
1657}
1658
1659int boy(int phoneNo, int ccode)
1660{
1661        //same as above
1662        //with boy/girl interchanged
1663}
1664\end{cfacode}
1665\end{tabular}
1666\caption{Dating service example using \code{signal} and \code{signal_block}. }
1667\label{tbl:datingservice}
1668\end{table}
1669An important note is that, until now, signalling a monitor was a delayed operation.
1670The ownership of the monitor is transferred only when the monitor would have otherwise been released, not at the point of the \code{signal} statement.
1671However, in some cases, it may be more convenient for users to immediately transfer ownership to the thread that is waiting for cooperation, which is achieved using the \code{signal_block} routine.
1672
1673The example in table \ref{tbl:datingservice} highlights the difference in behaviour.
1674As mentioned, \code{signal} only transfers ownership once the current critical section exits; this behaviour requires additional synchronization when a two-way handshake is needed.
1675To avoid this explicit synchronization, the \code{condition} type offers the \code{signal_block} routine, which handles the two-way handshake as shown in the example.
1676This feature removes the need for a second condition variables and simplifies programming.
1677Like every other monitor semantic, \code{signal_block} uses barging prevention, which means mutual-exclusion is baton-passed both on the front end and the back end of the call to \code{signal_block}, meaning no other thread can acquire the monitor either before or after the call.
1678
1679% ======================================================================
1680% ======================================================================
1681\section{External scheduling} \label{extsched}
1682% ======================================================================
1683% ======================================================================
1684An alternative to internal scheduling is external scheduling (see Table~\ref{tbl:sched}).
1685\begin{table}
1686\begin{tabular}{|c|c|c|}
1687Internal Scheduling & External Scheduling & Go\\
1688\hline
1689\begin{ucppcode}[tabsize=3]
1690_Monitor Semaphore {
1691        condition c;
1692        bool inUse;
1693public:
1694        void P() {
1695                if(inUse)
1696                        wait(c);
1697                inUse = true;
1698        }
1699        void V() {
1700                inUse = false;
1701                signal(c);
1702        }
1703}
1704\end{ucppcode}&\begin{ucppcode}[tabsize=3]
1705_Monitor Semaphore {
1706
1707        bool inUse;
1708public:
1709        void P() {
1710                if(inUse)
1711                        _Accept(V);
1712                inUse = true;
1713        }
1714        void V() {
1715                inUse = false;
1716
1717        }
1718}
1719\end{ucppcode}&\begin{gocode}[tabsize=3]
1720type MySem struct {
1721        inUse bool
1722        c     chan bool
1723}
1724
1725// acquire
1726func (s MySem) P() {
1727        if s.inUse {
1728                select {
1729                case <-s.c:
1730                }
1731        }
1732        s.inUse = true
1733}
1734
1735// release
1736func (s MySem) V() {
1737        s.inUse = false
1738
1739        //This actually deadlocks
1740        //when single thread
1741        s.c <- false
1742}
1743\end{gocode}
1744\end{tabular}
1745\caption{Different forms of scheduling.}
1746\label{tbl:sched}
1747\end{table}
1748This method is more constrained and explicit, which helps users reduce the non-deterministic nature of concurrency.
1749Indeed, as the following examples demonstrate, external scheduling allows users to wait for events from other threads without the concern of unrelated events occurring.
1750External scheduling can generally be done either in terms of control flow (e.g., Ada with \code{accept}, \uC with \code{_Accept}) or in terms of data (e.g., Go with channels).
1751Of course, both of these paradigms have their own strengths and weaknesses, but for this project, control-flow semantics was chosen to stay consistent with the rest of the languages semantics.
1752Two challenges specific to \CFA arise when trying to add external scheduling with loose object definitions and multiple-monitor routines.
1753The previous example shows a simple use \code{_Accept} versus \code{wait}/\code{signal} and its advantages.
1754Note that while other languages often use \code{accept}/\code{select} as the core external scheduling keyword, \CFA uses \code{waitfor} to prevent name collisions with existing socket \textbf{api}s.
1755
1756For the \code{P} member above using internal scheduling, the call to \code{wait} only guarantees that \code{V} is the last routine to access the monitor, allowing a third routine, say \code{isInUse()}, acquire mutual exclusion several times while routine \code{P} is waiting.
1757On the other hand, external scheduling guarantees that while routine \code{P} is waiting, no other routine than \code{V} can acquire the monitor.
1758
1759% ======================================================================
1760% ======================================================================
1761\subsection{Loose Object Definitions}
1762% ======================================================================
1763% ======================================================================
1764In \uC, a monitor class declaration includes an exhaustive list of monitor operations.
1765Since \CFA is not object oriented, monitors become both more difficult to implement and less clear for a user:
1766
1767\begin{cfacode}
1768monitor A {};
1769
1770void f(A & mutex a);
1771void g(A & mutex a) {
1772        waitfor(f); //Obvious which f() to wait for
1773}
1774
1775void f(A & mutex a, int); //New different F added in scope
1776void h(A & mutex a) {
1777        waitfor(f); //Less obvious which f() to wait for
1778}
1779\end{cfacode}
1780
1781Furthermore, external scheduling is an example where implementation constraints become visible from the interface.
1782Here is the pseudo-code for the entering phase of a monitor:
1783\begin{center}
1784\begin{tabular}{l}
1785\begin{pseudo}
1786        if monitor is free
1787                enter
1788        elif already own the monitor
1789                continue
1790        elif monitor accepts me
1791                enter
1792        else
1793                block
1794\end{pseudo}
1795\end{tabular}
1796\end{center}
1797For the first two conditions, it is easy to implement a check that can evaluate the condition in a few instructions.
1798However, a fast check for \pscode{monitor accepts me} is much harder to implement depending on the constraints put on the monitors.
1799Indeed, monitors are often expressed as an entry queue and some acceptor queue as in Figure~\ref{fig:ClassicalMonitor}.
1800
1801\begin{figure}
1802\centering
1803\subfloat[Classical Monitor] {
1804\label{fig:ClassicalMonitor}
1805{\resizebox{0.45\textwidth}{!}{\input{monitor}}}
1806}% subfloat
1807\qquad
1808\subfloat[\textbf{bulk-acq} Monitor] {
1809\label{fig:BulkMonitor}
1810{\resizebox{0.45\textwidth}{!}{\input{ext_monitor}}}
1811}% subfloat
1812\caption{External Scheduling Monitor}
1813\end{figure}
1814
1815There are other alternatives to these pictures, but in the case of the left picture, implementing a fast accept check is relatively easy.
1816Restricted to a fixed number of mutex members, N, the accept check reduces to updating a bitmask when the acceptor queue changes, a check that executes in a single instruction even with a fairly large number (e.g., 128) of mutex members.
1817This approach requires a unique dense ordering of routines with an upper-bound and that ordering must be consistent across translation units.
1818For OO languages these constraints are common, since objects only offer adding member routines consistently across translation units via inheritance.
1819However, in \CFA users can extend objects with mutex routines that are only visible in certain translation unit.
1820This means that establishing a program-wide dense-ordering among mutex routines can only be done in the program linking phase, and still could have issues when using dynamically shared objects.
1821
1822The alternative is to alter the implementation as in Figure~\ref{fig:BulkMonitor}.
1823Here, the mutex routine called is associated with a thread on the entry queue while a list of acceptable routines is kept separate.
1824Generating a mask dynamically means that the storage for the mask information can vary between calls to \code{waitfor}, allowing for more flexibility and extensions.
1825Storing an array of accepted function pointers replaces the single instruction bitmask comparison with dereferencing a pointer followed by a linear search.
1826Furthermore, supporting nested external scheduling (e.g., listing \ref{lst:nest-ext}) may now require additional searches for the \code{waitfor} statement to check if a routine is already queued.
1827
1828\begin{figure}
1829\begin{cfacode}[caption={Example of nested external scheduling},label={lst:nest-ext}]
1830monitor M {};
1831void foo( M & mutex a ) {}
1832void bar( M & mutex b ) {
1833        //Nested in the waitfor(bar, c) call
1834        waitfor(foo, b);
1835}
1836void baz( M & mutex c ) {
1837        waitfor(bar, c);
1838}
1839
1840\end{cfacode}
1841\end{figure}
1842
1843Note that in the right picture, tasks need to always keep track of the monitors associated with mutex routines, and the routine mask needs to have both a function pointer and a set of monitors, as is discussed in the next section.
1844These details are omitted from the picture for the sake of simplicity.
1845
1846At this point, a decision must be made between flexibility and performance.
1847Many design decisions in \CFA achieve both flexibility and performance, for example polymorphic routines add significant flexibility but inlining them means the optimizer can easily remove any runtime cost.
1848Here, however, the cost of flexibility cannot be trivially removed.
1849In the end, the most flexible approach has been chosen since it allows users to write programs that would otherwise be  hard to write.
1850This decision is based on the assumption that writing fast but inflexible locks is closer to a solved problem than writing locks that are as flexible as external scheduling in \CFA.
1851
1852% ======================================================================
1853% ======================================================================
1854\subsection{Multi-Monitor Scheduling}
1855% ======================================================================
1856% ======================================================================
1857
1858External scheduling, like internal scheduling, becomes significantly more complex when introducing multi-monitor syntax.
1859Even in the simplest possible case, some new semantics needs to be established:
1860\begin{cfacode}
1861monitor M {};
1862
1863void f(M & mutex a);
1864
1865void g(M & mutex b, M & mutex c) {
1866        waitfor(f); //two monitors M => unknown which to pass to f(M & mutex)
1867}
1868\end{cfacode}
1869The obvious solution is to specify the correct monitor as follows:
1870
1871\begin{cfacode}
1872monitor M {};
1873
1874void f(M & mutex a);
1875
1876void g(M & mutex a, M & mutex b) {
1877        //wait for call to f with argument b
1878        waitfor(f, b);
1879}
1880\end{cfacode}
1881This syntax is unambiguous.
1882Both locks are acquired and kept by \code{g}.
1883When routine \code{f} is called, the lock for monitor \code{b} is temporarily transferred from \code{g} to \code{f} (while \code{g} still holds lock \code{a}).
1884This behaviour can be extended to the multi-monitor \code{waitfor} statement as follows.
1885
1886\begin{cfacode}
1887monitor M {};
1888
1889void f(M & mutex a, M & mutex b);
1890
1891void g(M & mutex a, M & mutex b) {
1892        //wait for call to f with arguments a and b
1893        waitfor(f, a, b);
1894}
1895\end{cfacode}
1896
1897Note that the set of monitors passed to the \code{waitfor} statement must be entirely contained in the set of monitors already acquired in the routine. \code{waitfor} used in any other context is undefined behaviour.
1898
1899An important behaviour to note is when a set of monitors only match partially:
1900
1901\begin{cfacode}
1902mutex struct A {};
1903
1904mutex struct B {};
1905
1906void g(A & mutex a, B & mutex b) {
1907        waitfor(f, a, b);
1908}
1909
1910A a1, a2;
1911B b;
1912
1913void foo() {
1914        g(a1, b); //block on accept
1915}
1916
1917void bar() {
1918        f(a2, b); //fulfill cooperation
1919}
1920\end{cfacode}
1921While the equivalent can happen when using internal scheduling, the fact that conditions are specific to a set of monitors means that users have to use two different condition variables.
1922In both cases, partially matching monitor sets does not wakeup the waiting thread.
1923It is also important to note that in the case of external scheduling the order of parameters is irrelevant; \code{waitfor(f,a,b)} and \code{waitfor(f,b,a)} are indistinguishable waiting condition.
1924
1925% ======================================================================
1926% ======================================================================
1927\subsection{\code{waitfor} Semantics}
1928% ======================================================================
1929% ======================================================================
1930
1931Syntactically, the \code{waitfor} statement takes a function identifier and a set of monitors.
1932While the set of monitors can be any list of expressions, the function name is more restricted because the compiler validates at compile time the validity of the function type and the parameters used with the \code{waitfor} statement.
1933It checks that the set of monitors passed in matches the requirements for a function call.
1934Listing \ref{lst:waitfor} shows various usages of the waitfor statement and which are acceptable.
1935The choice of the function type is made ignoring any non-\code{mutex} parameter.
1936One limitation of the current implementation is that it does not handle overloading, but overloading is possible.
1937\begin{figure}
1938\begin{cfacode}[caption={Various correct and incorrect uses of the waitfor statement},label={lst:waitfor}]
1939monitor A{};
1940monitor B{};
1941
1942void f1( A & mutex );
1943void f2( A & mutex, B & mutex );
1944void f3( A & mutex, int );
1945void f4( A & mutex, int );
1946void f4( A & mutex, double );
1947
1948void foo( A & mutex a1, A & mutex a2, B & mutex b1, B & b2 ) {
1949        A * ap = & a1;
1950        void (*fp)( A & mutex ) = f1;
1951
1952        waitfor(f1, a1);     //Correct : 1 monitor case
1953        waitfor(f2, a1, b1); //Correct : 2 monitor case
1954        waitfor(f3, a1);     //Correct : non-mutex arguments are ignored
1955        waitfor(f1, *ap);    //Correct : expression as argument
1956
1957        waitfor(f1, a1, b1); //Incorrect : Too many mutex arguments
1958        waitfor(f2, a1);     //Incorrect : Too few mutex arguments
1959        waitfor(f2, a1, a2); //Incorrect : Mutex arguments don't match
1960        waitfor(f1, 1);      //Incorrect : 1 not a mutex argument
1961        waitfor(f9, a1);     //Incorrect : f9 function does not exist
1962        waitfor(*fp, a1 );   //Incorrect : fp not an identifier
1963        waitfor(f4, a1);     //Incorrect : f4 ambiguous
1964
1965        waitfor(f2, a1, b2); //Undefined behaviour : b2 not mutex
1966}
1967\end{cfacode}
1968\end{figure}
1969
1970Finally, for added flexibility, \CFA supports constructing a complex \code{waitfor} statement using the \code{or}, \code{timeout} and \code{else}.
1971Indeed, multiple \code{waitfor} clauses can be chained together using \code{or}; this chain forms a single statement that uses baton pass to any function that fits one of the function+monitor set passed in.
1972To enable users to tell which accepted function executed, \code{waitfor}s are followed by a statement (including the null statement \code{;}) or a compound statement, which is executed after the clause is triggered.
1973A \code{waitfor} chain can also be followed by a \code{timeout}, to signify an upper bound on the wait, or an \code{else}, to signify that the call should be non-blocking, which checks for a matching function call already arrived and otherwise continues.
1974Any and all of these clauses can be preceded by a \code{when} condition to dynamically toggle the accept clauses on or off based on some current state.
1975Listing \ref{lst:waitfor2} demonstrates several complex masks and some incorrect ones.
1976
1977\begin{figure}
1978\begin{cfacode}[caption={Various correct and incorrect uses of the or, else, and timeout clause around a waitfor statement},label={lst:waitfor2}]
1979monitor A{};
1980
1981void f1( A & mutex );
1982void f2( A & mutex );
1983
1984void foo( A & mutex a, bool b, int t ) {
1985        //Correct : blocking case
1986        waitfor(f1, a);
1987
1988        //Correct : block with statement
1989        waitfor(f1, a) {
1990                sout | "f1" | endl;
1991        }
1992
1993        //Correct : block waiting for f1 or f2
1994        waitfor(f1, a) {
1995                sout | "f1" | endl;
1996        } or waitfor(f2, a) {
1997                sout | "f2" | endl;
1998        }
1999
2000        //Correct : non-blocking case
2001        waitfor(f1, a); or else;
2002
2003        //Correct : non-blocking case
2004        waitfor(f1, a) {
2005                sout | "blocked" | endl;
2006        } or else {
2007                sout | "didn't block" | endl;
2008        }
2009
2010        //Correct : block at most 10 seconds
2011        waitfor(f1, a) {
2012                sout | "blocked" | endl;
2013        } or timeout( 10`s) {
2014                sout | "didn't block" | endl;
2015        }
2016
2017        //Correct : block only if b == true
2018        //if b == false, don't even make the call
2019        when(b) waitfor(f1, a);
2020
2021        //Correct : block only if b == true
2022        //if b == false, make non-blocking call
2023        waitfor(f1, a); or when(!b) else;
2024
2025        //Correct : block only of t > 1
2026        waitfor(f1, a); or when(t > 1) timeout(t); or else;
2027
2028        //Incorrect : timeout clause is dead code
2029        waitfor(f1, a); or timeout(t); or else;
2030
2031        //Incorrect : order must be
2032        //waitfor [or waitfor... [or timeout] [or else]]
2033        timeout(t); or waitfor(f1, a); or else;
2034}
2035\end{cfacode}
2036\end{figure}
2037
2038% ======================================================================
2039% ======================================================================
2040\subsection{Waiting For The Destructor}
2041% ======================================================================
2042% ======================================================================
2043An interesting use for the \code{waitfor} statement is destructor semantics.
2044Indeed, the \code{waitfor} statement can accept any \code{mutex} routine, which includes the destructor (see section \ref{data}).
2045However, with the semantics discussed until now, waiting for the destructor does not make any sense, since using an object after its destructor is called is undefined behaviour.
2046The simplest approach is to disallow \code{waitfor} on a destructor.
2047However, a more expressive approach is to flip ordering of execution when waiting for the destructor, meaning that waiting for the destructor allows the destructor to run after the current \code{mutex} routine, similarly to how a condition is signalled.
2048\begin{figure}
2049\begin{cfacode}[caption={Example of an executor which executes action in series until the destructor is called.},label={lst:dtor-order}]
2050monitor Executer {};
2051struct  Action;
2052
2053void ^?{}   (Executer & mutex this);
2054void execute(Executer & mutex this, const Action & );
2055void run    (Executer & mutex this) {
2056        while(true) {
2057                   waitfor(execute, this);
2058                or waitfor(^?{}   , this) {
2059                        break;
2060                }
2061        }
2062}
2063\end{cfacode}
2064\end{figure}
2065For example, listing \ref{lst:dtor-order} shows an example of an executor with an infinite loop, which waits for the destructor to break out of this loop.
2066Switching the semantic meaning introduces an idiomatic way to terminate a task and/or wait for its termination via destruction.
2067
2068
2069% ######     #    ######     #    #       #       ####### #       ###  #####  #     #
2070% #     #   # #   #     #   # #   #       #       #       #        #  #     # ##   ##
2071% #     #  #   #  #     #  #   #  #       #       #       #        #  #       # # # #
2072% ######  #     # ######  #     # #       #       #####   #        #   #####  #  #  #
2073% #       ####### #   #   ####### #       #       #       #        #        # #     #
2074% #       #     # #    #  #     # #       #       #       #        #  #     # #     #
2075% #       #     # #     # #     # ####### ####### ####### ####### ###  #####  #     #
2076\section{Parallelism}
2077Historically, computer performance was about processor speeds and instruction counts.
2078However, with heat dissipation being a direct consequence of speed increase, parallelism has become the new source for increased performance~\cite{Sutter05, Sutter05b}.
2079In this decade, it is no longer reasonable to create a high-performance application without caring about parallelism.
2080Indeed, parallelism is an important aspect of performance and more specifically throughput and hardware utilization.
2081The lowest-level approach of parallelism is to use \textbf{kthread} in combination with semantics like \code{fork}, \code{join}, etc.
2082However, since these have significant costs and limitations, \textbf{kthread} are now mostly used as an implementation tool rather than a user oriented one.
2083There are several alternatives to solve these issues that all have strengths and weaknesses.
2084While there are many variations of the presented paradigms, most of these variations do not actually change the guarantees or the semantics, they simply move costs in order to achieve better performance for certain workloads.
2085
2086\section{Paradigms}
2087\subsection{User-Level Threads}
2088A direct improvement on the \textbf{kthread} approach is to use \textbf{uthread}.
2089These threads offer most of the same features that the operating system already provides but can be used on a much larger scale.
2090This approach is the most powerful solution as it allows all the features of multithreading, while removing several of the more expensive costs of kernel threads.
2091The downside is that almost none of the low-level threading problems are hidden; users still have to think about data races, deadlocks and synchronization issues.
2092These issues can be somewhat alleviated by a concurrency toolkit with strong guarantees, but the parallelism toolkit offers very little to reduce complexity in itself.
2093
2094Examples of languages that support \textbf{uthread} are Erlang~\cite{Erlang} and \uC~\cite{uC++book}.
2095
2096\subsection{Fibers : User-Level Threads Without Preemption} \label{fibers}
2097A popular variant of \textbf{uthread} is what is often referred to as \textbf{fiber}.
2098However, \textbf{fiber} do not present meaningful semantic differences with \textbf{uthread}.
2099The significant difference between \textbf{uthread} and \textbf{fiber} is the lack of \textbf{preemption} in the latter.
2100Advocates of \textbf{fiber} list their high performance and ease of implementation as major strengths, but the performance difference between \textbf{uthread} and \textbf{fiber} is controversial, and the ease of implementation, while true, is a weak argument in the context of language design.
2101Therefore this proposal largely ignores fibers.
2102
2103An example of a language that uses fibers is Go~\cite{Go}
2104
2105\subsection{Jobs and Thread Pools}
2106An approach on the opposite end of the spectrum is to base parallelism on \textbf{pool}.
2107Indeed, \textbf{pool} offer limited flexibility but at the benefit of a simpler user interface.
2108In \textbf{pool} based systems, users express parallelism as units of work, called jobs, and a dependency graph (either explicit or implicit) that ties them together.
2109This approach means users need not worry about concurrency but significantly limit the interaction that can occur among jobs.
2110Indeed, any \textbf{job} that blocks also block the underlying worker, which effectively means the CPU utilization, and therefore throughput, suffers noticeably.
2111It can be argued that a solution to this problem is to use more workers than available cores.
2112However, unless the number of jobs and the number of workers are comparable, having a significant number of blocked jobs always results in idles cores.
2113
2114The gold standard of this implementation is Intel's TBB library~\cite{TBB}.
2115
2116\subsection{Paradigm Performance}
2117While the choice between the three paradigms listed above may have significant performance implications, it is difficult to pin down the performance implications of choosing a model at the language level.
2118Indeed, in many situations one of these paradigms may show better performance but it all strongly depends on the workload.
2119Having a large amount of mostly independent units of work to execute almost guarantees equivalent performance across paradigms and that the \textbf{pool}-based system has the best efficiency thanks to the lower memory overhead (i.e., no thread stack per job).
2120However, interactions among jobs can easily exacerbate contention.
2121User-level threads allow fine-grain context switching, which results in better resource utilization, but a context switch is more expensive and the extra control means users need to tweak more variables to get the desired performance.
2122Finally, if the units of uninterrupted work are large, enough the paradigm choice is largely amortized by the actual work done.
2123
2124\section{The \protect\CFA\ Kernel : Processors, Clusters and Threads}\label{kernel}
2125A \textbf{cfacluster} is a group of \textbf{kthread} executed in isolation. \textbf{uthread} are scheduled on the \textbf{kthread} of a given \textbf{cfacluster}, allowing organization between \textbf{uthread} and \textbf{kthread}.
2126It is important that \textbf{kthread} belonging to a same \textbf{cfacluster} have homogeneous settings, otherwise migrating a \textbf{uthread} from one \textbf{kthread} to the other can cause issues.
2127A \textbf{cfacluster} also offers a pluggable scheduler that can optimize the workload generated by the \textbf{uthread}.
2128
2129\textbf{cfacluster} have not been fully implemented in the context of this paper.
2130Currently \CFA only supports one \textbf{cfacluster}, the initial one.
2131
2132\subsection{Future Work: Machine Setup}\label{machine}
2133While this was not done in the context of this paper, another important aspect of clusters is affinity.
2134While many common desktop and laptop PCs have homogeneous CPUs, other devices often have more heterogeneous setups.
2135For example, a system using \textbf{numa} configurations may benefit from users being able to tie clusters and/or kernel threads to certain CPU cores.
2136OS support for CPU affinity is now common~\cite{affinityLinux, affinityWindows, affinityFreebsd, affinityNetbsd, affinityMacosx}, which means it is both possible and desirable for \CFA to offer an abstraction mechanism for portable CPU affinity.
2137
2138\subsection{Paradigms}\label{cfaparadigms}
2139Given these building blocks, it is possible to reproduce all three of the popular paradigms.
2140Indeed, \textbf{uthread} is the default paradigm in \CFA.
2141However, disabling \textbf{preemption} on the \textbf{cfacluster} means \textbf{cfathread} effectively become \textbf{fiber}.
2142Since several \textbf{cfacluster} with different scheduling policy can coexist in the same application, this allows \textbf{fiber} and \textbf{uthread} to coexist in the runtime of an application.
2143Finally, it is possible to build executors for thread pools from \textbf{uthread} or \textbf{fiber}, which includes specialized jobs like actors~\cite{Actors}.
2144
2145
2146
2147\section{Behind the Scenes}
2148There are several challenges specific to \CFA when implementing concurrency.
2149These challenges are a direct result of \textbf{bulk-acq} and loose object definitions.
2150These two constraints are the root cause of most design decisions in the implementation.
2151Furthermore, to avoid contention from dynamically allocating memory in a concurrent environment, the internal-scheduling design is (almost) entirely free of mallocs.
2152This approach avoids the chicken and egg problem~\cite{Chicken} of having a memory allocator that relies on the threading system and a threading system that relies on the runtime.
2153This extra goal means that memory management is a constant concern in the design of the system.
2154
2155The main memory concern for concurrency is queues.
2156All blocking operations are made by parking threads onto queues and all queues are designed with intrusive nodes, where each node has pre-allocated link fields for chaining, to avoid the need for memory allocation.
2157Since several concurrency operations can use an unbound amount of memory (depending on \textbf{bulk-acq}), statically defining information in the intrusive fields of threads is insufficient.The only way to use a variable amount of memory without requiring memory allocation is to pre-allocate large buffers of memory eagerly and store the information in these buffers.
2158Conveniently, the call stack fits that description and is easy to use, which is why it is used heavily in the implementation of internal scheduling, particularly variable-length arrays.
2159Since stack allocation is based on scopes, the first step of the implementation is to identify the scopes that are available to store the information, and which of these can have a variable-length array.
2160The threads and the condition both have a fixed amount of memory, while \code{mutex} routines and blocking calls allow for an unbound amount, within the stack size.
2161
2162Note that since the major contributions of this paper are extending monitor semantics to \textbf{bulk-acq} and loose object definitions, any challenges that are not resulting of these characteristics of \CFA are considered as solved problems and therefore not discussed.
2163
2164% ======================================================================
2165% ======================================================================
2166\section{Mutex Routines}
2167% ======================================================================
2168% ======================================================================
2169
2170The first step towards the monitor implementation is simple \code{mutex} routines.
2171In the single monitor case, mutual-exclusion is done using the entry/exit procedure in listing \ref{lst:entry1}.
2172The entry/exit procedures do not have to be extended to support multiple monitors.
2173Indeed it is sufficient to enter/leave monitors one-by-one as long as the order is correct to prevent deadlock~\cite{Havender68}.
2174In \CFA, ordering of monitor acquisition relies on memory ordering.
2175This approach is sufficient because all objects are guaranteed to have distinct non-overlapping memory layouts and mutual-exclusion for a monitor is only defined for its lifetime, meaning that destroying a monitor while it is acquired is undefined behaviour.
2176When a mutex call is made, the concerned monitors are aggregated into a variable-length pointer array and sorted based on pointer values.
2177This array persists for the entire duration of the mutual-exclusion and its ordering reused extensively.
2178\begin{figure}
2179\begin{multicols}{2}
2180Entry
2181\begin{pseudo}
2182if monitor is free
2183        enter
2184elif already own the monitor
2185        continue
2186else
2187        block
2188increment recursions
2189\end{pseudo}
2190\columnbreak
2191Exit
2192\begin{pseudo}
2193decrement recursion
2194if recursion == 0
2195        if entry queue not empty
2196                wake-up thread
2197\end{pseudo}
2198\end{multicols}
2199\begin{pseudo}[caption={Initial entry and exit routine for monitors},label={lst:entry1}]
2200\end{pseudo}
2201\end{figure}
2202
2203\subsection{Details: Interaction with polymorphism}
2204Depending on the choice of semantics for when monitor locks are acquired, interaction between monitors and \CFA's concept of polymorphism can be more complex to support.
2205However, it is shown that entry-point locking solves most of the issues.
2206
2207First of all, interaction between \code{otype} polymorphism (see Section~\ref{s:ParametricPolymorphism}) and monitors is impossible since monitors do not support copying.
2208Therefore, the main question is how to support \code{dtype} polymorphism.
2209It is important to present the difference between the two acquiring options: \textbf{callsite-locking} and entry-point locking, i.e., acquiring the monitors before making a mutex routine-call or as the first operation of the mutex routine-call.
2210For example:
2211\begin{table}[H]
2212\begin{center}
2213\begin{tabular}{|c|c|c|}
2214Mutex & \textbf{callsite-locking} & \textbf{entry-point-locking} \\
2215call & pseudo-code & pseudo-code \\
2216\hline
2217\begin{cfacode}[tabsize=3]
2218void foo(monitor& mutex a){
2219
2220        //Do Work
2221        //...
2222
2223}
2224
2225void main() {
2226        monitor a;
2227
2228        foo(a);
2229
2230}
2231\end{cfacode} & \begin{pseudo}[tabsize=3]
2232foo(& a) {
2233
2234        //Do Work
2235        //...
2236
2237}
2238
2239main() {
2240        monitor a;
2241        acquire(a);
2242        foo(a);
2243        release(a);
2244}
2245\end{pseudo} & \begin{pseudo}[tabsize=3]
2246foo(& a) {
2247        acquire(a);
2248        //Do Work
2249        //...
2250        release(a);
2251}
2252
2253main() {
2254        monitor a;
2255
2256        foo(a);
2257
2258}
2259\end{pseudo}
2260\end{tabular}
2261\end{center}
2262\caption{Call-site vs entry-point locking for mutex calls}
2263\label{tbl:locking-site}
2264\end{table}
2265
2266Note the \code{mutex} keyword relies on the type system, which means that in cases where a generic monitor-routine is desired, writing the mutex routine is possible with the proper trait, e.g.:
2267\begin{cfacode}
2268//Incorrect: T may not be monitor
2269forall(dtype T)
2270void foo(T * mutex t);
2271
2272//Correct: this function only works on monitors (any monitor)
2273forall(dtype T | is_monitor(T))
2274void bar(T * mutex t));
2275\end{cfacode}
2276
2277Both entry point and \textbf{callsite-locking} are feasible implementations.
2278The current \CFA implementation uses entry-point locking because it requires less work when using \textbf{raii}, effectively transferring the burden of implementation to object construction/destruction.
2279It is harder to use \textbf{raii} for call-site locking, as it does not necessarily have an existing scope that matches exactly the scope of the mutual exclusion, i.e., the function body.
2280For example, the monitor call can appear in the middle of an expression.
2281Furthermore, entry-point locking requires less code generation since any useful routine is called multiple times but there is only one entry point for many call sites.
2282
2283% ======================================================================
2284% ======================================================================
2285\section{Threading} \label{impl:thread}
2286% ======================================================================
2287% ======================================================================
2288
2289Figure \ref{fig:system1} shows a high-level picture if the \CFA runtime system in regards to concurrency.
2290Each component of the picture is explained in detail in the flowing sections.
2291
2292\begin{figure}
2293\begin{center}
2294{\resizebox{\textwidth}{!}{\input{system.pstex_t}}}
2295\end{center}
2296\caption{Overview of the entire system}
2297\label{fig:system1}
2298\end{figure}
2299
2300\subsection{Processors}
2301Parallelism in \CFA is built around using processors to specify how much parallelism is desired. \CFA processors are object wrappers around kernel threads, specifically \texttt{pthread}s in the current implementation of \CFA.
2302Indeed, any parallelism must go through operating-system libraries.
2303However, \textbf{uthread} are still the main source of concurrency, processors are simply the underlying source of parallelism.
2304Indeed, processor \textbf{kthread} simply fetch a \textbf{uthread} from the scheduler and run it; they are effectively executers for user-threads.
2305The main benefit of this approach is that it offers a well-defined boundary between kernel code and user code, for example, kernel thread quiescing, scheduling and interrupt handling.
2306Processors internally use coroutines to take advantage of the existing context-switching semantics.
2307
2308\subsection{Stack Management}
2309One of the challenges of this system is to reduce the footprint as much as possible.
2310Specifically, all \texttt{pthread}s created also have a stack created with them, which should be used as much as possible.
2311Normally, coroutines also create their own stack to run on, however, in the case of the coroutines used for processors, these coroutines run directly on the \textbf{kthread} stack, effectively stealing the processor stack.
2312The exception to this rule is the Main Processor, i.e., the initial \textbf{kthread} that is given to any program.
2313In order to respect C user expectations, the stack of the initial kernel thread, the main stack of the program, is used by the main user thread rather than the main processor, which can grow very large.
2314
2315\subsection{Context Switching}
2316As mentioned in section \ref{coroutine}, coroutines are a stepping stone for implementing threading, because they share the same mechanism for context-switching between different stacks.
2317To improve performance and simplicity, context-switching is implemented using the following assumption: all context-switches happen inside a specific function call.
2318This assumption means that the context-switch only has to copy the callee-saved registers onto the stack and then switch the stack registers with the ones of the target coroutine/thread.
2319Note that the instruction pointer can be left untouched since the context-switch is always inside the same function.
2320Threads, however, do not context-switch between each other directly.
2321They context-switch to the scheduler.
2322This method is called a 2-step context-switch and has the advantage of having a clear distinction between user code and the kernel where scheduling and other system operations happen.
2323Obviously, this doubles the context-switch cost because threads must context-switch to an intermediate stack.
2324The alternative 1-step context-switch uses the stack of the ``from'' thread to schedule and then context-switches directly to the ``to'' thread.
2325However, the performance of the 2-step context-switch is still superior to a \code{pthread_yield} (see section \ref{results}).
2326Additionally, for users in need for optimal performance, it is important to note that having a 2-step context-switch as the default does not prevent \CFA from offering a 1-step context-switch (akin to the Microsoft \code{SwitchToFiber}~\cite{switchToWindows} routine).
2327This option is not currently present in \CFA, but the changes required to add it are strictly additive.
2328
2329\subsection{Preemption} \label{preemption}
2330Finally, an important aspect for any complete threading system is preemption.
2331As mentioned in section \ref{basics}, preemption introduces an extra degree of uncertainty, which enables users to have multiple threads interleave transparently, rather than having to cooperate among threads for proper scheduling and CPU distribution.
2332Indeed, preemption is desirable because it adds a degree of isolation among threads.
2333In a fully cooperative system, any thread that runs a long loop can starve other threads, while in a preemptive system, starvation can still occur but it does not rely on every thread having to yield or block on a regular basis, which reduces significantly a programmer burden.
2334Obviously, preemption is not optimal for every workload.
2335However any preemptive system can become a cooperative system by making the time slices extremely large.
2336Therefore, \CFA uses a preemptive threading system.
2337
2338Preemption in \CFA\footnote{Note that the implementation of preemption is strongly tied with the underlying threading system.
2339For this reason, only the Linux implementation is cover, \CFA does not run on Windows at the time of writting} is based on kernel timers, which are used to run a discrete-event simulation.
2340Every processor keeps track of the current time and registers an expiration time with the preemption system.
2341When the preemption system receives a change in preemption, it inserts the time in a sorted order and sets a kernel timer for the closest one, effectively stepping through preemption events on each signal sent by the timer.
2342These timers use the Linux signal {\tt SIGALRM}, which is delivered to the process rather than the kernel-thread.
2343This results in an implementation problem, because when delivering signals to a process, the kernel can deliver the signal to any kernel thread for which the signal is not blocked, i.e.:
2344\begin{quote}
2345A process-directed signal may be delivered to any one of the threads that does not currently have the signal blocked.
2346If more than one of the threads has the signal unblocked, then the kernel chooses an arbitrary thread to which to deliver the signal.
2347SIGNAL(7) - Linux Programmer's Manual
2348\end{quote}
2349For the sake of simplicity, and in order to prevent the case of having two threads receiving alarms simultaneously, \CFA programs block the {\tt SIGALRM} signal on every kernel thread except one.
2350
2351Now because of how involuntary context-switches are handled, the kernel thread handling {\tt SIGALRM} cannot also be a processor thread.
2352Hence, involuntary context-switching is done by sending signal {\tt SIGUSR1} to the corresponding proces\-sor and having the thread yield from inside the signal handler.
2353This approach effectively context-switches away from the signal handler back to the kernel and the signal handler frame is eventually unwound when the thread is scheduled again.
2354As a result, a signal handler can start on one kernel thread and terminate on a second kernel thread (but the same user thread).
2355It is important to note that signal handlers save and restore signal masks because user-thread migration can cause a signal mask to migrate from one kernel thread to another.
2356This behaviour is only a problem if all kernel threads, among which a user thread can migrate, differ in terms of signal masks\footnote{Sadly, official POSIX documentation is silent on what distinguishes ``async-signal-safe'' functions from other functions.}.
2357However, since the kernel thread handling preemption requires a different signal mask, executing user threads on the kernel-alarm thread can cause deadlocks.
2358For this reason, the alarm thread is in a tight loop around a system call to \code{sigwaitinfo}, requiring very little CPU time for preemption.
2359One final detail about the alarm thread is how to wake it when additional communication is required (e.g., on thread termination).
2360This unblocking is also done using {\tt SIGALRM}, but sent through the \code{pthread_sigqueue}.
2361Indeed, \code{sigwait} can differentiate signals sent from \code{pthread_sigqueue} from signals sent from alarms or the kernel.
2362
2363\subsection{Scheduler}
2364Finally, an aspect that was not mentioned yet is the scheduling algorithm.
2365Currently, the \CFA scheduler uses a single ready queue for all processors, which is the simplest approach to scheduling.
2366Further discussion on scheduling is present in section \ref{futur:sched}.
2367
2368% ======================================================================
2369% ======================================================================
2370\section{Internal Scheduling} \label{impl:intsched}
2371% ======================================================================
2372% ======================================================================
2373The following figure is the traditional illustration of a monitor (repeated from page~\pageref{fig:ClassicalMonitor} for convenience):
2374
2375\begin{figure}[H]
2376\begin{center}
2377{\resizebox{0.4\textwidth}{!}{\input{monitor}}}
2378\end{center}
2379\caption{Traditional illustration of a monitor}
2380\end{figure}
2381
2382This picture has several components, the two most important being the entry queue and the AS-stack.
2383The entry queue is an (almost) FIFO list where threads waiting to enter are parked, while the acceptor/signaller (AS) stack is a FILO list used for threads that have been signalled or otherwise marked as running next.
2384
2385For \CFA, this picture does not have support for blocking multiple monitors on a single condition.
2386To support \textbf{bulk-acq} two changes to this picture are required.
2387First, it is no longer helpful to attach the condition to \emph{a single} monitor.
2388Secondly, the thread waiting on the condition has to be separated across multiple monitors, seen in figure \ref{fig:monitor_cfa}.
2389
2390\begin{figure}[H]
2391\begin{center}
2392{\resizebox{0.8\textwidth}{!}{\input{int_monitor}}}
2393\end{center}
2394\caption{Illustration of \CFA Monitor}
2395\label{fig:monitor_cfa}
2396\end{figure}
2397
2398This picture and the proper entry and leave algorithms (see listing \ref{lst:entry2}) is the fundamental implementation of internal scheduling.
2399Note that when a thread is moved from the condition to the AS-stack, it is conceptually split into N pieces, where N is the number of monitors specified in the parameter list.
2400The thread is woken up when all the pieces have popped from the AS-stacks and made active.
2401In this picture, the threads are split into halves but this is only because there are two monitors.
2402For a specific signalling operation every monitor needs a piece of thread on its AS-stack.
2403
2404\begin{figure}[b]
2405\begin{multicols}{2}
2406Entry
2407\begin{pseudo}
2408if monitor is free
2409        enter
2410elif already own the monitor
2411        continue
2412else
2413        block
2414increment recursion
2415
2416\end{pseudo}
2417\columnbreak
2418Exit
2419\begin{pseudo}
2420decrement recursion
2421if recursion == 0
2422        if signal_stack not empty
2423                set_owner to thread
2424                if all monitors ready
2425                        wake-up thread
2426
2427        if entry queue not empty
2428                wake-up thread
2429\end{pseudo}
2430\end{multicols}
2431\begin{pseudo}[caption={Entry and exit routine for monitors with internal scheduling},label={lst:entry2}]
2432\end{pseudo}
2433\end{figure}
2434
2435The solution discussed in \ref{intsched} can be seen in the exit routine of listing \ref{lst:entry2}.
2436Basically, the solution boils down to having a separate data structure for the condition queue and the AS-stack, and unconditionally transferring ownership of the monitors but only unblocking the thread when the last monitor has transferred ownership.
2437This solution is deadlock safe as well as preventing any potential barging.
2438The data structures used for the AS-stack are reused extensively for external scheduling, but in the case of internal scheduling, the data is allocated using variable-length arrays on the call stack of the \code{wait} and \code{signal_block} routines.
2439
2440\begin{figure}[H]
2441\begin{center}
2442{\resizebox{0.8\textwidth}{!}{\input{monitor_structs.pstex_t}}}
2443\end{center}
2444\caption{Data structures involved in internal/external scheduling}
2445\label{fig:structs}
2446\end{figure}
2447
2448Figure \ref{fig:structs} shows a high-level representation of these data structures.
2449The main idea behind them is that, a thread cannot contain an arbitrary number of intrusive ``next'' pointers for linking onto monitors.
2450The \code{condition node} is the data structure that is queued onto a condition variable and, when signalled, the condition queue is popped and each \code{condition criterion} is moved to the AS-stack.
2451Once all the criteria have been popped from their respective AS-stacks, the thread is woken up, which is what is shown in listing \ref{lst:entry2}.
2452
2453% ======================================================================
2454% ======================================================================
2455\section{External Scheduling}
2456% ======================================================================
2457% ======================================================================
2458Similarly to internal scheduling, external scheduling for multiple monitors relies on the idea that waiting-thread queues are no longer specific to a single monitor, as mentioned in section \ref{extsched}.
2459For internal scheduling, these queues are part of condition variables, which are still unique for a given scheduling operation (i.e., no signal statement uses multiple conditions).
2460However, in the case of external scheduling, there is no equivalent object which is associated with \code{waitfor} statements.
2461This absence means the queues holding the waiting threads must be stored inside at least one of the monitors that is acquired.
2462These monitors being the only objects that have sufficient lifetime and are available on both sides of the \code{waitfor} statement.
2463This requires an algorithm to choose which monitor holds the relevant queue.
2464It is also important that said algorithm be independent of the order in which users list parameters.
2465The proposed algorithm is to fall back on monitor lock ordering (sorting by address) and specify that the monitor that is acquired first is the one with the relevant waiting queue.
2466This assumes that the lock acquiring order is static for the lifetime of all concerned objects but that is a reasonable constraint.
2467
2468This algorithm choice has two consequences:
2469\begin{itemize}
2470        \item The queue of the monitor with the lowest address is no longer a true FIFO queue because threads can be moved to the front of the queue.
2471These queues need to contain a set of monitors for each of the waiting threads.
2472Therefore, another thread whose set contains the same lowest address monitor but different lower priority monitors may arrive first but enter the critical section after a thread with the correct pairing.
2473        \item The queue of the lowest priority monitor is both required and potentially unused.
2474Indeed, since it is not known at compile time which monitor is the monitor which has the lowest address, every monitor needs to have the correct queues even though it is possible that some queues go unused for the entire duration of the program, for example if a monitor is only used in a specific pair.
2475\end{itemize}
2476Therefore, the following modifications need to be made to support external scheduling:
2477\begin{itemize}
2478        \item The threads waiting on the entry queue need to keep track of which routine they are trying to enter, and using which set of monitors.
2479The \code{mutex} routine already has all the required information on its stack, so the thread only needs to keep a pointer to that information.
2480        \item The monitors need to keep a mask of acceptable routines.
2481This mask contains for each acceptable routine, a routine pointer and an array of monitors to go with it.
2482It also needs storage to keep track of which routine was accepted.
2483Since this information is not specific to any monitor, the monitors actually contain a pointer to an integer on the stack of the waiting thread.
2484Note that if a thread has acquired two monitors but executes a \code{waitfor} with only one monitor as a parameter, setting the mask of acceptable routines to both monitors will not cause any problems since the extra monitor will not change ownership regardless.
2485This becomes relevant when \code{when} clauses affect the number of monitors passed to a \code{waitfor} statement.
2486        \item The entry/exit routines need to be updated as shown in listing \ref{lst:entry3}.
2487\end{itemize}
2488
2489\subsection{External Scheduling - Destructors}
2490Finally, to support the ordering inversion of destructors, the code generation needs to be modified to use a special entry routine.
2491This routine is needed because of the storage requirements of the call order inversion.
2492Indeed, when waiting for the destructors, storage is needed for the waiting context and the lifetime of said storage needs to outlive the waiting operation it is needed for.
2493For regular \code{waitfor} statements, the call stack of the routine itself matches this requirement but it is no longer the case when waiting for the destructor since it is pushed on to the AS-stack for later.
2494The \code{waitfor} semantics can then be adjusted correspondingly, as seen in listing \ref{lst:entry-dtor}
2495
2496\begin{figure}
2497\begin{multicols}{2}
2498Entry
2499\begin{pseudo}
2500if monitor is free
2501        enter
2502elif already own the monitor
2503        continue
2504elif matches waitfor mask
2505        push criteria to AS-stack
2506        continue
2507else
2508        block
2509increment recursion
2510\end{pseudo}
2511\columnbreak
2512Exit
2513\begin{pseudo}
2514decrement recursion
2515if recursion == 0
2516        if signal_stack not empty
2517                set_owner to thread
2518                if all monitors ready
2519                        wake-up thread
2520                endif
2521        endif
2522
2523        if entry queue not empty
2524                wake-up thread
2525        endif
2526\end{pseudo}
2527\end{multicols}
2528\begin{pseudo}[caption={Entry and exit routine for monitors with internal scheduling and external scheduling},label={lst:entry3}]
2529\end{pseudo}
2530\end{figure}
2531
2532\begin{figure}
2533\begin{multicols}{2}
2534Destructor Entry
2535\begin{pseudo}
2536if monitor is free
2537        enter
2538elif already own the monitor
2539        increment recursion
2540        return
2541create wait context
2542if matches waitfor mask
2543        reset mask
2544        push self to AS-stack
2545        baton pass
2546else
2547        wait
2548increment recursion
2549\end{pseudo}
2550\columnbreak
2551Waitfor
2552\begin{pseudo}
2553if matching thread is already there
2554        if found destructor
2555                push destructor to AS-stack
2556                unlock all monitors
2557        else
2558                push self to AS-stack
2559                baton pass
2560        endif
2561        return
2562endif
2563if non-blocking
2564        Unlock all monitors
2565        Return
2566endif
2567
2568push self to AS-stack
2569set waitfor mask
2570block
2571return
2572\end{pseudo}
2573\end{multicols}
2574\begin{pseudo}[caption={Pseudo code for the \code{waitfor} routine and the \code{mutex} entry routine for destructors},label={lst:entry-dtor}]
2575\end{pseudo}
2576\end{figure}
2577
2578
2579% ======================================================================
2580% ======================================================================
2581\section{Putting It All Together}
2582% ======================================================================
2583% ======================================================================
2584
2585
2586\section{Threads As Monitors}
2587As it was subtly alluded in section \ref{threads}, \code{thread}s in \CFA are in fact monitors, which means that all monitor features are available when using threads.
2588For example, here is a very simple two thread pipeline that could be used for a simulator of a game engine:
2589\begin{figure}[H]
2590\begin{cfacode}[caption={Toy simulator using \code{thread}s and \code{monitor}s.},label={lst:engine-v1}]
2591// Visualization declaration
2592thread Renderer {} renderer;
2593Frame * simulate( Simulator & this );
2594
2595// Simulation declaration
2596thread Simulator{} simulator;
2597void render( Renderer & this );
2598
2599// Blocking call used as communication
2600void draw( Renderer & mutex this, Frame * frame );
2601
2602// Simulation loop
2603void main( Simulator & this ) {
2604        while( true ) {
2605                Frame * frame = simulate( this );
2606                draw( renderer, frame );
2607        }
2608}
2609
2610// Rendering loop
2611void main( Renderer & this ) {
2612        while( true ) {
2613                waitfor( draw, this );
2614                render( this );
2615        }
2616}
2617\end{cfacode}
2618\end{figure}
2619One of the obvious complaints of the previous code snippet (other than its toy-like simplicity) is that it does not handle exit conditions and just goes on forever.
2620Luckily, the monitor semantics can also be used to clearly enforce a shutdown order in a concise manner:
2621\begin{figure}[H]
2622\begin{cfacode}[caption={Same toy simulator with proper termination condition.},label={lst:engine-v2}]
2623// Visualization declaration
2624thread Renderer {} renderer;
2625Frame * simulate( Simulator & this );
2626
2627// Simulation declaration
2628thread Simulator{} simulator;
2629void render( Renderer & this );
2630
2631// Blocking call used as communication
2632void draw( Renderer & mutex this, Frame * frame );
2633
2634// Simulation loop
2635void main( Simulator & this ) {
2636        while( true ) {
2637                Frame * frame = simulate( this );
2638                draw( renderer, frame );
2639
2640                // Exit main loop after the last frame
2641                if( frame->is_last ) break;
2642        }
2643}
2644
2645// Rendering loop
2646void main( Renderer & this ) {
2647        while( true ) {
2648                   waitfor( draw, this );
2649                or waitfor( ^?{}, this ) {
2650                        // Add an exit condition
2651                        break;
2652                }
2653
2654                render( this );
2655        }
2656}
2657
2658// Call destructor for simulator once simulator finishes
2659// Call destructor for renderer to signify shutdown
2660\end{cfacode}
2661\end{figure}
2662
2663\section{Fibers \& Threads}
2664As mentioned in section \ref{preemption}, \CFA uses preemptive threads by default but can use fibers on demand.
2665Currently, using fibers is done by adding the following line of code to the program~:
2666\begin{cfacode}
2667unsigned int default_preemption() {
2668        return 0;
2669}
2670\end{cfacode}
2671This function is called by the kernel to fetch the default preemption rate, where 0 signifies an infinite time-slice, i.e., no preemption.
2672However, once clusters are fully implemented, it will be possible to create fibers and \textbf{uthread} in the same system, as in listing \ref{lst:fiber-uthread}
2673\begin{figure}
2674\begin{cfacode}[caption={Using fibers and \textbf{uthread} side-by-side in \CFA},label={lst:fiber-uthread}]
2675//Cluster forward declaration
2676struct cluster;
2677
2678//Processor forward declaration
2679struct processor;
2680
2681//Construct clusters with a preemption rate
2682void ?{}(cluster& this, unsigned int rate);
2683//Construct processor and add it to cluster
2684void ?{}(processor& this, cluster& cluster);
2685//Construct thread and schedule it on cluster
2686void ?{}(thread& this, cluster& cluster);
2687
2688//Declare two clusters
2689cluster thread_cluster = { 10`ms };                     //Preempt every 10 ms
2690cluster fibers_cluster = { 0 };                         //Never preempt
2691
2692//Construct 4 processors
2693processor processors[4] = {
2694        //2 for the thread cluster
2695        thread_cluster;
2696        thread_cluster;
2697        //2 for the fibers cluster
2698        fibers_cluster;
2699        fibers_cluster;
2700};
2701
2702//Declares thread
2703thread UThread {};
2704void ?{}(UThread& this) {
2705        //Construct underlying thread to automatically
2706        //be scheduled on the thread cluster
2707        (this){ thread_cluster }
2708}
2709
2710void main(UThread & this);
2711
2712//Declares fibers
2713thread Fiber {};
2714void ?{}(Fiber& this) {
2715        //Construct underlying thread to automatically
2716        //be scheduled on the fiber cluster
2717        (this.__thread){ fibers_cluster }
2718}
2719
2720void main(Fiber & this);
2721\end{cfacode}
2722\end{figure}
2723
2724
2725% ======================================================================
2726% ======================================================================
2727\section{Performance Results} \label{results}
2728% ======================================================================
2729% ======================================================================
2730\section{Machine Setup}
2731Table \ref{tab:machine} shows the characteristics of the machine used to run the benchmarks.
2732All tests were made on this machine.
2733\begin{table}[H]
2734\begin{center}
2735\begin{tabular}{| l | r | l | r |}
2736\hline
2737Architecture            & x86\_64                       & NUMA node(s)  & 8 \\
2738\hline
2739CPU op-mode(s)          & 32-bit, 64-bit                & Model name    & AMD Opteron\texttrademark  Processor 6380 \\
2740\hline
2741Byte Order                      & Little Endian                 & CPU Freq              & 2.5\si{\giga\hertz} \\
2742\hline
2743CPU(s)                  & 64                            & L1d cache     & \SI{16}{\kibi\byte} \\
2744\hline
2745Thread(s) per core      & 2                             & L1i cache     & \SI{64}{\kibi\byte} \\
2746\hline
2747Core(s) per socket      & 8                             & L2 cache              & \SI{2048}{\kibi\byte} \\
2748\hline
2749Socket(s)                       & 4                             & L3 cache              & \SI{6144}{\kibi\byte} \\
2750\hline
2751\hline
2752Operating system                & Ubuntu 16.04.3 LTS    & Kernel                & Linux 4.4-97-generic \\
2753\hline
2754Compiler                        & GCC 6.3               & Translator    & CFA 1 \\
2755\hline
2756Java version            & OpenJDK-9             & Go version    & 1.9.2 \\
2757\hline
2758\end{tabular}
2759\end{center}
2760\caption{Machine setup used for the tests}
2761\label{tab:machine}
2762\end{table}
2763
2764\section{Micro Benchmarks}
2765All benchmarks are run using the same harness to produce the results, seen as the \code{BENCH()} macro in the following examples.
2766This macro uses the following logic to benchmark the code:
2767\begin{pseudo}
2768#define BENCH(run, result) \
2769        before = gettime(); \
2770        run; \
2771        after  = gettime(); \
2772        result = (after - before) / N;
2773\end{pseudo}
2774The method used to get time is \code{clock_gettime(CLOCK_THREAD_CPUTIME_ID);}.
2775Each benchmark is using many iterations of a simple call to measure the cost of the call.
2776The specific number of iterations depends on the specific benchmark.
2777
2778\subsection{Context-Switching}
2779The first interesting benchmark is to measure how long context-switches take.
2780The simplest approach to do this is to yield on a thread, which executes a 2-step context switch.
2781Yielding causes the thread to context-switch to the scheduler and back, more precisely: from the \textbf{uthread} to the \textbf{kthread} then from the \textbf{kthread} back to the same \textbf{uthread} (or a different one in the general case).
2782In order to make the comparison fair, coroutines also execute a 2-step context-switch by resuming another coroutine which does nothing but suspending in a tight loop, which is a resume/suspend cycle instead of a yield.
2783Listing \ref{lst:ctx-switch} shows the code for coroutines and threads with the results in table \ref{tab:ctx-switch}.
2784All omitted tests are functionally identical to one of these tests.
2785The difference between coroutines and threads can be attributed to the cost of scheduling.
2786\begin{figure}
2787\begin{multicols}{2}
2788\CFA Coroutines
2789\begin{cfacode}
2790coroutine GreatSuspender {};
2791void main(GreatSuspender& this) {
2792        while(true) { suspend(); }
2793}
2794int main() {
2795        GreatSuspender s;
2796        resume(s);
2797        BENCH(
2798                for(size_t i=0; i<n; i++) {
2799                        resume(s);
2800                },
2801                result
2802        )
2803        printf("%llu\n", result);
2804}
2805\end{cfacode}
2806\columnbreak
2807\CFA Threads
2808\begin{cfacode}
2809
2810
2811
2812
2813int main() {
2814
2815
2816        BENCH(
2817                for(size_t i=0; i<n; i++) {
2818                        yield();
2819                },
2820                result
2821        )
2822        printf("%llu\n", result);
2823}
2824\end{cfacode}
2825\end{multicols}
2826\begin{cfacode}[caption={\CFA benchmark code used to measure context-switches for coroutines and threads.},label={lst:ctx-switch}]
2827\end{cfacode}
2828\end{figure}
2829
2830\begin{table}
2831\begin{center}
2832\begin{tabular}{| l | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] |}
2833\cline{2-4}
2834\multicolumn{1}{c |}{} & \multicolumn{1}{c |}{ Median } &\multicolumn{1}{c |}{ Average } & \multicolumn{1}{c |}{ Standard Deviation} \\
2835\hline
2836Kernel Thread   & 241.5 & 243.86        & 5.08 \\
2837\CFA Coroutine  & 38            & 38            & 0    \\
2838\CFA Thread             & 103           & 102.96        & 2.96 \\
2839\uC Coroutine   & 46            & 45.86 & 0.35 \\
2840\uC Thread              & 98            & 99.11 & 1.42 \\
2841Goroutine               & 150           & 149.96        & 3.16 \\
2842Java Thread             & 289           & 290.68        & 8.72 \\
2843\hline
2844\end{tabular}
2845\end{center}
2846\caption{Context Switch comparison.
2847All numbers are in nanoseconds(\si{\nano\second})}
2848\label{tab:ctx-switch}
2849\end{table}
2850
2851\subsection{Mutual-Exclusion}
2852The next interesting benchmark is to measure the overhead to enter/leave a critical-section.
2853For monitors, the simplest approach is to measure how long it takes to enter and leave a monitor routine.
2854Listing \ref{lst:mutex} shows the code for \CFA.
2855To put the results in context, the cost of entering a non-inline function and the cost of acquiring and releasing a \code{pthread_mutex} lock is also measured.
2856The results can be shown in table \ref{tab:mutex}.
2857
2858\begin{figure}
2859\begin{cfacode}[caption={\CFA benchmark code used to measure mutex routines.},label={lst:mutex}]
2860monitor M {};
2861void __attribute__((noinline)) call( M & mutex m /*, m2, m3, m4*/ ) {}
2862
2863int main() {
2864        M m/*, m2, m3, m4*/;
2865        BENCH(
2866                for(size_t i=0; i<n; i++) {
2867                        call(m/*, m2, m3, m4*/);
2868                },
2869                result
2870        )
2871        printf("%llu\n", result);
2872}
2873\end{cfacode}
2874\end{figure}
2875
2876\begin{table}
2877\begin{center}
2878\begin{tabular}{| l | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] |}
2879\cline{2-4}
2880\multicolumn{1}{c |}{} & \multicolumn{1}{c |}{ Median } &\multicolumn{1}{c |}{ Average } & \multicolumn{1}{c |}{ Standard Deviation} \\
2881\hline
2882C routine                                               & 2             & 2             & 0    \\
2883FetchAdd + FetchSub                             & 26            & 26            & 0    \\
2884Pthreads Mutex Lock                             & 31            & 31.86 & 0.99 \\
2885\uC \code{monitor} member routine               & 30            & 30            & 0    \\
2886\CFA \code{mutex} routine, 1 argument   & 41            & 41.57 & 0.9  \\
2887\CFA \code{mutex} routine, 2 argument   & 76            & 76.96 & 1.57 \\
2888\CFA \code{mutex} routine, 4 argument   & 145           & 146.68        & 3.85 \\
2889Java synchronized routine                       & 27            & 28.57 & 2.6  \\
2890\hline
2891\end{tabular}
2892\end{center}
2893\caption{Mutex routine comparison.
2894All numbers are in nanoseconds(\si{\nano\second})}
2895\label{tab:mutex}
2896\end{table}
2897
2898\subsection{Internal Scheduling}
2899The internal-scheduling benchmark measures the cost of waiting on and signalling a condition variable.
2900Listing \ref{lst:int-sched} shows the code for \CFA, with results table \ref{tab:int-sched}.
2901As with all other benchmarks, all omitted tests are functionally identical to one of these tests.
2902
2903\begin{figure}
2904\begin{cfacode}[caption={Benchmark code for internal scheduling},label={lst:int-sched}]
2905volatile int go = 0;
2906condition c;
2907monitor M {};
2908M m1;
2909
2910void __attribute__((noinline)) do_call( M & mutex a1 ) { signal(c); }
2911
2912thread T {};
2913void ^?{}( T & mutex this ) {}
2914void main( T & this ) {
2915        while(go == 0) { yield(); }
2916        while(go == 1) { do_call(m1); }
2917}
2918int  __attribute__((noinline)) do_wait( M & mutex a1 ) {
2919        go = 1;
2920        BENCH(
2921                for(size_t i=0; i<n; i++) {
2922                        wait(c);
2923                },
2924                result
2925        )
2926        printf("%llu\n", result);
2927        go = 0;
2928        return 0;
2929}
2930int main() {
2931        T t;
2932        return do_wait(m1);
2933}
2934\end{cfacode}
2935\end{figure}
2936
2937\begin{table}
2938\begin{center}
2939\begin{tabular}{| l | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] |}
2940\cline{2-4}
2941\multicolumn{1}{c |}{} & \multicolumn{1}{c |}{ Median } &\multicolumn{1}{c |}{ Average } & \multicolumn{1}{c |}{ Standard Deviation} \\
2942\hline
2943Pthreads Condition Variable                     & 5902.5        & 6093.29       & 714.78 \\
2944\uC \code{signal}                                       & 322           & 323   & 3.36   \\
2945\CFA \code{signal}, 1 \code{monitor}    & 352.5 & 353.11        & 3.66   \\
2946\CFA \code{signal}, 2 \code{monitor}    & 430           & 430.29        & 8.97   \\
2947\CFA \code{signal}, 4 \code{monitor}    & 594.5 & 606.57        & 18.33  \\
2948Java \code{notify}                              & 13831.5       & 15698.21      & 4782.3 \\
2949\hline
2950\end{tabular}
2951\end{center}
2952\caption{Internal scheduling comparison.
2953All numbers are in nanoseconds(\si{\nano\second})}
2954\label{tab:int-sched}
2955\end{table}
2956
2957\subsection{External Scheduling}
2958The Internal scheduling benchmark measures the cost of the \code{waitfor} statement (\code{_Accept} in \uC).
2959Listing \ref{lst:ext-sched} shows the code for \CFA, with results in table \ref{tab:ext-sched}.
2960As with all other benchmarks, all omitted tests are functionally identical to one of these tests.
2961
2962\begin{figure}
2963\begin{cfacode}[caption={Benchmark code for external scheduling},label={lst:ext-sched}]
2964volatile int go = 0;
2965monitor M {};
2966M m1;
2967thread T {};
2968
2969void __attribute__((noinline)) do_call( M & mutex a1 ) {}
2970
2971void ^?{}( T & mutex this ) {}
2972void main( T & this ) {
2973        while(go == 0) { yield(); }
2974        while(go == 1) { do_call(m1); }
2975}
2976int  __attribute__((noinline)) do_wait( M & mutex a1 ) {
2977        go = 1;
2978        BENCH(
2979                for(size_t i=0; i<n; i++) {
2980                        waitfor(call, a1);
2981                },
2982                result
2983        )
2984        printf("%llu\n", result);
2985        go = 0;
2986        return 0;
2987}
2988int main() {
2989        T t;
2990        return do_wait(m1);
2991}
2992\end{cfacode}
2993\end{figure}
2994
2995\begin{table}
2996\begin{center}
2997\begin{tabular}{| l | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] |}
2998\cline{2-4}
2999\multicolumn{1}{c |}{} & \multicolumn{1}{c |}{ Median } &\multicolumn{1}{c |}{ Average } & \multicolumn{1}{c |}{ Standard Deviation} \\
3000\hline
3001\uC \code{Accept}                                       & 350           & 350.61        & 3.11  \\
3002\CFA \code{waitfor}, 1 \code{monitor}   & 358.5 & 358.36        & 3.82  \\
3003\CFA \code{waitfor}, 2 \code{monitor}   & 422           & 426.79        & 7.95  \\
3004\CFA \code{waitfor}, 4 \code{monitor}   & 579.5 & 585.46        & 11.25 \\
3005\hline
3006\end{tabular}
3007\end{center}
3008\caption{External scheduling comparison.
3009All numbers are in nanoseconds(\si{\nano\second})}
3010\label{tab:ext-sched}
3011\end{table}
3012
3013\subsection{Object Creation}
3014Finally, the last benchmark measures the cost of creation for concurrent objects.
3015Listing \ref{lst:creation} shows the code for \texttt{pthread}s and \CFA threads, with results shown in table \ref{tab:creation}.
3016As with all other benchmarks, all omitted tests are functionally identical to one of these tests.
3017The only note here is that the call stacks of \CFA coroutines are lazily created, therefore without priming the coroutine, the creation cost is very low.
3018
3019\begin{figure}
3020\begin{center}
3021\texttt{pthread}
3022\begin{ccode}
3023int main() {
3024        BENCH(
3025                for(size_t i=0; i<n; i++) {
3026                        pthread_t thread;
3027                        if(pthread_create(&thread,NULL,foo,NULL)<0) {
3028                                perror( "failure" );
3029                                return 1;
3030                        }
3031
3032                        if(pthread_join(thread, NULL)<0) {
3033                                perror( "failure" );
3034                                return 1;
3035                        }
3036                },
3037                result
3038        )
3039        printf("%llu\n", result);
3040}
3041\end{ccode}
3042
3043
3044
3045\CFA Threads
3046\begin{cfacode}
3047int main() {
3048        BENCH(
3049                for(size_t i=0; i<n; i++) {
3050                        MyThread m;
3051                },
3052                result
3053        )
3054        printf("%llu\n", result);
3055}
3056\end{cfacode}
3057\end{center}
3058\begin{cfacode}[caption={Benchmark code for \texttt{pthread}s and \CFA to measure object creation},label={lst:creation}]
3059\end{cfacode}
3060\end{figure}
3061
3062\begin{table}
3063\begin{center}
3064\begin{tabular}{| l | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] | S[table-format=5.2,table-number-alignment=right] |}
3065\cline{2-4}
3066\multicolumn{1}{c |}{} & \multicolumn{1}{c |}{ Median } &\multicolumn{1}{c |}{ Average } & \multicolumn{1}{c |}{ Standard Deviation} \\
3067\hline
3068Pthreads                        & 26996 & 26984.71      & 156.6  \\
3069\CFA Coroutine Lazy     & 6             & 5.71  & 0.45   \\
3070\CFA Coroutine Eager    & 708           & 706.68        & 4.82   \\
3071\CFA Thread                     & 1173.5        & 1176.18       & 15.18  \\
3072\uC Coroutine           & 109           & 107.46        & 1.74   \\
3073\uC Thread                      & 526           & 530.89        & 9.73   \\
3074Goroutine                       & 2520.5        & 2530.93       & 61,56  \\
3075Java Thread                     & 91114.5       & 92272.79      & 961.58 \\
3076\hline
3077\end{tabular}
3078\end{center}
3079\caption{Creation comparison.
3080All numbers are in nanoseconds(\si{\nano\second}).}
3081\label{tab:creation}
3082\end{table}
3083
3084
3085
3086\section{Conclusion}
3087This paper has achieved a minimal concurrency \textbf{api} that is simple, efficient and usable as the basis for higher-level features.
3088The approach presented is based on a lightweight thread-system for parallelism, which sits on top of clusters of processors.
3089This M:N model is judged to be both more efficient and allow more flexibility for users.
3090Furthermore, this document introduces monitors as the main concurrency tool for users.
3091This paper also offers a novel approach allowing multiple monitors to be accessed simultaneously without running into the Nested Monitor Problem~\cite{Lister77}.
3092It also offers a full implementation of the concurrency runtime written entirely in \CFA, effectively the largest \CFA code base to date.
3093
3094
3095% ======================================================================
3096% ======================================================================
3097\section{Future Work}
3098% ======================================================================
3099% ======================================================================
3100
3101\subsection{Performance} \label{futur:perf}
3102This paper presents a first implementation of the \CFA concurrency runtime.
3103Therefore, there is still significant work to improve performance.
3104Many of the data structures and algorithms may change in the future to more efficient versions.
3105For example, the number of monitors in a single \textbf{bulk-acq} is only bound by the stack size, this is probably unnecessarily generous.
3106It may be possible that limiting the number helps increase performance.
3107However, it is not obvious that the benefit would be significant.
3108
3109\subsection{Flexible Scheduling} \label{futur:sched}
3110An important part of concurrency is scheduling.
3111Different scheduling algorithms can affect performance (both in terms of average and variation).
3112However, no single scheduler is optimal for all workloads and therefore there is value in being able to change the scheduler for given programs.
3113One solution is to offer various tweaking options to users, allowing the scheduler to be adjusted to the requirements of the workload.
3114However, in order to be truly flexible, it would be interesting to allow users to add arbitrary data and arbitrary scheduling algorithms.
3115For example, a web server could attach Type-of-Service information to threads and have a ``ToS aware'' scheduling algorithm tailored to this specific web server.
3116This path of flexible schedulers will be explored for \CFA.
3117
3118\subsection{Non-Blocking I/O} \label{futur:nbio}
3119While most of the parallelism tools are aimed at data parallelism and control-flow parallelism, many modern workloads are not bound on computation but on IO operations, a common case being web servers and XaaS (anything as a service).
3120These types of workloads often require significant engineering around amortizing costs of blocking IO operations.
3121At its core, non-blocking I/O is an operating system level feature that allows queuing IO operations (e.g., network operations) and registering for notifications instead of waiting for requests to complete.
3122In this context, the role of the language makes Non-Blocking IO easily available and with low overhead.
3123The current trend is to use asynchronous programming using tools like callbacks and/or futures and promises, which can be seen in frameworks like Node.js~\cite{NodeJs} for JavaScript, Spring MVC~\cite{SpringMVC} for Java and Django~\cite{Django} for Python.
3124However, while these are valid solutions, they lead to code that is harder to read and maintain because it is much less linear.
3125
3126\subsection{Other Concurrency Tools} \label{futur:tools}
3127While monitors offer a flexible and powerful concurrent core for \CFA, other concurrency tools are also necessary for a complete multi-paradigm concurrency package.
3128Examples of such tools can include simple locks and condition variables, futures and promises~\cite{promises}, executors and actors.
3129These additional features are useful when monitors offer a level of abstraction that is inadequate for certain tasks.
3130
3131\subsection{Implicit Threading} \label{futur:implcit}
3132Simpler applications can benefit greatly from having implicit parallelism.
3133That is, parallelism that does not rely on the user to write concurrency.
3134This type of parallelism can be achieved both at the language level and at the library level.
3135The canonical example of implicit parallelism is parallel for loops, which are the simplest example of a divide and conquer algorithms~\cite{uC++book}.
3136Table \ref{lst:parfor} shows three different code examples that accomplish point-wise sums of large arrays.
3137Note that none of these examples explicitly declare any concurrency or parallelism objects.
3138
3139\begin{table}
3140\begin{center}
3141\begin{tabular}[t]{|c|c|c|}
3142Sequential & Library Parallel & Language Parallel \\
3143\begin{cfacode}[tabsize=3]
3144void big_sum(
3145        int* a, int* b,
3146        int* o,
3147        size_t len)
3148{
3149        for(
3150                int i = 0;
3151                i < len;
3152                ++i )
3153        {
3154                o[i]=a[i]+b[i];
3155        }
3156}
3157
3158
3159
3160
3161
3162int* a[10000];
3163int* b[10000];
3164int* c[10000];
3165//... fill in a & b
3166big_sum(a,b,c,10000);
3167\end{cfacode} &\begin{cfacode}[tabsize=3]
3168void big_sum(
3169        int* a, int* b,
3170        int* o,
3171        size_t len)
3172{
3173        range ar(a, a+len);
3174        range br(b, b+len);
3175        range or(o, o+len);
3176        parfor( ai, bi, oi,
3177        [](     int* ai,
3178                int* bi,
3179                int* oi)
3180        {
3181                oi=ai+bi;
3182        });
3183}
3184
3185
3186int* a[10000];
3187int* b[10000];
3188int* c[10000];
3189//... fill in a & b
3190big_sum(a,b,c,10000);
3191\end{cfacode}&\begin{cfacode}[tabsize=3]
3192void big_sum(
3193        int* a, int* b,
3194        int* o,
3195        size_t len)
3196{
3197        parfor (ai,bi,oi)
3198            in (a, b, o )
3199        {
3200                oi = ai + bi;
3201        }
3202}
3203
3204
3205
3206
3207
3208
3209
3210int* a[10000];
3211int* b[10000];
3212int* c[10000];
3213//... fill in a & b
3214big_sum(a,b,c,10000);
3215\end{cfacode}
3216\end{tabular}
3217\end{center}
3218\caption{For loop to sum numbers: Sequential, using library parallelism and language parallelism.}
3219\label{lst:parfor}
3220\end{table}
3221
3222Implicit parallelism is a restrictive solution and therefore has its limitations.
3223However, it is a quick and simple approach to parallelism, which may very well be sufficient for smaller applications and reduces the amount of boilerplate needed to start benefiting from parallelism in modern CPUs.
3224
3225
3226% A C K N O W L E D G E M E N T S
3227% -------------------------------
3228\section{Acknowledgements}
3229
3230Thanks to Aaron Moss, Rob Schluntz and Andrew Beach for their work on the \CFA project as well as all the discussions which helped concretize the ideas in this paper.
3231Partial funding was supplied by the Natural Sciences and Engineering Research Council of Canada and a corporate partnership with Huawei Ltd.
3232
3233
3234% B I B L I O G R A P H Y
3235% -----------------------------
3236%\bibliographystyle{plain}
3237\bibliography{pl,local}
3238
3239\end{document}
3240
3241% Local Variables: %
3242% tab-width: 4 %
3243% fill-column: 120 %
3244% compile-command: "make" %
3245% End: %
Note: See TracBrowser for help on using the repository browser.