Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/colby_parsons_MMAth/text/waituntil.tex

    rf496046 r000d68f  
    163163
    164164Another example of programming-language \gls{synch_multiplex} is Go using a @select@ statement with channels~\cite{go:selectref}.
    165 Figure~\ref{l:BB_Go} shows the outline of a bounded buffer implemented with a Go routine.
     165Figure~\ref{l:BB_Go} shows the outline of a bounded buffer administrator implemented with a Go routine.
    166166Here two channels are used for inserting and removing by client producers and consumers, respectively.
    167 (The @term@ and @stop@ channels are used to synchronize with the program main.)
     167(The @done@ channel is used to synchronize with the program main.)
    168168Go's @select@ has the same exclusive-or semantics as the ALT primitive from Occam and associated code blocks for each clause like ALT and Ada.
    169169However, unlike Ada and ALT, Go does not provide guards for the \lstinline[language=go]{case} clauses of the \lstinline[language=go]{select}.
     170As such, the exponential blowup can be seen comparing Go and \uC in Figure~\label{f:AdaMultiplexing}.
    170171Go also provides a timeout via a channel and a @default@ clause like Ada @else@ for asynchronous multiplexing.
    171172
     
    175176\begin{lrbox}{\myboxA}
    176177\begin{lstlisting}[language=go,literate=]
     178insert := make( chan int )
     179remove := make( chan * int )
     180buffer := make( chan int Size )
     181done := make( chan int )
     182count := 0
     183func in_buf( int val ) {
     184    buffer <- val
     185    count++
     186}
     187func out_buf( int * ptr ) {
     188    *ptr := <-buffer
     189    count--
     190}
     191func BoundedBuffer {
     192    L: for {
     193        if ( count < Size && count > 0 ) {
     194            select { // wait for message
     195                case i := <- insert: in_buf( i )
     196                case p := <- remove: out_buf( p )
     197                case <- done: break L
     198            }
     199        } else if ( count < Size ) {
     200            select { // wait for message
     201                case i := <- insert: in_buf( i )
     202                case <- done: break L
     203            }
     204        } else ( count > 0 ) {
     205            select { // wait for message
     206                case p := <- remove: out_buf( p )
     207                case <- done: break L;
     208            }
     209        }
     210    }
     211    done <- 0
     212}
    177213func main() {
    178         insert := make( chan int, Size )
    179         remove := make( chan int, Size )
    180         term := make( chan string )
    181         finish := make( chan string )
    182 
    183         buf := func() {
    184                 L: for {
    185                         select { // wait for message
    186                           case i = <- buffer:
    187                           case <- term: break L
    188                         }
    189                         remove <- i;
    190                 }
    191                 finish <- "STOP" // completion
    192         }
    193         go buf() // start thread in buf
     214        go BoundedBuffer() // start administrator
    194215}
    195216
     
    203224\begin{lstlisting}[language=uC++=]
    204225_Task BoundedBuffer {
    205         ... // buffer declarations
    206         int count = 0;
     226        int * buffer;
     227        int front = back = count = 0;
    207228  public:
     229    // ... constructor implementation
    208230        void insert( int elem ) {
    209                 ... // add to buffer
     231                buffer[front] = elem;
     232        front = ( front + 1 ) % Size;
    210233                count += 1;
    211234        }
    212235        int remove() {
    213                 ... // remove and return from buffer
     236                int ret = buffer[back];
     237        back = ( back + 1 ) % Size;
    214238                count -= 1;
     239        return ret;
    215240        }
    216241  private:
     
    240265The @_Select@ statement extends the ALT/Go @select@ by offering both @and@ and @or@ semantics, which can be used together in the same statement.
    241266Both @_Accept@ and @_Select@ statements provide guards for multiplexing clauses, as well as, timeout, and @else@ clauses.
     267Figure~\ref{l:BB_uC++} shows the outline of a bounded buffer administrator implemented with \uC @_Accept@ statements.
    242268
    243269There are other languages that provide \gls{synch_multiplex}, including Rust's @select!@ over futures~\cite{rust:select}, OCaml's @select@ over channels~\cite{ocaml:channel}, and C++14's @when_any@ over futures~\cite{cpp:whenany}.
     
    741767                when_conditions[node] = true;
    742768
    743 if ( any when_conditions[node] == true ) {
    744 
    745 select_nodes nodes[N];                                                                  $\C{// declare N select nodes}$
    746 try {
    747     // ... set statuses for nodes with when_conditions[node] == false ...
    748 
    749     for ( node in nodes )                                                               $\C{// register nodes}$
    750         if ( when_conditions[node] )
    751             register_select( resource, node );
    752 
    753     while ( !check_completion( nodes ) ) {      $\C{// check predicate}$
    754         // block
    755         for ( resource in waituntil statement ) {       $\C{// run true code blocks}$
    756             if ( check_completion( nodes ) ) break;
    757             if ( resource is avail )
    758                 try {
    759                     if( on_selected( resource ) )       $\C{// conditionally run block}$
    760                         run code block
    761                 } finally                                                       $\C{// for exception safety}$
    762                     unregister_select( resource, node ); $\C{// immediate unregister}$
     769if ( any when_conditions[node] are true ) {
     770    select_nodes nodes[N];                                                                      $\C{// declare N select nodes}$
     771    try {
     772        // ... set statuses for nodes with when_conditions[node] == false ...
     773
     774        for ( node in nodes )                                                           $\C{// register nodes}$
     775            if ( when_conditions[node] )
     776                register_select( resource, node );
     777
     778        while ( !check_completion( nodes ) ) {  $\C{// check predicate}$
     779            // block
     780            for ( resource in waituntil statement ) {   $\C{// run true code blocks}$
     781                if ( check_completion( nodes ) ) break;
     782                if ( resource is avail )
     783                    try {
     784                        if( on_selected( resource ) )   $\C{// conditionally run block}$
     785                            run code block
     786                    } finally                                                   $\C{// for exception safety}$
     787                        unregister_select( resource, node ); $\C{// immediate unregister}$
     788            }
    763789        }
     790    } finally {                                                                                 $\C{// for exception safety}$
     791        for ( registered nodes in nodes )                                       $\C{// deregister nodes}$
     792            if ( when_conditions[node] && unregister_select( resource, node )
     793                    && on_selected( resource ) )
     794                run code block                                                  $\C{// run code block upon unregister}\CRT$
    764795    }
    765 } finally {                                                                                     $\C{// for exception safety}$
    766         for ( registered nodes in nodes )                                       $\C{// deregister nodes}$
    767                 if ( when_conditions[node] && unregister_select( resource, node )
    768                                 && on_selected( resource ) )
    769                         run code block                                                  $\C{// run code block upon unregister}\CRT$
    770 }
    771 
    772796}
    773797\end{cfa}
     
    914938\setlength{\tabcolsep}{5pt}
    915939
    916 \caption{Throughput (channel operations per second) of \CFA and Go for a pathologically case for contention in Go's select implementation}
     940\caption{Throughput (channel operations per second) of \CFA and Go in a pathological case for contention in Go's select implementation}
    917941\label{t:pathGo}
    918942\begin{tabular}{r|r|r}
Note: See TracChangeset for help on using the changeset viewer.