Changeset 3f7e12cb for doc


Ignore:
Timestamp:
Nov 8, 2017, 5:43:33 PM (8 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, stuck-waitfor-destruct, with_gc
Children:
954908d
Parents:
78315272 (diff), e35f30a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
doc
Files:
6 added
1 deleted
13 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/lstlang.sty

    r78315272 r3f7e12cb  
    22%%
    33%% Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
    4 %% 
    5 %% lstlang.sty -- 
    6 %% 
     4%%
     5%% lstlang.sty --
     6%%
    77%% Author           : Peter A. Buhr
    88%% Created On       : Sat May 13 16:34:42 2017
     
    110110                __attribute__, auto, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__,
    111111                __const, __const__, disable, dtype, enable, __extension__, fallthrough, fallthru,
    112                 finally, forall, ftype, _Generic, _Imaginary, inline, __label__, lvalue, _Noreturn, one_t, 
    113                 otype, restrict, _Static_assert, throw, throwResume, trait, try, ttype, typeof, __typeof, 
    114                 __typeof__, virtual, waitfor, when, with, zero_t},
     112                finally, forall, ftype, _Generic, _Imaginary, inline, __label__, lvalue, _Noreturn, one_t,
     113                otype, restrict, _Static_assert, throw, throwResume, trait, try, ttype, typeof, __typeof,
     114                __typeof__, virtual, with, zero_t},
    115115        morekeywords=[2]{
    116                 _Atomic, coroutine, is_coroutine, is_monitor, is_thread, monitor, mutex, nomutex,
    117                 resume, suspend, thread, _Thread_local, yield},
     116                _Atomic, coroutine, is_coroutine, is_monitor, is_thread, monitor, mutex, nomutex, or,
     117                resume, suspend, thread, _Thread_local, waitfor, when, yield},
    118118        moredirectives={defined,include_next}%
    119119}
  • doc/proposals/concurrency/.gitignore

    r78315272 r3f7e12cb  
    1616build/*.out
    1717build/*.ps
     18build/*.pstex
     19build/*.pstex_t
    1820build/*.tex
    1921build/*.toc
  • doc/proposals/concurrency/Makefile

    r78315272 r3f7e12cb  
    1313annex/glossary \
    1414text/intro \
     15text/basics \
    1516text/cforall \
    16 text/basics \
    1717text/concurrency \
     18text/internals \
    1819text/parallelism \
     20text/results \
     21text/together \
     22text/future \
    1923}
    2024
     
    2327        ext_monitor \
    2428        int_monitor \
     29        dependency \
    2530}}
    2631
    27 PICTURES = ${addsuffix .pstex, \
    28 }
     32PICTURES = ${addprefix build/, ${addsuffix .pstex, \
     33        system \
     34}}
    2935
    3036PROGRAMS = ${addsuffix .tex, \
     
    6369        build/*.out     \
    6470        build/*.ps      \
     71        build/*.pstex   \
    6572        build/*.pstex_t \
    6673        build/*.tex     \
  • doc/proposals/concurrency/annex/glossary.tex

    r78315272 r3f7e12cb  
    1313}
    1414
    15 \longnewglossaryentry{group-acquire}
    16 {name={bulk acquiring}}
     15\longnewglossaryentry{bulk-acq}
     16{name={bulk-acquiring}}
    1717{
    1818Implicitly acquiring several monitors when entering a monitor.
     19}
     20
     21\longnewglossaryentry{multi-acq}
     22{name={multiple-acquisition}}
     23{
     24Any locking technique which allow any single thread to acquire a lock multiple times.
    1925}
    2026
     
    101107\newacronym{api}{API}{Application Program Interface}
    102108\newacronym{raii}{RAII}{Ressource Acquisition Is Initialization}
     109\newacronym{numa}{NUMA}{Non-Uniform Memory Access}
  • doc/proposals/concurrency/figures/ext_monitor.fig

    r78315272 r3f7e12cb  
    14144 1 -1 0 0 0 10 0.0000 2 105 90 6000 2160 d\001
    1515-6
    16 6 5850 1650 6150 1950
    17 1 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 1800 105 105 6000 1800 6105 1905
    18 4 1 -1 0 0 0 10 0.0000 2 105 90 6000 1860 b\001
     166 5100 2100 5400 2400
     171 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 5250 2250 105 105 5250 2250 5355 2250
     184 1 -1 0 0 0 10 0.0000 2 105 120 5250 2295 X\001
    1919-6
    20206 5100 1800 5400 2100
     
    22224 1 -1 0 0 0 10 0.0000 2 105 120 5250 2010 Y\001
    2323-6
    24 6 5100 2100 5400 2400
    25 1 3 0 1 -1 -1 1 0 4 0.000 1 0.0000 5250 2250 105 105 5250 2250 5355 2250
    26 4 1 -1 0 0 0 10 0.0000 2 105 120 5250 2295 X\001
     246 5850 1650 6150 1950
     251 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 6000 1800 105 105 6000 1800 6105 1905
     264 1 -1 0 0 0 10 0.0000 2 105 90 6000 1860 b\001
    2727-6
    28 6 3000 5400 7200 5700
     286 3070 5445 7275 5655
    29291 3 0 1 -1 -1 0 0 20 0.000 1 0.0000 3150 5550 80 80 3150 5550 3230 5630
    30301 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 4500 5550 105 105 4500 5550 4605 5655
     
    32324 0 -1 0 0 0 12 0.0000 2 135 1035 4725 5625 blocked task\001
    33334 0 -1 0 0 0 12 0.0000 2 135 870 3300 5625 active task\001
    34 4 0 -1 0 0 0 12 0.0000 2 180 930 6225 5625 routine ptrs\001
     344 0 -1 0 0 0 12 0.0000 2 135 1050 6225 5625 routine mask\001
    3535-6
    36361 3 0 1 -1 -1 0 0 -1 0.000 1 0.0000 3300 3600 105 105 3300 3600 3405 3705
     
    43432 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    4444         4050 2925 5475 2925 5475 3225 4050 3225 4050 2925
    45 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 2
    46          5850 2850 6075 3000
    47452 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    4846         3150 3750 3750 3750 3750 4050 3150 4050
     
    66642 2 1 1 -1 -1 0 0 -1 4.000 0 0 0 0 0 5
    6765         5850 4200 5850 3300 4350 3300 4350 4200 5850 4200
    68 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 3
    69          5250 2850 5850 2850 5850 1650
    70 2 1 0 1 -1 -1 0 0 -1 0.000 0 0 -1 0 0 4
    71          3150 3150 3750 3150 3750 2850 5325 2850
    72662 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
    7367        1 1 1.00 60.00 120.00
    7468        7 1 1.00 60.00 120.00
    7569         5250 3150 5250 2400
     702 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
     71         3150 3150 3750 3150 3750 2850 5850 2850 5850 1650
     722 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
     73         5850 2850 6150 3000
    76742 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    7775         5100 1800 5400 1800 5400 2400 5100 2400 5100 1800
  • doc/proposals/concurrency/style/cfa-format.tex

    r78315272 r3f7e12cb  
    108108  belowskip=3pt,
    109109  keepspaces=true,
     110  tabsize=4,
    110111  % frame=lines,
    111112  literate=,
     
    133134  belowskip=3pt,
    134135  keepspaces=true,
     136  tabsize=4,
    135137  % frame=lines,
    136138  literate=,
     
    150152  keywordstyle=\bfseries\color{blue},
    151153  keywordstyle=[2]\bfseries\color{Plum},
    152   commentstyle=\itshape\color{OliveGreen},                  % green and italic comments
     154  commentstyle=\sf\itshape\color{OliveGreen},             % green and italic comments
    153155  identifierstyle=\color{identifierCol},
    154156  stringstyle=\sf\color{Mahogany},                                % use sanserif font
     
    158160  belowskip=3pt,
    159161  keepspaces=true,
     162  tabsize=4,
    160163  % frame=lines,
    161164  literate=,
     
    251254}{}
    252255
     256\lstnewenvironment{gocode}[1][]{
     257  \lstset{
     258    language = Golang,
     259    style=defaultStyle,
     260    #1
     261  }
     262}{}
     263
    253264\newcommand{\zero}{\lstinline{zero_t}\xspace}
    254265\newcommand{\one}{\lstinline{one_t}\xspace}
  • doc/proposals/concurrency/text/basics.tex

    r78315272 r3f7e12cb  
    11% ======================================================================
    22% ======================================================================
    3 \chapter{Basics}\label{basics}
     3\chapter{Concurrency Basics}\label{basics}
    44% ======================================================================
    55% ======================================================================
    6 Before 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.
     6Before 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.
    77
    88\section{Basics of concurrency}
    9 At its core, concurrency is based on having call-stacks and potentially multiple threads of execution for these stacks. Concurrency without parallelism only requires having multiple call stacks (or contexts) for a single thread of execution, and switching between these call stacks on a regular basis. A minimal concurrency product can be achieved by creating coroutines, which instead of context switching between each other, always ask an oracle where to context switch next. While coroutines do not technically require a stack, stackfull coroutines are the closest abstraction to a practical "naked"" call stack. When writing concurrency in terms of coroutines, the oracle effectively becomes a scheduler and the whole system now follows a cooperative threading-model \cit. The oracle/scheduler can either be a stackless or stackfull entity and correspondingly require one or two context switches to run a different coroutine. In any case, a subset of concurrency related challenges start to appear. For the complete set of concurrency challenges to occur, the only feature missing is preemption. Indeed, concurrency challenges appear with non-determinism. Guaranteeing mutual-exclusion or synchronisation are simply ways of limiting the lack of determinism in a system. A scheduler introduces order of execution uncertainty, while preemption introduces incertainty about where context-switches occur. Now it is important to understand that uncertainty is not necessarily undesireable; uncertainty can often be used by systems to significantly increase performance and is often the basis of giving a user the illusion that tasks are running in parallel. Optimal performance in concurrent applications is often obtained by having as much non-determinism as correctness allows\cit.
     9At its core, concurrency is based on having multiple call-stacks and scheduling among threads of execution executing on these stacks. Concurrency without parallelism only requires having multiple call stacks (or contexts) for a single thread of execution.
     10
     11Execution with a single thread and multiple stacks where the thread is self-scheduling deterministically across the stacks is called coroutining. Execution with a single and multiple stacks but where the thread is scheduled by an oracle (non-deterministic from the thread perspective) across the stacks is called concurrency.
     12
     13Therefore, a minimal concurrency system can be achieved by creating coroutines, which instead of context switching among each other, always ask an oracle where to context switch next. While coroutines can execute on the caller's stack-frame, stackfull coroutines allow full generality and are sufficient as the basis for concurrency. The aforementioned oracle is a scheduler and the whole system now follows a cooperative threading-model \cit. The oracle/scheduler can either be a stackless or stackfull entity and correspondingly require one or two context switches to run a different coroutine. In any case, a subset of concurrency related challenges start to appear. For the complete set of concurrency challenges to occur, the only feature missing is preemption.
     14
     15A scheduler introduces order of execution uncertainty, while preemption introduces uncertainty about where context-switches occur. Mutual-exclusion and synchronisation are ways of limiting non-determinism in a concurrent system. Now it is important to understand that uncertainty is desireable; 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. Optimal performance in concurrent applications is often obtained by having as much non-determinism as correctness allows\cit.
    1016
    1117\section{\protect\CFA 's Thread Building Blocks}
    12 One of the important features that is missing in C is threading. On modern architectures, a lack of threading is becoming less and less forgivable\cite{Sutter05, Sutter05b}, and therefore modern programming languages must have the proper tools to allow users to write performant concurrent and/or parallel programs. As an extension of C, \CFA needs to express these concepts in a way that is as natural as possible to programmers used to imperative languages. And being a system-level language means programmers expect to choose precisely which features they need and which cost they are willing to pay.
     18One of the important features that is missing in C is threading. On 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 performant concurrent programs to take advantage of parallelism. As 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. And being a system-level language means programmers expect to choose precisely which features they need and which cost they are willing to pay.
    1319
    1420\section{Coroutines: A stepping stone}\label{coroutine}
    15 While the main focus of this proposal is concurrency and parallelism, as mentionned above it is important to adress coroutines, which are actually a significant underlying aspect of a concurrency system. Indeed, while having nothing to do with parallelism and arguably little to do with concurrency, coroutines need to deal with context-switchs and other context-management operations. Therefore, this proposal includes coroutines both as an intermediate step for the implementation of threads, and a first class feature of \CFA. Furthermore, many design challenges of threads are at least partially present in designing coroutines, which makes the design effort that much more relevant. The core API of coroutines revolve around two features: independent call stacks and \code{suspend}/\code{resume}.
    16 
    17 Here is an example of a solution to the fibonnaci problem using \CFA coroutines:
    18 \begin{cfacode}
    19         coroutine Fibonacci {
    20               int fn; // used for communication
    21         };
    22 
    23         void ?{}(Fibonacci & this) { // constructor
    24               this.fn = 0;
    25         }
    26 
    27         // main automacically called on first resume
    28         void main(Fibonacci & this) {
    29                 int fn1, fn2;           // retained between resumes
    30                 this.fn = 0;
    31                 fn1 = this.fn;
    32                 suspend(this);          // return to last resume
    33 
    34                 this.fn = 1;
     21While 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. Coroutines need to deal with context-switches and other context-management operations. Therefore, this proposal includes coroutines both as an intermediate step for the implementation of threads, and a first class feature of \CFA. Furthermore, many design challenges of threads are at least partially present in designing coroutines, which makes the design effort that much more relevant. The core \acrshort{api} of coroutines revolve around two features: independent call stacks and \code{suspend}/\code{resume}.
     22
     23\begin{figure}
     24\begin{center}
     25\begin{tabular}{c @{\hskip 0.025in}|@{\hskip 0.025in} c @{\hskip 0.025in}|@{\hskip 0.025in} c}
     26\begin{ccode}[tabsize=2]
     27//Using callbacks
     28void fibonacci_func(
     29        int n,
     30        void (*callback)(int)
     31) {
     32        int first = 0;
     33        int second = 1;
     34        int next, i;
     35        for(i = 0; i < n; i++)
     36        {
     37                if(i <= 1)
     38                        next = i;
     39                else {
     40                        next = f1 + f2;
     41                        f1 = f2;
     42                        f2 = next;
     43                }
     44                callback(next);
     45        }
     46}
     47
     48int main() {
     49        void print_fib(int n) {
     50                printf("%d\n", n);
     51        }
     52
     53        fibonacci_func(
     54                10, print_fib
     55        );
     56
     57
     58
     59}
     60\end{ccode}&\begin{ccode}[tabsize=2]
     61//Using output array
     62void fibonacci_array(
     63        int n,
     64        int * array
     65) {
     66        int f1 = 0; int f2 = 1;
     67        int next, i;
     68        for(i = 0; i < n; i++)
     69        {
     70                if(i <= 1)
     71                        next = i;
     72                else {
     73                        next = f1 + f2;
     74                        f1 = f2;
     75                        f2 = next;
     76                }
     77                array[i] = next;
     78        }
     79}
     80
     81
     82int main() {
     83        int a[10];
     84
     85        fibonacci_func(
     86                10, a
     87        );
     88
     89        for(int i=0;i<10;i++){
     90                printf("%d\n", a[i]);
     91        }
     92
     93}
     94\end{ccode}&\begin{ccode}[tabsize=2]
     95//Using external state
     96typedef struct {
     97        int f1, f2;
     98} Iterator_t;
     99
     100int fibonacci_state(
     101        Iterator_t * it
     102) {
     103        int f;
     104        f = it->f1 + it->f2;
     105        it->f2 = it->f1;
     106        it->f1 = max(f,1);
     107        return f;
     108}
     109
     110
     111
     112
     113
     114
     115
     116int main() {
     117        Iterator_t it={0,0};
     118
     119        for(int i=0;i<10;i++){
     120                printf("%d\n",
     121                        fibonacci_state(
     122                                &it
     123                        );
     124                );
     125        }
     126
     127}
     128\end{ccode}
     129\end{tabular}
     130\end{center}
     131\caption{Different implementations of a fibonacci sequence generator in C.}
     132\label{lst:fibonacci-c}
     133\end{figure}
     134
     135A good example of a problem made easier with coroutines is generators, like the fibonacci sequence. This problem comes with the challenge of decoupling how a sequence is generated and how it is used. Figure \ref{lst:fibonacci-c} shows conventional approaches to writing generators in C. All three of these approach suffer from strong coupling. The left and center 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.
     136
     137Figure \ref{lst:fibonacci-cfa} is an example of a solution to the fibonnaci problem using \CFA coroutines, where the coroutine stack holds sufficient state for the generation. This solution has the advantage of having very strong decoupling between how the sequence is generated and how it is used. Indeed, this version is as easy to use as the \code{fibonacci_state} solution, while the imlpementation is very similar to the \code{fibonacci_func} example.
     138
     139\begin{figure}
     140\begin{cfacode}
     141coroutine Fibonacci {
     142        int fn; //used for communication
     143};
     144
     145void ?{}(Fibonacci & this) { //constructor
     146        this.fn = 0;
     147}
     148
     149//main automacically called on first resume
     150void main(Fibonacci & this) with (this) {
     151        int fn1, fn2;           //retained between resumes
     152        fn  = 0;
     153        fn1 = fn;
     154        suspend(this);          //return to last resume
     155
     156        fn  = 1;
     157        fn2 = fn1;
     158        fn1 = fn;
     159        suspend(this);          //return to last resume
     160
     161        for ( ;; ) {
     162                fn  = fn1 + fn2;
    35163                fn2 = fn1;
    36                 fn1 = this.fn;
    37                 suspend(this);          // return to last resume
    38 
    39                 for ( ;; ) {
    40                         this.fn = fn1 + fn2;
    41                         fn2 = fn1;
    42                         fn1 = this.fn;
    43                         suspend(this);  // return to last resume
     164                fn1 = fn;
     165                suspend(this);  //return to last resume
     166        }
     167}
     168
     169int next(Fibonacci & this) {
     170        resume(this); //transfer to last suspend
     171        return this.fn;
     172}
     173
     174void main() { //regular program main
     175        Fibonacci f1, f2;
     176        for ( int i = 1; i <= 10; i += 1 ) {
     177                sout | next( f1 ) | next( f2 ) | endl;
     178        }
     179}
     180\end{cfacode}
     181\caption{Implementation of fibonacci using coroutines}
     182\label{lst:fibonacci-cfa}
     183\end{figure}
     184
     185Figure \ref{lst:fmt-line} shows the \code{Format} coroutine which rearranges text in order to group characters into blocks of fixed size. The 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.
     186
     187\begin{figure}
     188\begin{cfacode}[tabsize=3]
     189//format characters into blocks of 4 and groups of 5 blocks per line
     190coroutine Format {
     191        char ch;                                                                        //used for communication
     192        int g, b;                                                               //global because used in destructor
     193};
     194
     195void  ?{}(Format & fmt) {
     196        resume( fmt );                                                  //prime (start) coroutine
     197}
     198
     199void ^?{}(Format & fmt) with fmt {
     200        if ( fmt.g != 0 || fmt.b != 0 )
     201        sout | endl;
     202}
     203
     204void main(Format & fmt) with fmt {
     205        for ( ;; ) {                                                    //for as many characters
     206                for(g = 0; g < 5; g++) {                //groups of 5 blocks
     207                        for(b = 0; b < 4; fb++) {       //blocks of 4 characters
     208                                suspend();
     209                                sout | ch;                                      //print character
     210                        }
     211                        sout | "  ";                                    //print block separator
    44212                }
    45         }
    46 
    47         int next(Fibonacci & this) {
    48                 resume(this); // transfer to last suspend
    49                 return this.fn;
    50         }
    51 
    52         void main() { // regular program main
    53                 Fibonacci f1, f2;
    54                 for ( int i = 1; i <= 10; i += 1 ) {
    55                         sout | next( f1 ) | next( f2 ) | endl;
    56                 }
    57         }
    58 \end{cfacode}
     213                sout | endl;                                            //print group separator
     214        }
     215}
     216
     217void prt(Format & fmt, char ch) {
     218        fmt.ch = ch;
     219        resume(fmt);
     220}
     221
     222int main() {
     223        Format fmt;
     224        char ch;
     225        Eof: for ( ;; ) {                                               //read until end of file
     226                sin | ch;                                                       //read one character
     227                if(eof(sin)) break Eof;                 //eof ?
     228                prt(fmt, ch);                                           //push character for formatting
     229        }
     230}
     231\end{cfacode}
     232\caption{Formatting text into lines of 5 blocks of 4 characters.}
     233\label{lst:fmt-line}
     234\end{figure}
    59235
    60236\subsection{Construction}
    61 One important design challenge for coroutines and threads (shown in section \ref{threads}) is that the runtime system needs to run code after the user-constructor runs. In the case of coroutines, this challenge is simpler since there is no non-determinism from preemption or scheduling. However, the underlying challenge remains the same for coroutines and threads.
    62 
    63 The runtime system needs to create the coroutine's stack and more importantly prepare it for the first resumption. The timing of the creation is non-trivial since users both expect to have fully constructed objects once execution enters the coroutine main and to be able to resume the coroutine from the constructor. Like for regular objects, constructors can still leak coroutines before they are ready. There are several solutions to this problem but the chosen options effectively forces the design of the coroutine.
     237One important design challenge for 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. In the case of coroutines, this challenge is simpler since there is no non-determinism from preemption or scheduling. However, the underlying challenge remains the same for coroutines and threads.
     238
     239The runtime system needs to create the coroutine's stack and more importantly prepare it for the first resumption. The timing of the creation is non-trivial since users both expect to have fully constructed objects once execution enters the coroutine main and to be able to resume the coroutine from the constructor. As regular objects, constructors can leak coroutines before they are ready. There are several solutions to this problem but the chosen options effectively forces the design of the coroutine.
    64240
    65241Furthermore, \CFA faces an extra challenge as polymorphic routines create invisible thunks when casted to non-polymorphic routines and these thunks have function scope. For example, the following code, while looking benign, can run into undefined behaviour because of thunks:
     
    71247
    72248forall(otype T)
    73 void noop(T *) {}
     249void noop(T*) {}
    74250
    75251void bar() {
    76252        int a;
    77         async(noop, &a);
    78 }
    79 \end{cfacode}
     253        async(noop, &a); //start thread running noop with argument a
     254}
     255\end{cfacode}
     256
    80257The generated C code\footnote{Code trimmed down for brevity} creates a local thunk to hold type information:
    81258
     
    95272}
    96273\end{ccode}
    97 The problem in this example is a race condition between the start of the execution of \code{noop} on the other thread and the stack frame of \code{bar} being destroyed. This extra challenge limits which solutions are viable because storing the function pointer for too long only increases the chances that the race will end in undefined behavior; i.e. the stack based thunk being destroyed before it was used. This challenge is an extension of challenges that come with second-class routines. Indeed, GCC nested routines also have the limitation that the routines cannot be passed outside of the scope of the functions these were declared in. The case of coroutines and threads is simply an extension of this problem to multiple call-stacks.
     274The 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 behavior; i.e., the stack-based thunk being destroyed before it can be used. This challenge is an extension of challenges that come with second-class routines. Indeed, GCC nested routines also have the limitation that nested routine cannot be passed outside of the declaration scope. The case of coroutines and threads is simply an extension of this problem to multiple call-stacks.
    98275
    99276\subsection{Alternative: Composition}
    100 One solution to this challenge would be to use composition/containement,
    101 
    102 \begin{cfacode}
    103         struct Fibonacci {
    104               int fn; // used for communication
    105               coroutine c; //composition
    106         };
    107 
    108         void ?{}(Fibonacci & this) {
    109               this.fn = 0;
    110                 (this.c){};
    111         }
    112 \end{cfacode}
    113 There are two downsides to this approach. The first, which is relatively minor, is that the base class needs to be made aware of the main routine pointer, regardless of whether a parameter or a virtual pointer is used, this means the coroutine data must be made larger to store a value that is actually a compile time constant (address of the main routine). The second problem, which is both subtle and significant, is that now users can get the initialisation order of there coroutines wrong. Indeed, every field of a \CFA struct is constructed but in declaration order, unless users explicitly write otherwise. This semantics means that users who forget to initialize a the coroutine may resume the coroutine with an uninitilized object. For coroutines, this is unlikely to be a problem, for threads however, this is a significant problem.
     277One solution to this challenge is to use composition/containement, where coroutine fields are added to manage the coroutine.
     278
     279\begin{cfacode}
     280struct Fibonacci {
     281        int fn; //used for communication
     282        coroutine c; //composition
     283};
     284
     285void FibMain(void *) {
     286        //...
     287}
     288
     289void ?{}(Fibonacci & this) {
     290        this.fn = 0;
     291        //Call constructor to initialize coroutine
     292        (this.c){myMain};
     293}
     294\end{cfacode}
     295The downside of this approach is that users need to correctly construct the coroutine handle before using it. Like any other objects, doing so the users carefully choose construction order to prevent usage of unconstructed objects. However, in the case of coroutines, users must also pass to the coroutine information about the coroutine main, like in the previous example. This opens the door for user errors and requires extra runtime storage to pass at runtime information that can be known statically.
    114296
    115297\subsection{Alternative: Reserved keyword}
     
    117299
    118300\begin{cfacode}
    119         coroutine Fibonacci {
    120               int fn; // used for communication
    121         };
    122 \end{cfacode}
    123 This mean the compiler can solve problems by injecting code where needed. The downside of this approach is that it makes coroutine a special case in the language. Users who would want to extend coroutines or build their own for various reasons can only do so in ways offered by the language. Furthermore, implementing coroutines without language supports also displays the power of \CFA.
    124 While this is ultimately the option used for idiomatic \CFA code, coroutines and threads can both be constructed by users without using the language support. The reserved keywords are only present to improve ease of use for the common cases.
     301coroutine Fibonacci {
     302        int fn; //used for communication
     303};
     304\end{cfacode}
     305The \code{coroutine} keyword means the compiler can find and inject code where needed. The downside of this approach is that it makes coroutine a special case in the language. Users wantint to extend coroutines or build their own for various reasons can only do so in ways offered by the language. Furthermore, implementing coroutines without language supports also displays the power of the programming language used. While this is ultimately the option used for idiomatic \CFA code, coroutines and threads can still be constructed by users without using the language support. The reserved keywords are only present to improve ease of use for the common cases.
    125306
    126307\subsection{Alternative: Lamda Objects}
     
    135316Often, the canonical threading paradigm in languages is based on function pointers, pthread being one of the most well known examples. The 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. Since the custom type is simple to write in \CFA and solves several issues, added support for routine/lambda based coroutines adds very little.
    136317
    137 A variation of this would be to use an simple function pointer in the same way pthread does for threads :
     318A variation of this would be to use a simple function pointer in the same way pthread does for threads :
    138319\begin{cfacode}
    139320void foo( coroutine_t cid, void * arg ) {
     
    148329}
    149330\end{cfacode}
    150 This semantic is more common for thread interfaces than coroutines but would work equally well. As discussed in section \ref{threads}, this approach is superseeded by static approaches in terms of expressivity.
     331This semantics is more common for thread interfaces than coroutines works equally well. As discussed in section \ref{threads}, this approach is superseeded by static approaches in terms of expressivity.
    151332
    152333\subsection{Alternative: Trait-based coroutines}
     
    159340      coroutine_desc * get_coroutine(T & this);
    160341};
    161 \end{cfacode}
    162 This ensures an object is not a coroutine until \code{resume} (or \code{prime}) is called on the object. Correspondingly, any object that is passed to \code{resume} is a coroutine since it must satisfy the \code{is_coroutine} trait to compile. The advantage of this approach is that users can easily create different types of coroutines, for example, changing the memory foot print of a coroutine is trivial when implementing the \code{get_coroutine} routine. The \CFA keyword \code{coroutine} only has the effect of implementing the getter and forward declarations required for users to only have to implement the main routine.
     342
     343forall( dtype T | is_coroutine(T) ) void suspend(T &);
     344forall( dtype T | is_coroutine(T) ) void resume (T &);
     345\end{cfacode}
     346This ensures an object is not a coroutine until \code{resume} is called on the object. Correspondingly, any object that is passed to \code{resume} is a coroutine since it must satisfy the \code{is_coroutine} trait to compile. The 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. The \CFA keyword \code{coroutine} only has the effect of implementing the getter and forward declarations required for users to only have to implement the main routine.
    163347
    164348\begin{center}
     
    186370\end{center}
    187371
    188 The combination of these two approaches allows users new to concurrency to have a easy and concise method while more advanced users can expose themselves to otherwise hidden pitfalls at the benefit of tighter control on memory layout and initialization.
     372The combination of these two approaches allows users new to coroutinning and concurrency to have an easy and concise specification, while more advanced users have tighter control on memory layout and initialization.
    189373
    190374\section{Thread Interface}\label{threads}
     
    192376
    193377\begin{cfacode}
    194         thread foo {};
     378thread foo {};
    195379\end{cfacode}
    196380
     
    205389\end{cfacode}
    206390
    207 Obviously, for this thread implementation to be usefull it must run some user code. Several other threading interfaces use a function-pointer representation as the interface of threads (for example \Csharp~\cite{Csharp} and Scala~\cite{Scala}). However, this proposal considers that statically tying a \code{main} routine to a thread superseeds this approach. Since the \code{main} routine is already a special routine in \CFA (where the program begins), it is possible naturally extend the semantics using overloading to declare mains for different threads (the normal main being the main of the initial thread). As such the \code{main} routine of a thread can be defined as
    208 \begin{cfacode}
    209         thread foo {};
    210 
    211         void main(foo & this) {
    212                 sout | "Hello World!" | endl;
    213         }
    214 \end{cfacode}
    215 
    216 In this example, threads of type \code{foo} start execution in the \code{void main(foo*)} routine which prints \code{"Hello World!"}. While this proposoal encourages this approach to enforce strongly-typed programming, users may prefer to use the routine based thread semantics for the sake of simplicity. With these semantics it is trivial to write a thread type that takes a function pointer as parameter and executes it on its stack asynchronously
    217 \begin{cfacode}
    218         typedef void (*voidFunc)(void);
    219 
    220         thread FuncRunner {
    221                 voidFunc func;
    222         };
    223 
    224         //ctor
    225         void ?{}(FuncRunner & this, voidFunc inFunc) {
    226                 this.func = inFunc;
    227         }
    228 
    229         //main
    230         void main(FuncRunner & this) {
    231                 this.func();
    232         }
    233 \end{cfacode}
    234 
    235 An advantage of the overloading approach to main is to clearly highlight where and what memory is required to pass parameters and return values to/from a thread.
    236 
    237 Of course for threads to be useful, it must be possible to start and stop threads and wait for them to complete execution. While using an \acrshort{api} such as \code{fork} and \code{join} is relatively common in the literature, such an interface is unnecessary. Indeed, the simplest approach is to use \acrshort{raii} principles and have threads \code{fork} once the constructor has completed and \code{join} before the destructor runs.
     391Obviously, for this thread implementation to be usefull it must run some user code. Several other threading interfaces use a function-pointer representation as the interface of threads (for example \Csharp~\cite{Csharp} and Scala~\cite{Scala}). However, this proposal considers that statically tying a \code{main} routine to a thread superseeds this approach. Since the \code{main} routine is already a special routine in \CFA (where the program begins), it is a natural extension of the semantics using overloading to declare mains for different threads (the normal main being the main of the initial thread). As such the \code{main} routine of a thread can be defined as
     392\begin{cfacode}
     393thread foo {};
     394
     395void main(foo & this) {
     396        sout | "Hello World!" | endl;
     397}
     398\end{cfacode}
     399
     400In this example, threads of type \code{foo} start execution in the \code{void main(foo &)} routine, which prints \code{"Hello World!"}. While this thesis encourages this approach to enforce strongly-typed programming, users may prefer to use the routine-based thread semantics for the sake of simplicity. With 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.
     401\begin{cfacode}
     402typedef void (*voidFunc)(int);
     403
     404thread FuncRunner {
     405        voidFunc func;
     406        int arg;
     407};
     408
     409void ?{}(FuncRunner & this, voidFunc inFunc, int arg) {
     410        this.func = inFunc;
     411        this.arg  = arg;
     412}
     413
     414void main(FuncRunner & this) {
     415        //thread starts here and runs the function
     416        this.func( this.arg );
     417}
     418\end{cfacode}
     419
     420A 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 \acrshort{api}.
     421
     422Of course for threads to be useful, it must be possible to start and stop threads and wait for them to complete execution. While using an \acrshort{api} such as \code{fork} and \code{join} is relatively common in the literature, such an interface is unnecessary. Indeed, the simplest approach is to use \acrshort{raii} principles and have threads \code{fork} after the constructor has completed and \code{join} before the destructor runs.
    238423\begin{cfacode}
    239424thread World;
     
    254439\end{cfacode}
    255440
    256 This semantic has several advantages over explicit semantics typesafety is guaranteed, a thread is always started and stopped exaclty once and users cannot make any progamming errors. Another advantage of this semantic is that it naturally scale to multiple threads meaning basic synchronisation is very simple
     441This semantic has several advantages over explicit semantics: a thread is always started and stopped exaclty once, users cannot make any progamming errors, and it naturally scales to multiple threads meaning basic synchronisation is very simple.
    257442
    258443\begin{cfacode}
     
    276461\end{cfacode}
    277462
    278 However, one of the apparent drawbacks of this system is that threads now always form a lattice, that is they are always destroyed in opposite order of construction because of block structure. However, storage allocation is not limited to blocks; dynamic allocation can create threads that outlive the scope in which the thread is created much like dynamically allocating memory lets objects outlive the scope in which they are created
     463However, one of the drawbacks of this approach is that threads now always form a lattice, that is they are always destroyed in the opposite order of construction because of block structure. This 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.
    279464
    280465\begin{cfacode}
     
    283468};
    284469
    285 //main
    286470void main(MyThread & this) {
    287471        //...
     
    291475        MyThread * long_lived;
    292476        {
     477                //Start a thread at the beginning of the scope
    293478                MyThread short_lived;
    294                 //Start a thread at the beginning of the scope
    295 
    296                 DoStuff();
    297479
    298480                //create another thread that will outlive the thread in this scope
    299481                long_lived = new MyThread;
    300482
     483                DoStuff();
     484
    301485                //Wait for the thread short_lived to finish
    302486        }
    303487        DoMoreStuff();
    304488
    305         //Now wait for the short_lived to finish
     489        //Now wait for the long_lived to finish
    306490        delete long_lived;
    307491}
  • doc/proposals/concurrency/text/cforall.tex

    r78315272 r3f7e12cb  
    11% ======================================================================
    22% ======================================================================
    3 \chapter{Cforall crash course}
     3\chapter{Cforall Overview}
    44% ======================================================================
    55% ======================================================================
    66
    7 As mentionned in the introduction, the document presents the design for the concurrency features in \CFA. Since it is a new language here is a quick review of the language specifically tailored to the features needed to support concurrency.
     7The following is a quick introduction to the \CFA language, specifically tailored to the features needed to support concurrency.
    88
    9 \CFA is a extension of ISO C and therefore supports much of the same paradigms as C. It is a non-object oriented system level language, meaning it has very most of the major abstractions have either no runtime cost or can be opt-out easily. Like C, the basics of \CFA revolve around structures and routines, which are thin abstractions over assembly. The vast majority of the code produced by a \CFA compiler respects memory-layouts and calling-conventions laid out by C. However, while \CFA is not an object-oriented language according to a strict definition. It does have some notion of objects, most importantly construction and destruction of objects. Most of the following pieces of code can be found as is on the \CFA website : \cite{www-cfa}
     9\CFA is a extension of ISO-C and therefore supports all of the same paradigms as C. It is a non-object oriented system language, meaning most of the major abstractions have either no runtime overhead or can be opt-out easily. Like C, the basics of \CFA revolve around structures and routines, which are thin abstractions over machine code. The vast majority of the code produced by the \CFA translator respects memory-layouts and calling-conventions laid out by C. Interestingly, while \CFA is not an object-oriented language, lacking the concept of a receiver (e.g., 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
     10values''\cite[3.15]{C11}}, most importantly construction and destruction of objects. Most of the following code examples can be found on the \CFA website \cite{www-cfa}
    1011
    1112\section{References}
    1213
    13 Like \CC, \CFA introduces references as an alternative to pointers. In regards to concurrency, the semantics difference between pointers and references aren't particularly relevant but since this document uses mostly references here is a quick overview of the semantics :
     14Like \CC, \CFA introduces rebindable references providing multiple dereferecing as an alternative to pointers. In 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:
    1415\begin{cfacode}
    1516int x, *p1 = &x, **p2 = &p1, ***p3 = &p2,
    16 &r1 = x,    &&r2 = r1,   &&&r3 = r2;
    17 ***p3 = 3;                                      // change x
    18 r3 = 3;                                         // change x, ***r3
    19 **p3 = ...;                                     // change p1
    20 &r3 = ...;                                      // change r1, (&*)**r3
    21 *p3 = ...;                                      // change p2
    22 &&r3 = ...;                                     // change r2, (&(&*)*)*r3
    23 &&&r3 = p3;                                     // change r3 to p3, (&(&(&*)*)*)r3
    24 int y, z, & ar[3] = { x, y, z };                // initialize array of references
    25 &ar[1] = &z;                                    // change reference array element
    26 typeof( ar[1] ) p;                              // is int, i.e., the type of referenced object
    27 typeof( &ar[1] ) q;                             // is int &, i.e., the type of reference
    28 sizeof( ar[1] ) == sizeof( int );               // is true, i.e., the size of referenced object
    29 sizeof( &ar[1] ) == sizeof( int *);             // is true, i.e., the size of a reference
     17        &r1 = x,    &&r2 = r1,   &&&r3 = r2;
     18***p3 = 3;                                                      //change x
     19r3    = 3;                                                      //change x, ***r3
     20**p3  = ...;                                            //change p1
     21*p3   = ...;                                            //change p2
     22int y, z, & ar[3] = {x, y, z};          //initialize array of references
     23typeof( ar[1]) p;                                       //is int, i.e., the type of referenced object
     24typeof(&ar[1]) q;                                       //is int &, i.e., the type of reference
     25sizeof( ar[1]) == sizeof(int);          //is true, i.e., the size of referenced object
     26sizeof(&ar[1]) == sizeof(int *);        //is true, i.e., the size of a reference
    3027\end{cfacode}
    31 The important thing to take away from this code snippet is that references offer a handle to an object much like pointers but which is automatically derefferenced when convinient.
     28The important take away from this code example is that references offer a handle to an object, much like pointers, but which is automatically dereferenced for convinience.
    3229
    3330\section{Overloading}
    3431
    35 Another important feature \CFA has in common with \CC is function overloading :
     32Another 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. As well, \CFA uses the return type as part of the selection criteria, as in Ada\cite{Ada}. For routines with multiple parameters and returns, the selection is complex.
    3633\begin{cfacode}
    37 // selection based on type and number of parameters
    38 void f( void );                                 // (1)
    39 void f( char );                                 // (2)
    40 void f( int, double );                          // (3)
    41 f();                                            // select (1)
    42 f( 'a' );                                       // select (2)
    43 f( 3, 5.2 );                                    // select (3)
     34//selection based on type and number of parameters
     35void f(void);                   //(1)
     36void f(char);                   //(2)
     37void f(int, double);    //(3)
     38f();                                    //select (1)
     39f('a');                                 //select (2)
     40f(3, 5.2);                              //select (3)
    4441
    45 // selection based on  type and number of returns
    46 char f( int );                                  // (1)
    47 double f( int );                                // (2)
    48 [ int, double ] f( int );                       // (3)
    49 char c = f( 3 );                                // select (1)
    50 double d = f( 4 );                              // select (2)
    51 [ int, double ] t = f( 5 );                     // select (3)
     42//selection based on  type and number of returns
     43char   f(int);                  //(1)
     44double f(int);                  //(2)
     45char   c = f(3);                //select (1)
     46double d = f(4);                //select (2)
    5247\end{cfacode}
    53 This feature is particularly important for concurrency since the runtime system relies on creating different types do represent concurrency objects. Therefore, overloading is necessary to prevent the need for long prefixes and other naming conventions that prevent clashes. As seen in chapter \ref{basics}, the main is an example of routine that benefits from overloading when concurrency in introduced.
     48This feature is particularly important for concurrency since the runtime system relies on creating different types to represent concurrency objects. Therefore, overloading is necessary to prevent the need for long prefixes and other naming conventions that prevent name clashes. As seen in chapter \ref{basics}, routine \code{main} is an example that benefits from overloading.
    5449
    5550\section{Operators}
    56 Overloading also extends to operators. The 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 would be, like so :
     51Overloading also extends to operators. The 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 occur, e.g.:
    5752\begin{cfacode}
    58 int ++?( int op );                              // unary prefix increment
    59 int ?++( int op );                              // unary postfix increment
    60 int ?+?( int op1, int op2 );                    // binary plus
    61 int ?<=?( int op1, int op2 );                   // binary less than
    62 int ?=?( int & op1, int op2 );                  // binary assignment
    63 int ?+=?( int & op1, int op2 );                 // binary plus-assignment
     53int ++? (int op);                       //unary prefix increment
     54int ?++ (int op);                       //unary postfix increment
     55int ?+? (int op1, int op2);             //binary plus
     56int ?<=?(int op1, int op2);             //binary less than
     57int ?=? (int & op1, int op2);           //binary assignment
     58int ?+=?(int & op1, int op2);           //binary plus-assignment
    6459
    65 struct S { int i, j; };
    66 S ?+?( S op1, S op2 ) {                         // add two structures
    67         return (S){ op1.i + op2.i, op1.j + op2.j };
     60struct S {int i, j;};
     61S ?+?(S op1, S op2) {                           //add two structures
     62        return (S){op1.i + op2.i, op1.j + op2.j};
    6863}
    69 S s1 = { 1, 2 }, s2 = { 2, 3 }, s3;
    70 s3 = s1 + s2;                                   // compute sum: s3 == { 2, 5 }
     64S s1 = {1, 2}, s2 = {2, 3}, s3;
     65s3 = s1 + s2;                                           //compute sum: s3 == {2, 5}
    7166\end{cfacode}
    72 
    73 Since concurrency does not use operator overloading, this feature is more important as an introduction for the syntax of constructors.
     67While concurrency does not use operator overloading directly, this feature is more important as an introduction for the syntax of constructors.
    7468
    7569\section{Constructors/Destructors}
    76 \CFA uses the following syntax for constructors and destructors :
     70Object life-time is often a challenge in concurrency. \CFA uses the approach of giving concurrent meaning to object life-time as a mean of synchronization and/or mutual exclusion. Since \CFA relies heavily on the life time of objects, constructors and destructors are a core feature required for concurrency and parallelism. \CFA uses the following syntax for constructors and destructors :
    7771\begin{cfacode}
    7872struct S {
     
    8074        int * ia;
    8175};
    82 void ?{}( S & s, int asize ) with s {           // constructor operator
    83         size = asize;                           // initialize fields
    84         ia = calloc( size, sizeof( S ) );
     76void ?{}(S & s, int asize) {    //constructor operator
     77        s.size = asize;                         //initialize fields
     78        s.ia = calloc(size, sizeof(S));
    8579}
    86 void ^?{}( S & s ) with s {                     // destructor operator
    87         free( ia );                             // de-initialization fields
     80void ^?{}(S & s) {                              //destructor operator
     81        free(ia);                                       //de-initialization fields
    8882}
    8983int main() {
    90         S x = { 10 }, y = { 100 };              // implict calls: ?{}( x, 10 ), ?{}( y, 100 )
    91         ...                                     // use x and y
    92         ^x{};  ^y{};                            // explicit calls to de-initialize
    93         x{ 20 };  y{ 200 };                     // explicit calls to reinitialize
    94         ...                                     // reuse x and y
    95 }                                               // implict calls: ^?{}( y ), ^?{}( x )
     84        S x = {10}, y = {100};          //implict calls: ?{}(x, 10), ?{}(y, 100)
     85        ...                                                     //use x and y
     86        ^x{};  ^y{};                            //explicit calls to de-initialize
     87        x{20};  y{200};                         //explicit calls to reinitialize
     88        ...                                                     //reuse x and y
     89}                                                               //implict calls: ^?{}(y), ^?{}(x)
    9690\end{cfacode}
    97 The language guarantees that every object and all their fields are constructed. Like \CC construction is automatically done on declaration and destruction done when the declared variables reach the end of its scope.
     91The language guarantees that every object and all their fields are constructed. Like \CC, construction of an object is automatically done on allocation and destruction of the object is done on deallocation. Allocation and deallocation can occur on the stack or on the heap.
     92\begin{cfacode}
     93{
     94        struct S s = {10};      //allocation, call constructor
     95        ...
     96}                                               //deallocation, call destructor
     97struct S * s = new();   //allocation, call constructor
     98...
     99delete(s);                              //deallocation, call destructor
     100\end{cfacode}
     101Note 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.
    98102
    99 For more information see \cite{cforall-ug,rob-thesis,www-cfa}.
     103\section{Parametric Polymorphism}
     104Routines in \CFA can also be reused for multiple types. This capability is done using the \code{forall} clause which gives \CFA its name. \code{forall} clauses allow separately compiled routines to support generic usage over multiple types. For example, the following sum function works for any type that supports construction from 0 and addition :
     105\begin{cfacode}
     106//constraint type, 0 and +
     107forall(otype T | { void ?{}(T *, zero_t); T ?+?(T, T); })
     108T sum(T a[ ], size_t size) {
     109        T total = 0;                            //construct T from 0
     110        for(size_t i = 0; i < size; i++)
     111                total = total + a[i];   //select appropriate +
     112        return total;
     113}
     114
     115S sa[5];
     116int i = sum(sa, 5);                             //use S's 0 construction and +
     117\end{cfacode}
     118
     119Since writing constraints on types can become cumbersome for more constrained functions, \CFA also has the concept of traits. Traits are named collection of constraints that can be used both instead and in addition to regular constraints:
     120\begin{cfacode}
     121trait sumable( otype T ) {
     122        void ?{}(T *, zero_t);          //constructor from 0 literal
     123        T ?+?(T, T);                            //assortment of additions
     124        T ?+=?(T *, T);
     125        T ++?(T *);
     126        T ?++(T *);
     127};
     128forall( otype T | sumable(T) )  //use trait
     129T sum(T a[], size_t size);
     130\end{cfacode}
     131
     132\section{with Clause/Statement}
     133Since \CFA lacks the concept of a receiver, certain functions end-up needing to repeat variable names often. To remove this inconvenience, \CFA provides the \code{with} statement, which opens an aggregate scope making its fields directly accessible (like Pascal).
     134\begin{cfacode}
     135struct S { int i, j; };
     136int mem(S & this) with (this)           //with clause
     137        i = 1;                                          //this->i
     138        j = 2;                                          //this->j
     139}
     140int foo() {
     141        struct S1 { ... } s1;
     142        struct S2 { ... } s2;
     143        with (s1)                                       //with statement
     144        {
     145                //access fields of s1
     146                //without qualification
     147                with (s2)                                       //nesting
     148                {
     149                        //access fields of s1 and s2
     150                        //without qualification
     151                }
     152        }
     153        with (s1, s2)                           //scopes open in parallel
     154        {
     155                //access fields of s1 and s2
     156                //without qualification
     157        }
     158}
     159\end{cfacode}
     160
     161For more information on \CFA see \cite{cforall-ug,rob-thesis,www-cfa}.
  • doc/proposals/concurrency/text/concurrency.tex

    r78315272 r3f7e12cb  
    44% ======================================================================
    55% ======================================================================
    6 Several tool can be used to solve concurrency challenges. Since 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}). In these paradigms, interaction among concurrent objects relies on message passing~\cite{Thoth,Harmony,V-Kernel} or other paradigms that closely relate to networking concepts (channels\cit for example). However, 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 call). This distinction in turn means that, in order to be effective, programmers need to learn two sets of designs patterns. While this distinction can be hidden away in library code, effective use of the librairy still has to take both paradigms into account.
     6Several tool can be used to solve concurrency challenges. Since 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}). In 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). However, 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 call). This distinction in turn means that, in order to be effective, programmers need to learn two sets of designs patterns. While this distinction can be hidden away in library code, effective use of the librairy still has to take both paradigms into account.
    77
    88Approaches 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. At the lowest level, concurrent paradigms are implemented as atomic operations and locks. Many such mechanisms have been proposed, including semaphores~\cite{Dijkstra68b} and path expressions~\cite{Campbell74}. However, for productivity reasons it is desireable to have a higher-level construct be the core concurrency paradigm~\cite{HPP:Study}.
    99
    10 An approach that is worth mentionning because it is gaining in popularity is transactionnal memory~\cite{Dice10}[Check citation]. While this approach is even pursued by system languages like \CC\cit, the performance and feature set is currently too restrictive to be the main concurrency paradigm for general purpose language, which is why it was rejected as the core paradigm for concurrency in \CFA.
    11 
    12 One of the most natural, elegant, and efficient mechanisms for synchronization and communication, especially for shared memory systems, is the \emph{monitor}. Monitors were first proposed by Brinch Hansen~\cite{Hansen73} and later described and extended by C.A.R.~Hoare~\cite{Hoare74}. Many 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. In 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. For these reasons, this project proposes monitors as the core concurrency-construct.
     10An approach that is worth mentioning because it is gaining in popularity is transactionnal memory~\cite{Dice10}[Check citation]. While this approach is even pursued by system languages like \CC\cit, the performance and feature set is currently too restrictive to be the main concurrency paradigm for systems language, which is why it was rejected as the core paradigm for concurrency in \CFA.
     11
     12One of the most natural, elegant, and efficient mechanisms for synchronization and communication, especially for shared-memory systems, is the \emph{monitor}. Monitors were first proposed by Brinch Hansen~\cite{Hansen73} and later described and extended by C.A.R.~Hoare~\cite{Hoare74}. Many 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. In 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. For these reasons, this project proposes monitors as the core concurrency-construct.
    1313
    1414\section{Basics}
    15 Non-determinism requires concurrent systems to offer support for mutual-exclusion and synchronisation. Mutual-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. On the other hand, synchronization enforces relative ordering of execution and synchronization tools numerous mechanisms to establish timing relationships among threads.
     15Non-determinism requires concurrent systems to offer support for mutual-exclusion and synchronisation. Mutual-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. On the other hand, synchronization enforces relative ordering of execution and synchronization tools provide numerous mechanisms to establish timing relationships among threads.
    1616
    1717\subsection{Mutual-Exclusion}
    18 As mentionned above, mutual-exclusion is the guarantee that only a fix number of threads can enter a critical section at once. However, many solution exists for mutual exclusion which vary in terms of performance, flexibility and ease of use. Methods range from low-level locks, which are fast and flexible but require significant attention to be correct, to  higher-level mutual-exclusion methods, which sacrifice some performance in order to improve ease of use. Ease 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. For example, the \CC \code{std::atomic<T>} which offer an easy way to express mutual-exclusion on a restricted set of operations (.e.g: reading/writing large types atomically). Another challenge with low-level locks is composability. Locks are not composable because it takes careful organising for multiple locks to be used while preventing deadlocks. Easing composability is another feature higher-level mutual-exclusion mechanisms often offer.
     18As mentionned above, mutual-exclusion is the guarantee that only a fix number of threads can enter a critical section at once. However, many solutions exist for mutual exclusion, which vary in terms of performance, flexibility and ease of use. Methods range from low-level locks, which are fast and flexible but require significant attention to be correct, to  higher-level mutual-exclusion methods, which sacrifice some performance in order to improve ease of use. Ease 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. For 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). Another challenge with low-level locks is composability. Locks have restricted composability because it takes careful organising for multiple locks to be used while preventing deadlocks. Easing composability is another feature higher-level mutual-exclusion mechanisms often offer.
    1919
    2020\subsection{Synchronization}
    21 As for mutual-exclusion, low level synchronisation primitive often offer good performance and good flexibility at the cost of ease of use. Again, higher-level mechanism often simplify usage by adding better coupling between synchronization and data, .eg., message passing, or offering simple solution to otherwise involved challenges. An example of this is barging. As mentionned above synchronization can be expressed as guaranteeing that event \textit{X} always happens before \textit{Y}. Most of the time synchronisation happens around a critical section, where threads most acquire said critical section in a certain order. However, it may also be desired to be able to guarantee that event \textit{Z} does not occur between \textit{X} and \textit{Y}. This is called barging, where event \textit{X} tries to effect event \textit{Y} but anoter thread races to grab the critical section and emits \textit{Z} before \textit{Y}. Preventing or detecting barging is an involved challenge with low-level locks, which can be made much easier by higher-level constructs.
     21As for mutual-exclusion, low-level synchronisation primitives often offer good performance and good flexibility at the cost of ease of use. Again, higher-level mechanism often simplify usage by adding better coupling between synchronization and data, e.g.: message passing, or offering simpler solution to otherwise involved challenges. As mentioned above, synchronization can be expressed as guaranteeing that event \textit{X} always happens before \textit{Y}. Most of the time, synchronisation happens within a critical section, where threads must acquire mutual-exclusion in a certain order. However, it may also be desirable to guarantee that event \textit{Z} does not occur between \textit{X} and \textit{Y}. Not satisfying this property called barging. For 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}. The classic exmaple is the thread that finishes using a ressource and unblocks a thread waiting to use the resource, but the unblocked thread must compete again to acquire the resource. Preventing or detecting barging is an involved challenge with low-level locks, which can be made much easier by higher-level constructs. This challenge is often split into two different methods, barging avoidance and barging prevention. Algorithms that use status flags and other flag variables to detect barging threads are said to be using barging avoidance while algorithms that baton-passing locks between threads instead of releasing the locks are said to be using barging prevention.
    2222
    2323% ======================================================================
     
    2828A monitor is a set of routines that ensure mutual exclusion when accessing shared state. This concept is generally associated with Object-Oriented Languages like Java~\cite{Java} or \uC~\cite{uC++book} but does not strictly require OO semantics. The only requirements is the ability to declare a handle to a shared object and a set of routines that act on it :
    2929\begin{cfacode}
    30         typedef /*some monitor type*/ monitor;
    31         int f(monitor & m);
    32 
    33         int main() {
    34                 monitor m;  //Handle m
    35                 f(m);       //Routine using handle
    36         }
     30typedef /*some monitor type*/ monitor;
     31int f(monitor & m);
     32
     33int main() {
     34        monitor m;  //Handle m
     35        f(m);       //Routine using handle
     36}
    3737\end{cfacode}
    3838
     
    4747
    4848\begin{cfacode}
    49         monitor counter_t { /*...see section $\ref{data}$...*/ };
    50 
    51         void ?{}(counter_t & nomutex this); //constructor
    52         size_t ++?(counter_t & mutex this); //increment
    53 
    54         //need for mutex is platform dependent
    55         void ?{}(size_t * this, counter_t & mutex cnt); //conversion
    56 \end{cfacode}
    57 
    58 Here, the constructor(\code{?\{\}}) uses the \code{nomutex} keyword to signify that it does not acquire the monitor mutual-exclusion when constructing. This semantics is because an object not yet constructed should never be shared and therefore does not require mutual exclusion. The prefix increment operator uses \code{mutex} to protect the incrementing process from race conditions. Finally, there is a conversion operator from \code{counter_t} to \code{size_t}. This conversion may or may not require the \code{mutex} keyword depending on whether or not reading an \code{size_t} is an atomic operation.
    59 
    60 Having both \code{mutex} and \code{nomutex} keywords is redundant based on the meaning of a routine having neither of these keywords. For example, given a routine without qualifiers \code{void foo(counter_t & this)}, then it is reasonable that it should default to the safest option \code{mutex}, whereas assuming \code{nomutex} is unsafe and may cause subtle errors. In fact, \code{nomutex} is the "normal" parameter behaviour, with the \code{nomutex} keyword effectively stating explicitly that "this routine is not special". Another alternative is to make having exactly one of these keywords mandatory, which would provide the same semantics but without the ambiguity of supporting routines neither keyword. Mandatory keywords would also have the added benefit of being self-documented but at the cost of extra typing. While there are several benefits to mandatory keywords, they do bring a few challenges. Mandatory keywords in \CFA would imply that the compiler must know without a doubt wheter or not a parameter is a monitor or not. Since \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. For this reason, \CFA only has the \code{mutex} keyword.
    61 
    62 
    63 The next semantic decision is to establish when \code{mutex} may be used as a type qualifier. Consider the following declarations:
    64 \begin{cfacode}
    65 int f1(monitor & mutex m);
    66 int f2(const monitor & mutex m);
    67 int f3(monitor ** mutex m);
    68 int f4(monitor * mutex m []);
    69 int f5(graph(monitor*) & mutex m);
    70 \end{cfacode}
    71 The problem is to indentify which object(s) should be acquired. Furthermore, each object needs to be acquired only once. In 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. Adding indirections (\code{f3}) still allows the compiler and programmer to indentify which object is acquired. However, adding in arrays (\code{f4}) makes it much harder. Array lengths are not necessarily known in C, and even then making sure objects are only acquired once becomes none-trivial. This can be extended to absurd limits like \code{f5}, which uses a graph of monitors. To keep everyone as sane as possible~\cite{Chicken}, this projects imposes the requirement that a routine may only acquire one monitor per parameter and it must be the type of the parameter with one level of indirection (ignoring potential qualifiers). Also note that while routine \code{f3} can be supported, meaning that monitor \code{**m} is be acquired, passing an array to this routine would be type safe and yet result in undefined behavior because only the first element of the array is acquired. This is specially true for non-copyable objects like monitors, where an array of pointers is simplest way to express a group of monitors. However, this ambiguity is part of the C type-system with respects to arrays. For this reason, \code{mutex} is disallowed in the context where arrays may be passed:
    72 
    73 \begin{cfacode}
    74 int f1(monitor & mutex m);   //Okay : recommanded case
    75 int f2(monitor * mutex m);   //Okay : could be an array but probably not
    76 int f3(monitor mutex m []);  //Not Okay : Array of unkown length
    77 int f4(monitor ** mutex m);  //Not Okay : Could be an array
    78 int f5(monitor * mutex m []); //Not Okay : Array of unkown length
    79 \end{cfacode}
    80 
    81 Unlike object-oriented monitors, where calling a mutex member \emph{implicitly} acquires mutual-exclusion, \CFA uses an explicit mechanism to acquire mutual-exclusion. A consequence of this approach is that it extends naturally to multi-monitor calls.
    82 \begin{cfacode}
    83 int f(MonitorA & mutex a, MonitorB & mutex b);
    84 
    85 MonitorA a;
    86 MonitorB b;
    87 f(a,b);
    88 \end{cfacode}
    89 The capacity to acquire multiple locks before entering a critical section is called \emph{\gls{group-acquire}}. In practice, writing multi-locking routines that do not lead to deadlocks is tricky. Having language support for such a feature is therefore a significant asset for \CFA. In the case presented above, \CFA guarantees that the order of aquisition is consistent across calls to routines using the same monitors as arguments. However, since \CFA monitors use multi-acquisition locks, users can effectively force the acquiring order. For example, notice which routines use \code{mutex}/\code{nomutex} and how this affects aquiring order:
    90 \begin{cfacode}
    91         void foo(A & mutex a, B & mutex b) { //acquire a & b
    92                 ...
    93         }
    94 
    95         void bar(A & mutex a, B & /*nomutex*/ b) { //acquire a
    96                 ... foo(a, b); ... //acquire b
    97         }
    98 
    99         void baz(A & /*nomutex*/ a, B & mutex b) { //acquire b
    100                 ... foo(a, b); ... //acquire a
    101         }
    102 \end{cfacode}
    103 The multi-acquisition monitor lock allows a monitor lock to be acquired by both \code{bar} or \code{baz} and acquired again in \code{foo}. In the calls to \code{bar} and \code{baz} the monitors are acquired in opposite order.
    104 
    105 However, such use leads the lock acquiring order problem. In 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}. This subtle mistake means that calling these routines concurrently may lead to deadlock and is therefore undefined behavior. As shown on several occasion\cit, solving this problem requires:
    106 \begin{enumerate}
    107         \item Dynamically tracking of the monitor-call order.
    108         \item Implement rollback semantics.
    109 \end{enumerate}
    110 While the first requirement is already a significant constraint on the system, implementing a general rollback semantics in a C-like language is prohibitively complex \cit. In \CFA, users simply need to be carefull when acquiring multiple monitors at the same time.
    111 
    112 Finally, for convenience, monitors support multiple acquiring, that is acquiring a monitor while already holding it does not cause a deadlock. It simply increments an internal counter which is then used to release the monitor after the number of acquires and releases match up. This is particularly usefull when monitor routines use other monitor routines as helpers or for recursions. For example:
    113 \begin{cfacode}
    114 monitor bank {
    115         int money;
    116         log_t usr_log;
    117 };
    118 
    119 void deposit( bank & mutex b, int deposit ) {
    120         b.money += deposit;
    121         b.usr_log | "Adding" | deposit | endl;
    122 }
    123 
    124 void transfer( bank & mutex mybank, bank & mutex yourbank, int me2you) {
    125         deposit( mybank, -me2you );
    126         deposit( yourbank, me2you );
    127 }
    128 \end{cfacode}
    129 
    130 % ======================================================================
    131 % ======================================================================
    132 \subsection{Data semantics} \label{data}
    133 % ======================================================================
    134 % ======================================================================
    135 Once the call semantics are established, the next step is to establish data semantics. Indeed, until now a monitor is used simply as a generic handle but in most cases monitors contain shared data. This data should be intrinsic to the monitor declaration to prevent any accidental use of data without its appropriate protection. For example, here is a complete version of the counter showed in section \ref{call}:
    136 \begin{cfacode}
    137 monitor counter_t {
    138         int value;
    139 };
    140 
    141 void ?{}(counter_t & this) {
    142         this.cnt = 0;
    143 }
    144 
    145 int ?++(counter_t & mutex this) {
    146         return ++this.value;
    147 }
    148 
    149 //need for mutex is platform dependent here
    150 void ?{}(int * this, counter_t & mutex cnt) {
    151         *this = (int)cnt;
    152 }
    153 \end{cfacode}
    154 
     49monitor counter_t { /*...see section $\ref{data}$...*/ };
     50
     51void ?{}(counter_t & nomutex this); //constructor
     52size_t ++?(counter_t & mutex this); //increment
     53
     54//need for mutex is platform dependent
     55void ?{}(size_t * this, counter_t & mutex cnt); //conversion
     56\end{cfacode}
    15557This counter is used as follows:
    15658\begin{center}
     
    16971\end{tabular}
    17072\end{center}
    171 Notice how the counter is used without any explicit synchronisation and yet supports thread-safe semantics for both reading and writting.
    172 
    173 % ======================================================================
    174 % ======================================================================
    175 \subsection{Implementation Details: Interaction with polymorphism}
    176 % ======================================================================
    177 % ======================================================================
    178 Depending on the choice of semantics for when monitor locks are acquired, interaction between monitors and \CFA's concept of polymorphism can be complex to support. However, it is shown that entry-point locking solves most of the issues.
    179 
    180 First of all, interaction between \code{otype} polymorphism and monitors is impossible since monitors do not support copying. Therefore, the main question is how to support \code{dtype} polymorphism. Since a monitor's main purpose is to ensure mutual exclusion when accessing shared data, this implies that mutual exclusion is only required for routines that do in fact access shared data. However, since \code{dtype} polymorphism always handles incomplete types (by definition), no \code{dtype} polymorphic routine can access shared data since the data requires knowledge about the type. Therefore, the only concern when combining \code{dtype} polymorphism and monitors is to protect access to routines.
    181 
    182 Before looking into complex control-flow, it is important to present the difference between the two acquiring options : callsite 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. For example:
     73Notice how the counter is used without any explicit synchronisation and yet supports thread-safe semantics for both reading and writting, which is similar in usage to \CC \code{atomic} template.
     74
     75Here, the constructor(\code{?\{\}}) uses the \code{nomutex} keyword to signify that it does not acquire the monitor mutual-exclusion when constructing. This semantics is because an object not yet con\-structed should never be shared and therefore does not require mutual exclusion. The prefix increment operator uses \code{mutex} to protect the incrementing process from race conditions. Finally, there is a conversion operator from \code{counter_t} to \code{size_t}. This conversion may or may not require the \code{mutex} keyword depending on whether or not reading a \code{size_t} is an atomic operation.
     76
     77For maximum usability, monitors use \gls{multi-acq} semantics, which means a single thread can acquire the same monitor multiple times without deadlock. For example, figure \ref{fig:search} uses recursion and \gls{multi-acq} to print values inside a binary tree.
     78\begin{figure}
     79\label{fig:search}
     80\begin{cfacode}
     81monitor printer { ... };
     82struct tree {
     83        tree * left, right;
     84        char * value;
     85};
     86void print(printer & mutex p, char * v);
     87
     88void print(printer & mutex p, tree * t) {
     89        print(p, t->value);
     90        print(p, t->left );
     91        print(p, t->right);
     92}
     93\end{cfacode}
     94\caption{Recursive printing algorithm using \gls{multi-acq}.}
     95\end{figure}
     96
     97Having both \code{mutex} and \code{nomutex} keywords is redundant based on the meaning of a routine having neither of these keywords. For example, given a routine without qualifiers \code{void foo(counter_t & this)}, then it is reasonable that it should default to the safest option \code{mutex}, whereas assuming \code{nomutex} is unsafe and may cause subtle errors. In fact, \code{nomutex} is the ``normal'' parameter behaviour, with the \code{nomutex} keyword effectively stating explicitly that ``this routine is not special''. Another alternative is making exactly one of these keywords mandatory, which provides the same semantics but without the ambiguity of supporting routines with neither keyword. Mandatory keywords would also have the added benefit of being self-documented but at the cost of extra typing. While there are several benefits to mandatory keywords, they do bring a few challenges. Mandatory keywords in \CFA would imply that the compiler must know without doubt whether or not a parameter is a monitor or not. Since \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. For this reason, \CFA only has the \code{mutex} keyword and uses no keyword to mean \code{nomutex}.
     98
     99The next semantic decision is to establish when \code{mutex} may be used as a type qualifier. Consider the following declarations:
     100\begin{cfacode}
     101int f1(monitor & mutex m);
     102int f2(const monitor & mutex m);
     103int f3(monitor ** mutex m);
     104int f4(monitor * mutex m []);
     105int f5(graph(monitor*) & mutex m);
     106\end{cfacode}
     107The problem is to indentify which object(s) should be acquired. Furthermore, each object needs to be acquired only once. In 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. Adding indirections (\code{f3}) still allows the compiler and programmer to indentify which object is acquired. However, adding in arrays (\code{f4}) makes it much harder. Array lengths are not necessarily known in C, and even then making sure objects are only acquired once becomes none-trivial. This problem can be extended to absurd limits like \code{f5}, which uses a graph of monitors. To 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). Also note that while routine \code{f3} can be supported, meaning that monitor \code{**m} is be acquired, passing an array to this routine would be type safe and yet result in undefined behavior because only the first element of the array is acquired. However, this ambiguity is part of the C type-system with respects to arrays. For this reason, \code{mutex} is disallowed in the context where arrays may be passed:
     108\begin{cfacode}
     109int f1(monitor & mutex m);   //Okay : recommanded case
     110int f2(monitor * mutex m);   //Okay : could be an array but probably not
     111int f3(monitor mutex m []);  //Not Okay : Array of unkown length
     112int f4(monitor ** mutex m);  //Not Okay : Could be an array
     113int f5(monitor * mutex m []); //Not Okay : Array of unkown length
     114\end{cfacode}
     115Note that not all array functions are actually distinct in the type system. However, even if the code generation could tell the difference, the extra information is still not sufficient to extend meaningfully the monitor call semantic.
     116
     117Unlike object-oriented monitors, where calling a mutex member \emph{implicitly} acquires mutual-exclusion of the receiver object, \CFA uses an explicit mechanism to acquire mutual-exclusion. A consequence of this approach is that it extends naturally to multi-monitor calls.
     118\begin{cfacode}
     119int f(MonitorA & mutex a, MonitorB & mutex b);
     120
     121MonitorA a;
     122MonitorB b;
     123f(a,b);
     124\end{cfacode}
     125While OO monitors could be extended with a mutex qualifier for multiple-monitor calls, no example of this feature could be found. The capacity to acquire multiple locks before entering a critical section is called \emph{\gls{bulk-acq}}. In practice, writing multi-locking routines that do not lead to deadlocks is tricky. Having language support for such a feature is therefore a significant asset for \CFA. In the case presented above, \CFA guarantees that the order of aquisition is consistent across calls to different routines using the same monitors as arguments. This consistent ordering means acquiring multiple monitors in the way is safe from deadlock. However, users can still force the acquiring order. For example, notice which routines use \code{mutex}/\code{nomutex} and how this affects aquiring order:
     126\begin{cfacode}
     127void foo(A & mutex a, B & mutex b) { //acquire a & b
     128        ...
     129}
     130
     131void bar(A & mutex a, B & /*nomutex*/ b) { //acquire a
     132        ... foo(a, b); ... //acquire b
     133}
     134
     135void baz(A & /*nomutex*/ a, B & mutex b) { //acquire b
     136        ... foo(a, b); ... //acquire a
     137}
     138\end{cfacode}
     139The \gls{multi-acq} monitor lock allows a monitor lock to be acquired by both \code{bar} or \code{baz} and acquired again in \code{foo}. In the calls to \code{bar} and \code{baz} the monitors are acquired in opposite order.
     140
     141However, such use leads to the lock acquiring order problem. In 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}. This subtle mistake means that calling these routines concurrently may lead to deadlock and is therefore undefined behavior. As shown\cit, solving this problem requires:
     142\begin{enumerate}
     143        \item Dynamically tracking of the monitor-call order.
     144        \item Implement rollback semantics.
     145\end{enumerate}
     146While the first requirement is already a significant constraint on the system, implementing a general rollback semantics in a C-like language is prohibitively complex \cit. In \CFA, users simply need to be carefull when acquiring multiple monitors at the same time or only use \gls{bulk-acq} of all the monitors. While \CFA provides only a partial solution, many system provide no solution and the \CFA partial solution handles many useful cases.
     147
     148For example, \gls{multi-acq} and \gls{bulk-acq} can be used together in interesting ways:
     149\begin{cfacode}
     150monitor bank { ... };
     151
     152void deposit( bank & mutex b, int deposit );
     153
     154void transfer( bank & mutex mybank, bank & mutex yourbank, int me2you) {
     155        deposit( mybank, -me2you );
     156        deposit( yourbank, me2you );
     157}
     158\end{cfacode}
     159This example shows a trivial solution to the bank-account transfer-problem\cit. Without \gls{multi-acq} and \gls{bulk-acq}, the solution to this problem is much more involved and requires carefull engineering.
     160
     161\subsection{\code{mutex} statement} \label{mutex-stmt}
     162
     163The call semantics discussed aboved have one software engineering issue, only a named routine can acquire the mutual-exclusion of a set of monitor. \CFA offers the \code{mutex} statement to workaround the need for unnecessary names, avoiding a major software engineering problem\cit. Listing \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. Beyond naming, the \code{mutex} statement has no semantic difference from a routine call with \code{mutex} parameters.
     164
     165\begin{figure}
    183166\begin{center}
    184 \setlength\tabcolsep{1.5pt}
    185 \begin{tabular}{|c|c|c|}
    186 Code & \gls{callsite-locking} & \gls{entry-point-locking} \\
    187 \CFA & pseudo-code & pseudo-code \\
     167\begin{tabular}{|c|c|}
     168function call & \code{mutex} statement \\
    188169\hline
    189170\begin{cfacode}[tabsize=3]
    190 void foo(monitor& mutex a){
    191 
    192 
    193 
    194         //Do Work
    195         //...
    196 
    197 }
    198 
    199 void main() {
    200         monitor a;
    201 
    202 
    203 
    204         foo(a);
    205 
    206 }
    207 \end{cfacode} & \begin{pseudo}[tabsize=3]
    208 foo(& a) {
    209 
    210 
    211 
    212         //Do Work
    213         //...
    214 
    215 }
    216 
    217 main() {
    218         monitor a;
    219         //calling routine
    220         //handles concurrency
    221         acquire(a);
    222         foo(a);
    223         release(a);
    224 }
    225 \end{pseudo} & \begin{pseudo}[tabsize=3]
    226 foo(& a) {
    227         //called routine
    228         //handles concurrency
    229         acquire(a);
    230         //Do Work
    231         //...
    232         release(a);
    233 }
    234 
    235 main() {
    236         monitor a;
    237 
    238 
    239 
    240         foo(a);
    241 
    242 }
    243 \end{pseudo}
     171monitor M {};
     172void foo( M & mutex m ) {
     173        //critical section
     174}
     175
     176void bar( M & m ) {
     177        foo( m );
     178}
     179\end{cfacode}&\begin{cfacode}[tabsize=3]
     180monitor M {};
     181void bar( M & m ) {
     182        mutex(m) {
     183                //critical section
     184        }
     185}
     186
     187
     188\end{cfacode}
    244189\end{tabular}
    245190\end{center}
    246 
    247 \Gls{callsite-locking} is inefficient, since any \code{dtype} routine may have to obtain some lock before calling a routine, depending on whether or not the type passed is a monitor. However, with \gls{entry-point-locking} calling a monitor routine becomes exactly the same as calling it from anywhere else.
    248 
    249 Note the \code{mutex} keyword relies on the resolver, which means that in cases where a generic monitor routine is actually desired, writing a mutex routine is possible with the proper trait. This is possible because monitors are designed in terms a trait. For example:
    250 \begin{cfacode}
    251 //Incorrect
    252 //T is not a monitor
    253 forall(dtype T)
    254 void foo(T * mutex t);
    255 
    256 //Correct
    257 //this function only works on monitors
    258 //(any monitor)
    259 forall(dtype T | is_monitor(T))
    260 void bar(T * mutex t));
    261 \end{cfacode}
    262 
    263 
    264 % ======================================================================
    265 % ======================================================================
    266 \section{Internal scheduling} \label{insched}
    267 % ======================================================================
    268 % ======================================================================
    269 In addition to mutual exclusion, the monitors at the core of \CFA's concurrency can also be used to achieve synchronisation. With monitors, this is generally achieved with internal or external scheduling as in\cit. Since internal scheduling of single monitors is mostly a solved problem, this proposal concentraits on extending internal scheduling to multiple monitors at once. Indeed, like the \gls{group-acquire} semantics, internal scheduling extends to multiple monitors at once in a way that is natural to the user but requires additional complexity on the implementation side.
     191\caption{Regular call semantics vs. \code{mutex} statement}
     192\label{lst:mutex-stmt}
     193\end{figure}
     194
     195% ======================================================================
     196% ======================================================================
     197\subsection{Data semantics} \label{data}
     198% ======================================================================
     199% ======================================================================
     200Once the call semantics are established, the next step is to establish data semantics. Indeed, until now a monitor is used simply as a generic handle but in most cases monitors contain shared data. This data should be intrinsic to the monitor declaration to prevent any accidental use of data without its appropriate protection. For example, here is a complete version of the counter showed in section \ref{call}:
     201\begin{cfacode}
     202monitor counter_t {
     203        int value;
     204};
     205
     206void ?{}(counter_t & this) {
     207        this.cnt = 0;
     208}
     209
     210int ?++(counter_t & mutex this) {
     211        return ++this.value;
     212}
     213
     214//need for mutex is platform dependent here
     215void ?{}(int * this, counter_t & mutex cnt) {
     216        *this = (int)cnt;
     217}
     218\end{cfacode}
     219
     220Like threads and coroutines, monitors are defined in terms of traits with some additional language support in the form of the \code{monitor} keyword. The monitor trait is :
     221\begin{cfacode}
     222trait is_monitor(dtype T) {
     223        monitor_desc * get_monitor( T & );
     224        void ^?{}( T & mutex );
     225};
     226\end{cfacode}
     227Note that the destructor of a monitor must be a \code{mutex} routine. This requirement ensures that the destructor has mutual-exclusion. As with any object, any call to a monitor, using \code{mutex} or otherwise, is Undefined Behaviour after the destructor has run.
     228
     229% ======================================================================
     230% ======================================================================
     231\section{Internal scheduling} \label{intsched}
     232% ======================================================================
     233% ======================================================================
     234In addition to mutual exclusion, the monitors at the core of \CFA's concurrency can also be used to achieve synchronisation. With monitors, this capability is generally achieved with internal or external scheduling as in\cit. Since internal scheduling within a single monitor is mostly a solved problem, this thesis concentrates on extending internal scheduling to multiple monitors. Indeed, like the \gls{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.
    270235
    271236First, here is a simple example of such a technique:
    272237
    273238\begin{cfacode}
    274         monitor A {
    275                 condition e;
    276         }
    277 
    278         void foo(A & mutex a) {
    279                 ...
    280                 // Wait for cooperation from bar()
    281                 wait(a.e);
    282                 ...
    283         }
    284 
    285         void bar(A & mutex a) {
    286                 // Provide cooperation for foo()
    287                 ...
    288                 // Unblock foo at scope exit
    289                 signal(a.e);
    290         }
    291 \end{cfacode}
    292 
    293 There are two details to note here. First, there \code{signal} is a delayed operation, it only unblocks the waiting thread when it reaches the end of the critical section. This is needed to respect mutual-exclusion. Second, in \CFA, \code{condition} have no particular need to be stored inside a monitor, beyond any software engineering reasons. Here routine \code{foo} waits for the \code{signal} from \code{bar} before making further progress, effectively ensuring a basic ordering.
    294 
    295 An important aspect to take into account here is that \CFA does not allow barging, which means that once function \code{bar} releases the monitor, foo is guaranteed to resume immediately after (unless some other thread waited on the same condition). This guarantees offers the benefit of not having to loop arount waits in order to guarantee that a condition is still met. The 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. Supporting barging prevention as well as extending internal scheduling to multiple monitors is the main source of complexity in the design of \CFA concurrency.
     239monitor A {
     240        condition e;
     241}
     242
     243void foo(A & mutex a) {
     244        ...
     245        //Wait for cooperation from bar()
     246        wait(a.e);
     247        ...
     248}
     249
     250void bar(A & mutex a) {
     251        //Provide cooperation for foo()
     252        ...
     253        //Unblock foo
     254        signal(a.e);
     255}
     256\end{cfacode}
     257
     258There are two details to note here. First, the \code{signal} is a delayed operation, it only unblocks the waiting thread when it reaches the end of the critical section. This semantic is needed to respect mutual-exclusion. The alternative is to return immediately after the call to \code{signal}, which is significantly more restrictive. Second, 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. Here routine \code{foo} waits for the \code{signal} from \code{bar} before making further progress, effectively ensuring a basic ordering.
     259
     260An 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 resume immediately after (unless some other thread waited on the same condition). This guarantees offers the benefit of not having to loop arount waits in order to guarantee that a condition is still met. The 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. Supporting barging prevention as well as extending internal scheduling to multiple monitors is the main source of complexity in the design of \CFA concurrency.
    296261
    297262% ======================================================================
     
    300265% ======================================================================
    301266% ======================================================================
    302 It is easier to understand the problem of multi-monitor scheduling using a series of pseudo-code. Note 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.
     267It is easier to understand the problem of multi-monitor scheduling using a series of pseudo-code. Note 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. Indeed, \code{wait} statements always use the implicit condition as paremeter and explicitly names the monitors (A and B) associated with the condition. Note that in \CFA, condition variables are tied to a set 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.
    303268
    304269\begin{multicols}{2}
     
    319284\end{pseudo}
    320285\end{multicols}
    321 The example shows the simple case of having two threads (one for each column) and a single monitor A. One thread acquires before waiting (atomically blocking and releasing A) and the other acquires before signalling. There is an important thing to note here, both \code{wait} and \code{signal} must be called with the proper monitor(s) already acquired. This restriction is hidden on the user side in \uC, as it is a logical requirement for barging prevention.
    322 
    323 A direct extension of the previous example is the \gls{group-acquire} version:
     286The example shows the simple case of having two threads (one for each column) and a single monitor A. One thread acquires before waiting (atomically blocking and releasing A) and the other acquires before signalling. It is important to note here that both \code{wait} and \code{signal} must be called with the proper monitor(s) already acquired. This semantic is a logical requirement for barging prevention.
     287
     288A direct extension of the previous example is a \gls{bulk-acq} version:
    324289
    325290\begin{multicols}{2}
     
    338303\end{pseudo}
    339304\end{multicols}
    340 This version uses \gls{group-acquire} (denoted using the \& symbol), but the presence of multiple monitors does not add a particularly new meaning. Synchronization happens between the two threads in exactly the same way and order. The only difference is that mutual exclusion covers more monitors. On the implementation side, handling multiple monitors does add a degree of complexity as the next few examples demonstrate.
    341 
    342 While 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. However, for monitors as for locks, it is possible to write a program using nesting without encountering any problems if nested is done correctly. For example, the next pseudo-code snippet acquires monitors A then B before waiting while only acquiring B when signalling, effectively avoiding the nested monitor problem.
    343 
     305This version uses \gls{bulk-acq} (denoted using the {\sf\&} symbol), but the presence of multiple monitors does not add a particularly new meaning. Synchronization happens between the two threads in exactly the same way and order. The only difference is that mutual exclusion covers more monitors. On the implementation side, handling multiple monitors does add a degree of complexity as the next few examples demonstrate.
     306
     307While 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. For monitors, a well known deadlock problem is the Nested Monitor Problem\cit, which occurs when a \code{wait} is made by a thread that holds more than one monitor. For example, the following pseudo-code runs into the nested-monitor problem :
    344308\begin{multicols}{2}
    345309\begin{pseudo}
     
    354318
    355319\begin{pseudo}
     320acquire A
     321        acquire B
     322                signal B
     323        release B
     324release A
     325\end{pseudo}
     326\end{multicols}
     327
     328The \code{wait} only releases monitor \code{B} so the signalling thread cannot acquire monitor \code{A} to get to the \code{signal}. Attempting release of all acquired monitors at the \code{wait} results in another set of problems such as releasing monitor \code{C}, which has nothing to do with the \code{signal}.
     329
     330However, for monitors as for locks, it is possible to write a program using nesting without encountering any problems if nesting is done correctly. For 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.
     331
     332\begin{multicols}{2}
     333\begin{pseudo}
     334acquire A
     335        acquire B
     336                wait B
     337        release B
     338release A
     339\end{pseudo}
     340
     341\columnbreak
     342
     343\begin{pseudo}
    356344
    357345acquire B
     
    362350\end{multicols}
    363351
    364 The next example is where \gls{group-acquire} adds a significant layer of complexity to the internal signalling semantics.
    365 
     352% ======================================================================
     353% ======================================================================
     354\subsection{Internal Scheduling - in depth}
     355% ======================================================================
     356% ======================================================================
     357
     358A larger example is presented to show complex issuesfor \gls{bulk-acq} and all the implementation options are analyzed. Listing \ref{lst:int-bulk-pseudo} shows an example where \gls{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 which implements the pseudo-code in listing \ref{lst:int-bulk-pseudo}. For the purpose of translating the given pseudo-code into \CFA-code any method of introducing monitor into context, other than a \code{mutex} parameter, is acceptable, e.g., global variables, pointer parameters or using locals with the \code{mutex}-statement.
     359
     360\begin{figure}[!b]
    366361\begin{multicols}{2}
    367362Waiting thread
    368363\begin{pseudo}[numbers=left]
    369364acquire A
    370         // Code Section 1
     365        //Code Section 1
    371366        acquire A & B
    372                 // Code Section 2
     367                //Code Section 2
    373368                wait A & B
    374                 // Code Section 3
     369                //Code Section 3
    375370        release A & B
    376         // Code Section 4
     371        //Code Section 4
    377372release A
    378373\end{pseudo}
     
    383378\begin{pseudo}[numbers=left, firstnumber=10]
    384379acquire A
    385         // Code Section 5
     380        //Code Section 5
    386381        acquire A & B
    387                 // Code Section 6
     382                //Code Section 6
    388383                signal A & B
    389                 // Code Section 7
     384                //Code Section 7
    390385        release A & B
    391         // Code Section 8
     386        //Code Section 8
    392387release A
    393388\end{pseudo}
    394389\end{multicols}
     390\caption{Internal scheduling with \gls{bulk-acq}}
     391\label{lst:int-bulk-pseudo}
     392\end{figure}
     393
     394\begin{figure}[!b]
    395395\begin{center}
    396 Listing 1
     396\begin{cfacode}[xleftmargin=.4\textwidth]
     397monitor A a;
     398monitor B b;
     399condition c;
     400\end{cfacode}
    397401\end{center}
    398 
    399 It is particularly important to pay attention to code sections 8 and 4, which are where the existing semantics of internal scheduling need to be extended for multiple monitors. The root of the problem is that \gls{group-acquire} is used in a context where one of the monitors is already acquired and is why it is important to define the behaviour of the previous pseudo-code. When the signaller thread reaches the location where it should "release A \& B" (line 16), it must actually transfer ownership of monitor B to the waiting thread. This ownership trasnfer is required in order to prevent barging. Since the signalling thread still needs the monitor A, simply waking up the waiting thread is not an option because it would violate mutual exclusion. There are three options:
     402\begin{multicols}{2}
     403Waiting thread
     404\begin{cfacode}
     405mutex(a) {
     406        //Code Section 1
     407        mutex(a, b) {
     408                //Code Section 2
     409                wait(c);
     410                //Code Section 3
     411        }
     412        //Code Section 4
     413}
     414\end{cfacode}
     415
     416\columnbreak
     417
     418Signalling thread
     419\begin{cfacode}
     420mutex(a) {
     421        //Code Section 5
     422        mutex(a, b) {
     423                //Code Section 6
     424                signal(c);
     425                //Code Section 7
     426        }
     427        //Code Section 8
     428}
     429\end{cfacode}
     430\end{multicols}
     431\caption{Equivalent \CFA code for listing \ref{lst:int-bulk-pseudo}}
     432\label{lst:int-bulk-cfa}
     433\end{figure}
     434
     435The complexity begins at code sections 4 and 8, which are where the existing semantics of internal scheduling need to be extended for multiple monitors. The root of the problem is that \gls{bulk-acq} is used in a context where one of the monitors is already acquired and is why it is important to define the behaviour of the previous pseudo-code. When the signaller thread reaches the location where it should ``release \code{A & B}'' (line 16), it must actually transfer ownership of monitor \code{B} to the waiting thread. This ownership trasnfer is required in order to prevent barging. Since the signalling thread still needs monitor \code{A}, simply waking up the waiting thread is not an option because it violates mutual exclusion. There are three options.
    400436
    401437\subsubsection{Delaying signals}
    402 The first more obvious solution to solve the problem of multi-monitor scheduling is to keep ownership of all locks until the last lock is ready to be transferred. It can be argued that that moment is the correct time to transfer ownership when the last lock is no longer needed because this semantics fits most closely to the behaviour of single monitor scheduling. This solution has the main benefit of transferring ownership of groups of monitors, which simplifies the semantics from mutiple objects to a single group of object, effectively making the existing single monitor semantic viable by simply changing monitors to monitor collections.
     438The obvious solution to solve the problem of multi-monitor scheduling is to keep ownership of all locks until the last lock is ready to be transferred. It 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. This solution has the main benefit of transferring ownership of groups of monitors, which simplifies the semantics from mutiple objects to a single group of objects, effectively making the existing single-monitor semantic viable by simply changing monitors to monitor groups.
    403439\begin{multicols}{2}
    404440Waiter
     
    424460\end{pseudo}
    425461\end{multicols}
    426 However, this solution can become much more complicated depending on what is executed while secretly holding B (at line 10). Indeed, nothing prevents a user from signalling monitor A on a different condition variable:
    427 \newpage
    428 \begin{multicols}{2}
    429 Thread 1
     462However, this solution can become much more complicated depending on what is executed while secretly holding B (at line 10). Indeed, nothing prevents signalling monitor A on a different condition variable:
     463\begin{figure}
     464\begin{multicols}{3}
     465Thread $\alpha$
    430466\begin{pseudo}[numbers=left, firstnumber=1]
    431467acquire A
     
    436472\end{pseudo}
    437473
    438 Thread 2
    439 \begin{pseudo}[numbers=left, firstnumber=6]
    440 acquire A
    441         wait A
    442 release A
    443 \end{pseudo}
    444 
    445474\columnbreak
    446475
    447 Thread 3
    448 \begin{pseudo}[numbers=left, firstnumber=10]
     476Thread $\gamma$
     477\begin{pseudo}[numbers=left, firstnumber=1]
    449478acquire A
    450479        acquire A & B
    451480                signal A & B
    452481        release A & B
    453         //Secretly keep B here
    454482        signal A
    455483release A
    456 //Wakeup thread 1 or 2?
    457 //Who wakes up the other thread?
    458 \end{pseudo}
     484\end{pseudo}
     485
     486\columnbreak
     487
     488Thread $\beta$
     489\begin{pseudo}[numbers=left, firstnumber=1]
     490acquire A
     491        wait A
     492release A
     493\end{pseudo}
     494
    459495\end{multicols}
     496\caption{Dependency graph}
     497\label{lst:dependency}
     498\end{figure}
    460499
    461500The goal in this solution is to avoid the need to transfer ownership of a subset of the condition monitors. However, this goal is unreacheable in the previous example. Depending on the order of signals (line 12 and 15) two cases can happen.
     
    467506Note that ordering is not determined by a race condition but by whether signalled threads are enqueued in FIFO or FILO order. However, regardless of the answer, users can move line 15 before line 11 and get the reverse effect.
    468507
    469 In 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 monitors cannot be handled as a single homogenous group.
     508In 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 monitors cannot be handled as a single homogenous group and therefore effectively precludes this approach.
    470509
    471510\subsubsection{Dependency graphs}
    472 In the Listing 1 pseudo-code, there is a solution which statisfies both barging prevention and mutual exclusion. If ownership of both monitors is transferred to the waiter when the signaller releases A and then the waiter transfers back ownership of A when it releases it then the problem is solved. Dynamically finding the correct order is therefore the second possible solution. The problem it encounters is that it effectively boils down to resolving a dependency graph of ownership requirements. Here even the simplest of code snippets requires two transfers and it seems to increase in a manner closer to polynomial. For example, the following code, which is just a direct extension to three monitors, requires at least three ownership transfer and has multiple solutions:
     511In the listing \ref{lst:int-bulk-pseudo} pseudo-code, there is a solution which statisfies both barging prevention and mutual exclusion. If 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} when it releases it, then the problem is solved (\code{B} is no longer in use at this point). Dynamically finding the correct order is therefore the second possible solution. The problem it encounters is that it effectively boils down to resolving a dependency graph of ownership requirements. Here even the simplest of code snippets requires two transfers and it seems to increase in a manner closer to polynomial. For example, the following code, which is just a direct extension to three monitors, requires at least three ownership transfer and has multiple solutions:
    473512
    474513\begin{multicols}{2}
     
    495534\end{pseudo}
    496535\end{multicols}
    497 Resolving dependency graph being a complex and expensive endeavour, this solution is not the preffered one.
     536
     537\begin{figure}
     538\begin{center}
     539\input{dependency}
     540\end{center}
     541\caption{Dependency graph of the statements in listing \ref{lst:dependency}}
     542\label{fig:dependency}
     543\end{figure}
     544
     545Listing \ref{lst:dependency} is the three thread example rewritten for dependency graphs. 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$). The 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 dependency unfolds. Resolving dependency graph being a complex and expensive endeavour, this solution is not the preffered one.
    498546
    499547\subsubsection{Partial signalling} \label{partial-sig}
    500 Finally, the solution that is chosen for \CFA is to use partial signalling. Consider the following case:
    501 
    502 \begin{multicols}{2}
    503 \begin{pseudo}[numbers=left]
    504 acquire A
    505         acquire A & B
    506                 wait A & B
    507         release A & B
    508 release A
    509 \end{pseudo}
    510 
    511 \columnbreak
    512 
    513 \begin{pseudo}[numbers=left, firstnumber=6]
    514 acquire A
    515         acquire A & B
    516                 signal A & B
    517         release A & B
    518         // ... More code
    519 release A
    520 \end{pseudo}
    521 \end{multicols}
    522 The partial signalling solution transfers ownership of monitor B at lines 10 but does not wake the waiting thread since it is still using monitor A. Only when it reaches line 11 does it actually wakeup the waiting thread. This solution has the benefit that complexity is encapsulated into only two actions, passing monitors to the next owner when they should be release and conditionnaly waking threads if all conditions are met. Contrary to the other solutions, this solution quickly hits an upper bound on complexity of implementation.
     548Finally, the solution that is chosen for \CFA is to use partial signalling. Again using listing \ref{lst:int-bulk-pseudo}, the partial signalling solution transfers ownership of monitor B at lines 10 but does not wake the waiting thread since it is still using monitor A. Only when it reaches line 11 does it actually wakeup the waiting thread. This solution has the benefit that complexity is encapsulated into only two actions, passing monitors to the next owner when they should be release and conditionally waking threads if all conditions are met. This solution has a much simpler implementation than a dependency graph solving algorithm which is why it was chosen. Furthermore, after being fully implemented, this solution does not appear to have any downsides worth mentionning.
    523549
    524550% ======================================================================
     
    527553% ======================================================================
    528554% ======================================================================
    529 An important note is that, until now, signalling a monitor was a delayed operation. The ownership of the monitor is transferred only when the monitor would have otherwise been released, not at the point of the \code{signal} statement. However, 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\footnote{name to be discussed}.
    530 
    531 For example here is an example highlighting the difference in behaviour:
    532 \begin{center}
     555\begin{figure}
    533556\begin{tabular}{|c|c|}
    534557\code{signal} & \code{signal_block} \\
    535558\hline
    536 \begin{cfacode}
    537 monitor M { int val; };
    538 
    539 void foo(M & mutex m ) {
    540         m.val++;
    541         sout| "Foo:" | m.val |endl;
    542 
    543         wait( c );
    544 
    545         m.val++;
    546         sout| "Foo:" | m.val |endl;
    547 }
    548 
    549 void bar(M & mutex m ) {
    550         m.val++;
    551         sout| "Bar:" | m.val |endl;
    552 
    553         signal( c );
    554 
    555         m.val++;
    556         sout| "Bar:" | m.val |endl;
    557 }
    558 \end{cfacode}&\begin{cfacode}
    559 monitor M { int val; };
    560 
    561 void foo(M & mutex m ) {
    562         m.val++;
    563         sout| "Foo:" | m.val |endl;
    564 
    565         wait( c );
    566 
    567         m.val++;
    568         sout| "Foo:" | m.val |endl;
    569 }
    570 
    571 void bar(M & mutex m ) {
    572         m.val++;
    573         sout| "Bar:" | m.val |endl;
    574 
    575         signal_block( c );
    576 
    577         m.val++;
    578         sout| "Bar:" | m.val |endl;
     559\begin{cfacode}[tabsize=3]
     560monitor DatingService
     561{
     562        //compatibility codes
     563        enum{ CCodes = 20 };
     564
     565        int girlPhoneNo
     566        int boyPhoneNo;
     567};
     568
     569condition girls[CCodes];
     570condition boys [CCodes];
     571condition exchange;
     572
     573int girl(int phoneNo, int ccode)
     574{
     575        //no compatible boy ?
     576        if(empty(boys[ccode]))
     577        {
     578                //wait for boy
     579                wait(girls[ccode]);
     580
     581                //make phone number available
     582                girlPhoneNo = phoneNo;
     583
     584                //wake boy from chair
     585                signal(exchange);
     586        }
     587        else
     588        {
     589                //make phone number available
     590                girlPhoneNo = phoneNo;
     591
     592                //wake boy
     593                signal(boys[ccode]);
     594
     595                //sit in chair
     596                wait(exchange);
     597        }
     598        return boyPhoneNo;
     599}
     600
     601int boy(int phoneNo, int ccode)
     602{
     603        //same as above
     604        //with boy/girl interchanged
     605}
     606\end{cfacode}&\begin{cfacode}[tabsize=3]
     607monitor DatingService
     608{
     609        //compatibility codes
     610        enum{ CCodes = 20 };
     611
     612        int girlPhoneNo;
     613        int boyPhoneNo;
     614};
     615
     616condition girls[CCodes];
     617condition boys [CCodes];
     618//exchange is not needed
     619
     620int girl(int phoneNo, int ccode)
     621{
     622        //no compatible boy ?
     623        if(empty(boys[ccode]))
     624        {
     625                //wait for boy
     626                wait(girls[ccode]);
     627
     628                //make phone number available
     629                girlPhoneNo = phoneNo;
     630
     631                //wake boy from chair
     632                signal(exchange);
     633        }
     634        else
     635        {
     636                //make phone number available
     637                girlPhoneNo = phoneNo;
     638
     639                //wake boy
     640                signal_block(boys[ccode]);
     641
     642                //second handshake unnecessary
     643
     644        }
     645        return boyPhoneNo;
     646}
     647
     648int boy(int phoneNo, int ccode)
     649{
     650        //same as above
     651        //with boy/girl interchanged
    579652}
    580653\end{cfacode}
    581654\end{tabular}
    582 \end{center}
    583 Assuming that \code{val} is initialized at 0, that each routine are called from seperate thread and that \code{foo} is always called first. The previous code would yield the following output:
    584 
     655\caption{Dating service example using \code{signal} and \code{signal_block}. }
     656\label{lst:datingservice}
     657\end{figure}
     658An important note is that, until now, signalling a monitor was a delayed operation. The ownership of the monitor is transferred only when the monitor would have otherwise been released, not at the point of the \code{signal} statement. However, 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\footnote{name to be discussed}.
     659
     660The example in listing \ref{lst:datingservice} highlights the difference in behaviour. As mentioned, \code{signal} only transfers ownership once the current critical section exits, this behaviour requires additional synchronisation when a two-way handshake is needed. To avoid this extraneous synchronisation, the \code{condition} type offers the \code{signal_block} routine, which handles the two-way handshake as shown in the example. This removes the need for a second condition variables and simplifies programming. Like every other monitor semantic, \code{signal_block} uses barging prevention, which means mutual-exclusion is baton-passed both on the frond-end and the back-end of the call to \code{signal_block}, meaning no other thread can acquire the monitor neither before nor after the call.
     661
     662% ======================================================================
     663% ======================================================================
     664\section{External scheduling} \label{extsched}
     665% ======================================================================
     666% ======================================================================
     667An alternative to internal scheduling is external scheduling, e.g., in \uC.
    585668\begin{center}
    586 \begin{tabular}{|c|c|}
    587 \code{signal} & \code{signal_block} \\
     669\begin{tabular}{|c|c|c|}
     670Internal Scheduling & External Scheduling & Go\\
    588671\hline
    589 \begin{pseudo}
    590 Foo: 0
    591 Bar: 1
    592 Bar: 2
    593 Foo: 3
    594 \end{pseudo}&\begin{pseudo}
    595 Foo: 0
    596 Bar: 1
    597 Foo: 2
    598 Bar: 3
    599 \end{pseudo}
    600 \end{tabular}
    601 \end{center}
    602 
    603 As mentionned, \code{signal} only transfers ownership once the current critical section exits, resulting in the second "Bar" line to be printed before the second "Foo" line. On the other hand, \code{signal_block} immediately transfers ownership to \code{bar}, causing an inversion of output. Obviously this means that \code{signal_block} is a blocking call, which will only be resumed once the signalled function exits the critical section.
    604 
    605 % ======================================================================
    606 % ======================================================================
    607 \subsection{Internal scheduling: Implementation} \label{inschedimpl}
    608 % ======================================================================
    609 % ======================================================================
    610 There are several challenges specific to \CFA when implementing internal scheduling. These challenges are direct results of \gls{group-acquire} and loose object definitions. These two constraints are to root cause of most design decisions in the implementation of internal scheduling. Furthermore, to avoid the head-aches of dynamically allocating memory in a concurrent environment, the internal-scheduling design is entirely free of mallocs and other dynamic memory allocation scheme. This is to avoid the chicken and egg problem of having a memory allocator that relies on the threading system and a threading system that relies on the runtime. This extra goal, means that memory management is a constant concern in the design of the system.
    611 
    612 The main memory concern for concurrency is queues. All blocking operations are made by parking threads onto queues. These queues need to be intrinsic\cit to avoid the need memory allocation. This entails that all the fields needed to keep track of all needed information. Since internal scheduling can use an unbound amount of memory (depending on \gls{group-acquire}) statically defining information information in the intrusive fields of threads is insufficient. The only variable sized container that does not require memory allocation is the callstack, which is heavily used in the implementation of internal scheduling. Particularly the GCC extension variable length arrays which is used extensively.
    613 
    614 Since stack allocation is based around scope, 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. In the case of external scheduling, the threads and the condition both allow a fixed amount of memory to be stored, while mutex-routines and the actual blocking call allow for an unbound amount (though adding too much to the mutex routine stack size can become expansive faster).
    615 
    616 The following figure is the traditionnal illustration of a monitor :
    617 
    618 \begin{center}
    619 {\resizebox{0.4\textwidth}{!}{\input{monitor}}}
    620 \end{center}
    621 
    622 For \CFA, the previous picture does not have support for blocking multiple monitors on a single condition. To support \gls{group-acquire} two changes to this picture are required. First, it doesn't make sense to tie the condition to a single monitor since blocking two monitors as one would require arbitrarily picking a monitor to hold the condition. Secondly, the object waiting on the conditions and AS-stack cannot simply contain the waiting thread since a single thread can potentially wait on multiple monitors. As mentionned in section \ref{inschedimpl}, the handling in multiple monitors is done by partially passing, which entails that each concerned monitor needs to have a node object. However, for waiting on the condition, since all threads need to wait together, a single object needs to be queued in the condition. Moving out the condition and updating the node types yields :
    623 
    624 \begin{center}
    625 {\resizebox{0.8\textwidth}{!}{\input{int_monitor}}}
    626 \end{center}
    627 
    628 \newpage
    629 
    630 This picture and the proper entry and leave algorithms is the fundamental implementation of internal scheduling.
    631 
    632 \begin{multicols}{2}
    633 Entry
    634 \begin{pseudo}[numbers=left]
    635 if monitor is free
    636         enter
    637 elif I already own the monitor
    638         continue
    639 else
    640         block
    641 increment recursion
    642 
    643 \end{pseudo}
    644 \columnbreak
    645 Exit
    646 \begin{pseudo}[numbers=left, firstnumber=8]
    647 decrement recursion
    648 if recursion == 0
    649         if signal_stack not empty
    650                 set_owner to thread
    651                 if all monitors ready
    652                         wake-up thread
    653 
    654         if entry queue not empty
    655                 wake-up thread
    656 \end{pseudo}
    657 \end{multicols}
    658 
    659 Some important things to notice about the exit routine. The solution discussed in \ref{inschedimpl} can be seen on line 11 of the previous pseudo code. Basically, the solution boils down to having a seperate 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 trasnferred ownership. This solution is safe as well as preventing any potential barging.
    660 
    661 % ======================================================================
    662 % ======================================================================
    663 \section{External scheduling} \label{extsched}
    664 % ======================================================================
    665 % ======================================================================
    666 An alternative to internal scheduling is to use external scheduling.
    667 \begin{center}
    668 \begin{tabular}{|c|c|}
    669 Internal Scheduling & External Scheduling \\
    670 \hline
    671 \begin{ucppcode}
     672\begin{ucppcode}[tabsize=3]
    672673_Monitor Semaphore {
    673674        condition c;
     
    675676public:
    676677        void P() {
    677                 if(inUse) wait(c);
     678                if(inUse)
     679                        wait(c);
    678680                inUse = true;
    679681        }
     
    683685        }
    684686}
    685 \end{ucppcode}&\begin{ucppcode}
     687\end{ucppcode}&\begin{ucppcode}[tabsize=3]
    686688_Monitor Semaphore {
    687689
     
    689691public:
    690692        void P() {
    691                 if(inUse) _Accept(V);
     693                if(inUse)
     694                        _Accept(V);
    692695                inUse = true;
    693696        }
     
    697700        }
    698701}
    699 \end{ucppcode}
     702\end{ucppcode}&\begin{gocode}[tabsize=3]
     703type MySem struct {
     704        inUse bool
     705        c     chan bool
     706}
     707
     708// acquire
     709func (s MySem) P() {
     710        if s.inUse {
     711                select {
     712                case <-s.c:
     713                }
     714        }
     715        s.inUse = true
     716}
     717
     718// release
     719func (s MySem) V() {
     720        s.inUse = false
     721
     722        //This actually deadlocks
     723        //when single thread
     724        s.c <- false
     725}
     726\end{gocode}
    700727\end{tabular}
    701728\end{center}
    702 This method is more constrained and explicit, which may help users tone down the undeterministic nature of concurrency. Indeed, as the following examples demonstrates, external scheduling allows users to wait for events from other threads without the concern of unrelated events occuring. External scheduling can generally be done either in terms of control flow (e.g., \uC) or in terms of data (e.g. Go). Of course, both of these paradigms have their own strenghts and weaknesses but for this project control-flow semantics were chosen to stay consistent with the rest of the languages semantics. Two challenges specific to \CFA arise when trying to add external scheduling with loose object definitions and multi-monitor routines. The previous example shows a simple use \code{_Accept} versus \code{wait}/\code{signal} and its advantages. Note that while other languages often use \code{accept} as the core external scheduling keyword, \CFA uses \code{waitfor} to prevent name collisions with existing socket APIs.
    703 
    704 In the case of internal scheduling, the call to \code{wait} only guarantees that \code{V} is the last routine to access the monitor. This entails that the routine \code{V} may have acquired mutual exclusion several times while routine \code{P} was waiting. On the other hand, external scheduling guarantees that while routine \code{P} was waiting, no routine other than \code{V} could acquire the monitor.
     729This method is more constrained and explicit, which helps users tone down the undeterministic nature of concurrency. Indeed, as the following examples demonstrates, external scheduling allows users to wait for events from other threads without the concern of unrelated events occuring. External scheduling can generally be done either in terms of control flow (e.g., \uC with \code{_Accept}) or in terms of data (e.g., Go with channels). Of course, both of these paradigms have their own strenghts and weaknesses but for this project control-flow semantics were chosen to stay consistent with the rest of the languages semantics. Two challenges specific to \CFA arise when trying to add external scheduling with loose object definitions and multi-monitor routines. The previous example shows a simple use \code{_Accept} versus \code{wait}/\code{signal} and its advantages. Note 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 \acrshort{api}s.
     730
     731For 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. On the other hand, external scheduling guarantees that while routine \code{P} is waiting, no routine other than \code{V} can acquire the monitor.
    705732
    706733% ======================================================================
     
    709736% ======================================================================
    710737% ======================================================================
    711 In \uC, monitor declarations include an exhaustive list of monitor operations. Since \CFA is not object oriented it becomes both more difficult to implement but also less clear for the user:
    712 
    713 \begin{cfacode}
    714         monitor A {};
    715 
    716         void f(A & mutex a);
    717         void f(int a, float b);
    718         void g(A & mutex a) {
    719                 waitfor(f); // Less obvious which f() to wait for
    720         }
     738In \uC, monitor declarations include an exhaustive list of monitor operations. Since \CFA is not object oriented, monitors become both more difficult to implement and less clear for a user:
     739
     740\begin{cfacode}
     741monitor A {};
     742
     743void f(A & mutex a);
     744void g(A & mutex a) {
     745        waitfor(f); //Obvious which f() to wait for
     746}
     747
     748void f(A & mutex a, int); //New different F added in scope
     749void h(A & mutex a) {
     750        waitfor(f); //Less obvious which f() to wait for
     751}
    721752\end{cfacode}
    722753
     
    728759        if monitor is free
    729760                enter
    730         elif I already own the monitor
     761        elif already own the monitor
    731762                continue
    732763        elif monitor accepts me
     
    738769\end{center}
    739770
    740 For the fist two conditions, it is easy to implement a check that can evaluate the condition in a few instruction. However, a fast check for \pscode{monitor accepts me} is much harder to implement depending on the constraints put on the monitors. Indeed, monitors are often expressed as an entry queue and some acceptor queue as in the following figure:
     771For the first two conditions, it is easy to implement a check that can evaluate the condition in a few instruction. However, a fast check for \pscode{monitor accepts me} is much harder to implement depending on the constraints put on the monitors. Indeed, monitors are often expressed as an entry queue and some acceptor queue as in the following figure:
    741772
    742773\begin{center}
     
    744775\end{center}
    745776
    746 There are other alternatives to these pictures but in the case of this picture implementing a fast accept check is relatively easy. Indeed simply updating a bitmask when the acceptor queue changes is enough to have a check that executes in a single instruction, even with a fairly large number (e.g. 128) of mutex members. This technique cannot be used in \CFA because it relies on the fact that the monitor type declares all the acceptable routines. For OO languages this does not compromise much since monitors already have an exhaustive list of member routines. However, for \CFA this is not the case; routines can be added to a type anywhere after its declaration. Its important to note that the bitmask approach does not actually require an exhaustive list of routines, but it requires a dense unique ordering of routines with an upper-bound and that ordering must be consistent across translation units.
    747 The alternative would be to have a picture more like this one:
     777There are other alternatives to these pictures, but in the case of this picture, implementing a fast accept check is relatively easy. Restricted 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. This technique cannot be used in \CFA because it relies on the fact that the monitor type enumerates (declares) all the acceptable routines. For OO languages this does not compromise much since monitors already have an exhaustive list of member routines. However, for \CFA this is not the case; routines can be added to a type anywhere after its declaration. It is important to note that the bitmask approach does not actually require an exhaustive list of routines, but it requires a dense unique ordering of routines with an upper-bound and that ordering must be consistent across translation units.
     778The alternative is to alter the implementeation like this:
    748779
    749780\begin{center}
     
    751782\end{center}
    752783
    753 Not storing the queues inside the monitor means that the storage can vary between routines, allowing for more flexibility and extensions. Storing an array of function-pointers would solve the issue of uniquely identifying acceptable routines. However, the single instruction bitmask compare has been replaced by dereferencing a pointer followed by a linear search. Furthermore, supporting nested external scheduling may now require additionnal searches on calls to waitfor to check if a routine is already queued in.
    754 
    755 At this point we must make a decision between flexibility and performance. Many 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. Here however, the cost of flexibility cannot be trivially removed. In the end, the most flexible approach has been chosen since it allows users to write programs that would otherwise be prohibitively hard to write. This is based on the assumption that writing fast but inflexible locks is closer to a solved problems than writing locks that are as flexible as external scheduling in \CFA.
    756 
    757 Another aspect to consider is what happens if multiple overloads of the same routine are used. For the time being it is assumed that multiple overloads of the same routine are considered as distinct routines. However, this could easily be extended in the future.
     784Generating a mask dynamically means that the storage for the mask information can vary between calls to \code{waitfor}, allowing for more flexibility and extensions. Storing an array of accepted function-pointers replaces the single instruction bitmask compare with dereferencing a pointer followed by a linear search. Furthermore, supporting nested external scheduling (e.g., listing \ref{lst:nest-ext}) may now require additionnal searches on calls to \code{waitfor} statement to check if a routine is already queued in.
     785
     786\begin{figure}
     787\begin{cfacode}
     788monitor M {};
     789void foo( M & mutex a ) {}
     790void bar( M & mutex b ) {
     791        //Nested in the waitfor(bar, c) call
     792        waitfor(foo, b);
     793}
     794void baz( M & mutex c ) {
     795        waitfor(bar, c);
     796}
     797
     798\end{cfacode}
     799\caption{Example of nested external scheduling}
     800\label{lst:nest-ext}
     801\end{figure}
     802
     803Note that in the second picture, tasks need to always keep track of which routine they are attempting to acquire the monitor and the routine mask needs to have both a function pointer and a set of monitors, as will be discussed in the next section. These details where omitted from the picture for the sake of simplifying the representation.
     804
     805At this point, a decision must be made between flexibility and performance. Many 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. Here however, the cost of flexibility cannot be trivially removed. In the end, the most flexible approach has been chosen since it allows users to write programs that would otherwise be prohibitively hard to write. This decision is based on the assumption that writing fast but inflexible locks is closer to a solved problems than writing locks that are as flexible as external scheduling in \CFA.
    758806
    759807% ======================================================================
     
    763811% ======================================================================
    764812
    765 External scheduling, like internal scheduling, becomes orders of magnitude more complex when we start introducing multi-monitor syntax. Even in the simplest possible case some new semantics need to be established:
    766 \begin{cfacode}
    767         mutex struct A {};
    768 
    769         mutex struct B {};
    770 
    771         void g(A & mutex a, B & mutex b) {
    772                 waitfor(f); //ambiguous, which monitor
    773         }
     813External scheduling, like internal scheduling, becomes significantly more complex when introducing multi-monitor syntax. Even in the simplest possible case, some new semantics need to be established:
     814\begin{cfacode}
     815monitor M {};
     816
     817void f(M & mutex a);
     818
     819void g(M & mutex b, M & mutex c) {
     820        waitfor(f); //two monitors M => unkown which to pass to f(M & mutex)
     821}
    774822\end{cfacode}
    775823
     
    777825
    778826\begin{cfacode}
    779         mutex struct A {};
    780 
    781         mutex struct B {};
    782 
    783         void g(A & mutex a, B & mutex b) {
    784                 waitfor( f, b );
    785         }
    786 \end{cfacode}
    787 
    788 This is unambiguous. Both locks will be acquired and kept, when routine \code{f} is called the lock for monitor \code{b} will be temporarily transferred from \code{g} to \code{f} (while \code{g} still holds lock \code{a}). This behavior can be extended to multi-monitor waitfor statment as follows.
    789 
    790 \begin{cfacode}
    791         mutex struct A {};
    792 
    793         mutex struct B {};
    794 
    795         void g(A & mutex a, B & mutex b) {
    796                 waitfor( f, a, b);
    797         }
    798 \end{cfacode}
    799 
    800 Note that the set of monitors passed to the \code{waitfor} statement must be entirely contained in the set of monitor already acquired in the routine. \code{waitfor} used in any other context is Undefined Behaviour.
    801 
    802 An important behavior to note is that what happens when set of monitors only match partially :
    803 
    804 \begin{cfacode}
    805         mutex struct A {};
    806 
    807         mutex struct B {};
    808 
    809         void g(A & mutex a, B & mutex b) {
    810                 waitfor(f, a, b);
    811         }
    812 
    813         A a1, a2;
    814         B b;
    815 
    816         void foo() {
    817                 g(a1, b);
    818         }
    819 
    820         void bar() {
    821                 f(a2, b);
    822         }
    823 \end{cfacode}
    824 
    825 While the equivalent can happen when using internal scheduling, the fact that conditions are branded on first use means that users have to use two different condition variables. In both cases, partially matching monitor sets will not wake-up the waiting thread. It is also important to note that in the case of external scheduling, as for routine calls, the order of parameters is important; \code{waitfor(f,a,b)} and \code{waitfor(f,b,a)} are to distinct waiting condition.
    826 
    827 % ======================================================================
    828 % ======================================================================
    829 \subsection{Implementation Details: External scheduling queues}
    830 % ======================================================================
    831 % ======================================================================
    832 To support multi-monitor external scheduling means that some kind of entry-queues must be used that is aware of both monitors. However, acceptable routines must be aware of the entry queues which means they must be stored inside at least one of the monitors that will be acquired. This in turn adds the requirement a systematic algorithm of disambiguating which queue is relavant regardless of user ordering. The proposed algorithm is to fall back on monitors lock ordering and specify that the monitor that is acquired first is the lock with the relevant entry queue. This assumes that the lock acquiring order is static for the lifetime of all concerned objects but that is a reasonable constraint. This algorithm choice has two consequences, the entry queue of the highest priority monitor is no longer a true FIFO queue and the queue of the lowest priority monitor is both required and probably unused. The queue can no longer be a FIFO queue because instead of simply containing the waiting threads in order arrival, they also contain the second mutex. Therefore, another thread with the same highest priority monitor but a different lowest priority monitor may arrive first but enter the critical section after a thread with the correct pairing. Secondly, since it may not be known at compile time which monitor will be the lowest priority monitor, every monitor needs to have the correct queues even though it is probable that half the multi-monitor queues will go unused for the entire duration of the program.
    833 
    834 % ======================================================================
    835 % ======================================================================
    836 \section{Other concurrency tools}
    837 % ======================================================================
    838 % ======================================================================
    839 % \TODO
     827monitor M {};
     828
     829void f(M & mutex a);
     830
     831void g(M & mutex a, M & mutex b) {
     832        waitfor( f, b );
     833}
     834\end{cfacode}
     835
     836This syntax is unambiguous. Both locks are acquired and kept by \code{g}. When 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}). This behavior can be extended to multi-monitor \code{waitfor} statement as follows.
     837
     838\begin{cfacode}
     839monitor M {};
     840
     841void f(M & mutex a, M & mutex b);
     842
     843void g(M & mutex a, M & mutex b) {
     844        waitfor( f, a, b);
     845}
     846\end{cfacode}
     847
     848Note 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.
     849
     850An important behavior to note is when a set of monitors only match partially :
     851
     852\begin{cfacode}
     853mutex struct A {};
     854
     855mutex struct B {};
     856
     857void g(A & mutex a, B & mutex b) {
     858        waitfor(f, a, b);
     859}
     860
     861A a1, a2;
     862B b;
     863
     864void foo() {
     865        g(a1, b); //block on accept
     866}
     867
     868void bar() {
     869        f(a2, b); //fufill cooperation
     870}
     871\end{cfacode}
     872
     873While 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. In both cases, partially matching monitor sets does not wake-up the waiting thread. It is also important to note that in the case of external scheduling, as for routine calls, the order of parameters is irrelevant; \code{waitfor(f,a,b)} and \code{waitfor(f,b,a)} are indistinguishable waiting condition.
     874
     875% ======================================================================
     876% ======================================================================
     877\subsection{\code{waitfor} semantics}
     878% ======================================================================
     879% ======================================================================
     880
     881Syntactically, the \code{waitfor} statement takes a function identifier and a set of monitors. While the set of monitors can be any list of expression, 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. It checks that the set of monitor passed in matches the requirements for a function call. Listing \ref{lst:waitfor} shows various usage of the waitfor statement and which are acceptable. The choice of the function type is made ignoring any non-\code{mutex} parameter. One limitation of the current implementation is that it does not handle overloading.
     882\begin{figure}
     883\begin{cfacode}
     884monitor A{};
     885monitor B{};
     886
     887void f1( A & mutex );
     888void f2( A & mutex, B & mutex );
     889void f3( A & mutex, int );
     890void f4( A & mutex, int );
     891void f4( A & mutex, double );
     892
     893void foo( A & mutex a1, A & mutex a2, B & mutex b1, B & b2 ) {
     894        A * ap = & a1;
     895        void (*fp)( A & mutex ) = f1;
     896
     897        waitfor(f1, a1);     //Correct : 1 monitor case
     898        waitfor(f2, a1, b1); //Correct : 2 monitor case
     899        waitfor(f3, a1);     //Correct : non-mutex arguments are ignored
     900        waitfor(f1, *ap);    //Correct : expression as argument
     901
     902        waitfor(f1, a1, b1); //Incorrect : Too many mutex arguments
     903        waitfor(f2, a1);     //Incorrect : Too few mutex arguments
     904        waitfor(f2, a1, a2); //Incorrect : Mutex arguments don't match
     905        waitfor(f1, 1);      //Incorrect : 1 not a mutex argument
     906        waitfor(f9, a1);     //Incorrect : f9 function does not exist
     907        waitfor(*fp, a1 );   //Incorrect : fp not an identifier
     908        waitfor(f4, a1);     //Incorrect : f4 ambiguous
     909
     910        waitfor(f2, a1, b2); //Undefined Behaviour : b2 may not acquired
     911}
     912\end{cfacode}
     913\caption{Various correct and incorrect uses of the waitfor statement}
     914\label{lst:waitfor}
     915\end{figure}
     916
     917Finally, for added flexibility, \CFA supports constructing complex \code{waitfor} mask using the \code{or}, \code{timeout} and \code{else}. Indeed, multiple \code{waitfor} can be chained together using \code{or}; this chain forms a single statement that uses baton-pass to any one function that fits one of the function+monitor set passed in. To eanble users to tell which accepted function is accepted, \code{waitfor}s are followed by a statement (including the null statement \code{;}) or a compound statement. When multiple \code{waitfor} are chained together, only the statement corresponding to the accepted function is executed. A \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, that is only check of a matching function call already arrived and return immediately otherwise. Any and all of these clauses can be preceded by a \code{when} condition to dynamically construct the mask based on some current state. Listing \ref{lst:waitfor2}, demonstrates several complex masks and some incorrect ones.
     918
     919\begin{figure}
     920\begin{cfacode}
     921monitor A{};
     922
     923void f1( A & mutex );
     924void f2( A & mutex );
     925
     926void foo( A & mutex a, bool b, int t ) {
     927        //Correct : blocking case
     928        waitfor(f1, a);
     929
     930        //Correct : block with statement
     931        waitfor(f1, a) {
     932                sout | "f1" | endl;
     933        }
     934
     935        //Correct : block waiting for f1 or f2
     936        waitfor(f1, a) {
     937                sout | "f1" | endl;
     938        } or waitfor(f2, a) {
     939                sout | "f2" | endl;
     940        }
     941
     942        //Correct : non-blocking case
     943        waitfor(f1, a); or else;
     944
     945        //Correct : non-blocking case
     946        waitfor(f1, a) {
     947                sout | "blocked" | endl;
     948        } or else {
     949                sout | "didn't block" | endl;
     950        }
     951
     952        //Correct : block at most 10 seconds
     953        waitfor(f1, a) {
     954                sout | "blocked" | endl;
     955        } or timeout( 10`s) {
     956                sout | "didn't block" | endl;
     957        }
     958
     959        //Correct : block only if b == true
     960        //if b == false, don't even make the call
     961        when(b) waitfor(f1, a);
     962
     963        //Correct : block only if b == true
     964        //if b == false, make non-blocking call
     965        waitfor(f1, a); or when(!b) else;
     966
     967        //Correct : block only of t > 1
     968        waitfor(f1, a); or when(t > 1) timeout(t); or else;
     969
     970        //Incorrect : timeout clause is dead code
     971        waitfor(f1, a); or timeout(t); or else;
     972
     973        //Incorrect : order must be
     974        //waitfor [or waitfor... [or timeout] [or else]]
     975        timeout(t); or waitfor(f1, a); or else;
     976}
     977\end{cfacode}
     978\caption{Various correct and incorrect uses of the or, else, and timeout clause around a waitfor statement}
     979\label{lst:waitfor2}
     980\end{figure}
     981
     982% ======================================================================
     983% ======================================================================
     984\subsection{Waiting for the destructor}
     985% ======================================================================
     986% ======================================================================
     987An interesting use for the \code{waitfor} statement is destructor semantics. Indeed, the \code{waitfor} statement can accept any \code{mutex} routine, which includes the destructor (see section \ref{data}). However, 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. The simplest approach is to disallow \code{waitfor} on a destructor. However, a more expressive approach is to flip execution ordering 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.
     988\begin{figure}
     989\begin{cfacode}
     990monitor Executer {};
     991struct  Action;
     992
     993void ^?{}   (Executer & mutex this);
     994void execute(Executer & mutex this, const Action & );
     995void run    (Executer & mutex this) {
     996        while(true) {
     997                   waitfor(execute, this);
     998                or waitfor(^?{}   , this) {
     999                        break;
     1000                }
     1001        }
     1002}
     1003\end{cfacode}
     1004\caption{Example of an executor which executes action in series until the destructor is called.}
     1005\label{lst:dtor-order}
     1006\end{figure}
     1007For 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. Switching the semantic meaning introduces an idiomatic way to terminate a task and/or wait for its termination via destruction.
  • doc/proposals/concurrency/text/intro.tex

    r78315272 r3f7e12cb  
    33% ======================================================================
    44
    5 This proposal provides a minimal concurrency API that is simple, efficient and can be reused to build higher-level features. The simplest possible concurrency system is a thread and a lock but this low-level approach is hard to master. An easier approach for users is to support higher-level constructs as the basis of the concurrency, in \CFA. Indeed, for highly productive parallel programming, high-level approaches are much more popular~\cite{HPP:Study}. Examples are task based, message passing and implicit threading. Therefore a high-level approach is adapted in \CFA
     5This thesis provides a minimal concurrency \acrshort{api} that is simple, efficient and can be reused to build higher-level features. The simplest possible concurrency system is a thread and a lock but this low-level approach is hard to master. An easier approach for users is to support higher-level constructs as the basis of concurrency. Indeed, for highly productive concurrent programming, high-level approaches are much more popular~\cite{HPP:Study}. Examples are task based, message passing and implicit threading. The high-level approach and its minimal \acrshort{api} are tested in a dialect of C, call \CFA. Furthermore, the proposed \acrshort{api} doubles as an early definition of the \CFA language and library. This thesis also comes with an implementation of the concurrency library for \CFA as well as all the required language features added to the source-to-source translator.
    66
    7 There 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 users. While these two concepts are often combined, they are in fact distinct concepts that require different tools~\cite{Buhr05a}. Concurrency tools need to handle mutual exclusion and synchronization, while parallelism tools are about performance, cost and resource utilization.
     7There 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. While these two concepts are often combined, they are in fact distinct, requiring different tools~\cite{Buhr05a}. Concurrency tools need to handle mutual exclusion and synchronization, while parallelism tools are about performance, cost and resource utilization.
  • doc/proposals/concurrency/text/parallelism.tex

    r78315272 r3f7e12cb  
    1111\section{Paradigm}
    1212\subsection{User-level threads}
    13 A direct improvement on the \gls{kthread} approach is to use \glspl{uthread}. These threads offer most of the same features that the operating system already provide but can be used on a much larger scale. This approach is the most powerfull solution as it allows all the features of multi-threading, while removing several of the more expensives costs of using kernel threads. The down side is that almost none of the low-level threading problems are hidden, users still have to think about data races, deadlocks and synchronization issues. These issues can be somewhat alleviated by a concurrency toolkit with strong garantees but the parallelism toolkit offers very little to reduce complexity in itself.
     13A direct improvement on the \gls{kthread} approach is to use \glspl{uthread}. These threads offer most of the same features that the operating system already provide but can be used on a much larger scale. This approach is the most powerfull solution as it allows all the features of multi-threading, while removing several of the more expensive costs of kernel threads. The down side is that almost none of the low-level threading problems are hidden; users still have to think about data races, deadlocks and synchronization issues. These issues can be somewhat alleviated by a concurrency toolkit with strong garantees but the parallelism toolkit offers very little to reduce complexity in itself.
    1414
    1515Examples of languages that support \glspl{uthread} are Erlang~\cite{Erlang} and \uC~\cite{uC++book}.
    1616
    1717\subsection{Fibers : user-level threads without preemption}
    18 A popular varient of \glspl{uthread} is what is often reffered to as \glspl{fiber}. However, \glspl{fiber} do not present meaningful semantical differences with \glspl{uthread}. Advocates of \glspl{fiber} list their high performance and ease of implementation as majors strenghts of \glspl{fiber} but the performance difference between \glspl{uthread} and \glspl{fiber} is controversial and the ease of implementation, while true, is a weak argument in the context of language design. Therefore this proposal largely ignore fibers.
     18A popular varient of \glspl{uthread} is what is often refered to as \glspl{fiber}. However, \glspl{fiber} do not present meaningful semantical differences with \glspl{uthread}. The significant difference between \glspl{uthread} and \glspl{fiber} is the lack of \gls{preemption} in the later one. Advocates of \glspl{fiber} list their high performance and ease of implementation as majors strenghts of \glspl{fiber} but the performance difference between \glspl{uthread} and \glspl{fiber} is controversial, and the ease of implementation, while true, is a weak argument in the context of language design. Therefore this proposal largely ignores fibers.
    1919
    2020An example of a language that uses fibers is Go~\cite{Go}
    2121
    2222\subsection{Jobs and thread pools}
    23 The approach on the opposite end of the spectrum is to base parallelism on \glspl{pool}. Indeed, \glspl{pool} offer limited flexibility but at the benefit of a simpler user interface. In \gls{pool} based systems, users express parallelism as units of work and a dependency graph (either explicit or implicit) that tie them together. This approach means users need not worry about concurrency but significantly limits the interaction that can occur among jobs. Indeed, any \gls{job} that blocks also blocks the underlying worker, which effectively means the CPU utilization, and therefore throughput, suffers noticeably. It can be argued that a solution to this problem is to use more workers than available cores. However, unless the number of jobs and the number of workers are comparable, having a significant amount of blocked jobs always results in idles cores.
     23An approach on the opposite end of the spectrum is to base parallelism on \glspl{pool}. Indeed, \glspl{pool} offer limited flexibility but at the benefit of a simpler user interface. In \gls{pool} based systems, users express parallelism as units of work, called jobs, and a dependency graph (either explicit or implicit) that tie them together. This approach means users need not worry about concurrency but significantly limit the interaction that can occur among jobs. Indeed, any \gls{job} that blocks also blocks the underlying worker, which effectively means the CPU utilization, and therefore throughput, suffers noticeably. It can be argued that a solution to this problem is to use more workers than available cores. However, unless the number of jobs and the number of workers are comparable, having a significant amount of blocked jobs always results in idles cores.
    2424
    2525The gold standard of this implementation is Intel's TBB library~\cite{TBB}.
    2626
    2727\subsection{Paradigm performance}
    28 While the choice between the three paradigms listed above may have significant performance implication, it is difficult to pindown the performance implications of chosing a model at the language level. Indeed, in many situations one of these paradigms may show better performance but it all strongly depends on the workload. Having a large amount of mostly independent units of work to execute almost guarantess that the \gls{pool} based system has the best performance thanks to the lower memory overhead. However, interactions between jobs can easily exacerbate contention. User-level threads allow fine-grain context switching, which results in better resource utilisation, but context switches will be more expansive and the extra control means users need to tweak more variables to get the desired performance. Furthermore, if the units of uninterrupted work are large enough the paradigm choice is largely amorticised by the actual work done.
     28While the choice between the three paradigms listed above may have significant performance implication, it is difficult to pindown the performance implications of chosing a model at the language level. Indeed, in many situations one of these paradigms may show better performance but it all strongly depends on the workload. Having a large amount of mostly independent units of work to execute almost guarantess that the \gls{pool} based system has the best performance thanks to the lower memory overhead (i.e., no thread stack per job). However, interactions among jobs can easily exacerbate contention. User-level threads allow fine-grain context switching, which results in better resource utilisation, but a context switch is more expensive and the extra control means users need to tweak more variables to get the desired performance. Finally, if the units of uninterrupted work are large enough the paradigm choice is largely amortised by the actual work done.
    2929
    30 \newpage
    31 \TODO
    32 \subsection{The \protect\CFA\ Kernel : Processors, Clusters and Threads}\label{kernel}
     30\section{The \protect\CFA\ Kernel : Processors, Clusters and Threads}\label{kernel}
    3331
     32\Glspl{cfacluster} have not been fully implmented in the context of this thesis, currently \CFA only supports one \gls{cfacluster}, the initial one. The objective of \gls{cfacluster} is to group \gls{kthread} with identical settings together. \Glspl{uthread} can be scheduled on a \glspl{kthread} of a given \gls{cfacluster}, allowing organization between \glspl{kthread} and \glspl{uthread}. It is important that \glspl{kthread} belonging to a same \glspl{cfacluster} have homogenous settings, otherwise migrating a \gls{uthread} from one \gls{kthread} to the other can cause issues.
     33
     34\subsection{Future Work: Machine setup}\label{machine}
     35While this was not done in the context of this thesis, another important aspect of clusters is affinity. While many common desktop and laptop PCs have homogeneous CPUs, other devices often have more heteregenous setups. For example, system using \acrshort{numa} configurations may benefit from users being able to tie clusters and/or kernel threads to certains CPU cores. OS support for CPU affinity is now common \cit, which means it is both possible and desirable for \CFA to offer an abstraction mechanism for portable CPU affinity.
    3436
    3537\subsection{Paradigms}\label{cfaparadigms}
    36 Given these building blocks we can then reproduce the all three of the popular paradigms. Indeed, we get \glspl{uthread} as the default paradigm in \CFA. However, disabling \glspl{preemption} on the \gls{cfacluster} means \glspl{cfathread} effectively become \glspl{fiber}. Since several \glspl{cfacluster} with different scheduling policy can coexist in the same application, this allows \glspl{fiber} and \glspl{uthread} to coexist in the runtime of an application.
    37 
    38 % \subsection{High-level options}\label{tasks}
    39 %
    40 % \subsubsection{Thread interface}
    41 % constructors destructors
    42 %       initializer lists
    43 % monitors
    44 %
    45 % \subsubsection{Futures}
    46 %
    47 % \subsubsection{Implicit threading}
    48 % Finally, simpler applications can benefit greatly from having implicit parallelism. That is, parallelism that does not rely on the user to write concurrency. This type of parallelism can be achieved both at the language level and at the system level.
    49 %
    50 % \begin{center}
    51 % \begin{tabular}[t]{|c|c|c|}
    52 % Sequential & System Parallel & Language Parallel \\
    53 % \begin{lstlisting}
    54 % void big_sum(int* a, int* b,
    55 %                int* out,
    56 %                size_t length)
    57 % {
    58 %       for(int i = 0; i < length; ++i ) {
    59 %               out[i] = a[i] + b[i];
    60 %       }
    61 % }
    62 %
    63 %
    64 %
    65 %
    66 %
    67 % int* a[10000];
    68 % int* b[10000];
    69 % int* c[10000];
    70 % //... fill in a and b ...
    71 % big_sum(a, b, c, 10000);
    72 % \end{lstlisting} &\begin{lstlisting}
    73 % void big_sum(int* a, int* b,
    74 %                int* out,
    75 %                size_t length)
    76 % {
    77 %       range ar(a, a + length);
    78 %       range br(b, b + length);
    79 %       range or(out, out + length);
    80 %       parfor( ai, bi, oi,
    81 %       [](int* ai, int* bi, int* oi) {
    82 %               oi = ai + bi;
    83 %       });
    84 % }
    85 %
    86 % int* a[10000];
    87 % int* b[10000];
    88 % int* c[10000];
    89 % //... fill in a and b ...
    90 % big_sum(a, b, c, 10000);
    91 % \end{lstlisting}&\begin{lstlisting}
    92 % void big_sum(int* a, int* b,
    93 %                int* out,
    94 %                size_t length)
    95 % {
    96 %       for (ai, bi, oi) in (a, b, out) {
    97 %               oi = ai + bi;
    98 %       }
    99 % }
    100 %
    101 %
    102 %
    103 %
    104 %
    105 % int* a[10000];
    106 % int* b[10000];
    107 % int* c[10000];
    108 % //... fill in a and b ...
    109 % big_sum(a, b, c, 10000);
    110 % \end{lstlisting}
    111 % \end{tabular}
    112 % \end{center}
    113 %
    114 % \subsection{Machine setup}\label{machine}
    115 % Threads are all good and well but wee still some OS support to fully utilize available hardware.
    116 %
    117 % \textbf{\large{Work in progress...}} Do wee need something beyond specifying the number of kernel threads?
     38Given these building blocks, it is possible to reproduce all three of the popular paradigms. Indeed, \glspl{uthread} is the default paradigm in \CFA. However, disabling \gls{preemption} on the \gls{cfacluster} means \glspl{cfathread} effectively become \glspl{fiber}. Since several \glspl{cfacluster} with different scheduling policy can coexist in the same application, this allows \glspl{fiber} and \glspl{uthread} to coexist in the runtime of an application. Finally, it is possible to build executors for thread pools from \glspl{uthread} or \glspl{fiber}.
  • doc/proposals/concurrency/thesis.tex

    r78315272 r3f7e12cb  
    11% requires tex packages: texlive-base texlive-latex-base tex-common texlive-humanities texlive-latex-extra texlive-fonts-recommended
    22
    3 % inline code ©...© (copyright symbol) emacs: C-q M-)
    4 % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
    5 % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    6 % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
    7 % LaTex escape §...§ (section symbol) emacs: C-q M-'
    8 % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
     3% inline code �...� (copyright symbol) emacs: C-q M-)
     4% red highlighting �...� (registered trademark symbol) emacs: C-q M-.
     5% blue highlighting �...� (sharp s symbol) emacs: C-q M-_
     6% green highlighting �...� (cent symbol) emacs: C-q M-"
     7% LaTex escape �...� (section symbol) emacs: C-q M-'
     8% keyword escape �...� (pilcrow symbol) emacs: C-q M-^
    99% math escape $...$ (dollar symbol)
    1010
     
    2727\usepackage{multicol}
    2828\usepackage[acronym]{glossaries}
    29 \usepackage{varioref}   
     29\usepackage{varioref}
    3030\usepackage{listings}                                           % format program code
    3131\usepackage[flushmargin]{footmisc}                              % support label/reference in footnote
     
    3535\usepackage[pagewise]{lineno}
    3636\usepackage{fancyhdr}
     37\usepackage{float}
    3738\renewcommand{\linenumberfont}{\scriptsize\sffamily}
     39\usepackage{siunitx}
     40\sisetup{ binary-units=true }
    3841\input{style}                                                   % bespoke macros used in the document
    3942\usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
     
    7073%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    7174
    72 \setcounter{secnumdepth}{3}                           % number subsubsections
    73 \setcounter{tocdepth}{3}                              % subsubsections in table of contents
     75\setcounter{secnumdepth}{2}                           % number subsubsections
     76\setcounter{tocdepth}{2}                              % subsubsections in table of contents
    7477% \linenumbers                                          % comment out to turn off line numbering
    7578\makeindex
     
    103106\input{parallelism}
    104107
    105 \chapter{Putting it all together}
     108\input{internals}
     109
     110\input{together}
     111
     112\input{results}
     113
     114\input{future}
    106115
    107116\chapter{Conclusion}
    108 
    109 \chapter{Future work}
    110 Concurrency and parallelism is still a very active field that strongly benefits from hardware advances. As such certain features that aren't necessarily mature enough in their current state could become relevant in the lifetime of \CFA.
    111 \subsection{Transactions}
    112117
    113118\section*{Acknowledgements}
  • doc/proposals/concurrency/version

    r78315272 r3f7e12cb  
    1 0.9.180
     10.11.47
Note: See TracChangeset for help on using the changeset viewer.