Changes in / [d5a52cc:1393df07]


Ignore:
Files:
9 deleted
27 edited

Legend:

Unmodified
Added
Removed
  • .gitignore

    rd5a52cc r1393df07  
    2525include
    2626share
    27 *.class
    2827
    2928# src executables, for lib and bin
  • doc/refrat/refrat.tex

    rd5a52cc r1393df07  
    1111%% Created On       : Wed Apr  6 14:52:25 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Tue Aug 15 18:46:31 2017
    14 %% Update Count     : 106
     13%% Last Modified On : Sun Aug  6 10:25:31 2017
     14%% Update Count     : 105
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    492492
    493493\begin{rationale}
    494 The use of ``©?©'' in identifiers means that some C programs are not \CFA programs.
    495 For instance, the sequence of characters ``©(i < 0)?--i:i©'' is legal in a C program, but a \CFA compiler detects a syntax error because it treats ``©?--©'' as an identifier, not as the two tokens ``©?©'' and ``©--©''.
     494The use of ``©?©'' in identifiers means that some C programs are not \CFA programs.  For instance, the sequence of characters ``©(i < 0)?--i:i©'' is legal in a C program, but a
     495\CFA compiler detects a syntax error because it treats ``©?--©'' as an identifier, not as the two tokens ``©?©'' and ``©--©''.
    496496\end{rationale}
    497497
  • doc/user/user.tex

    rd5a52cc r1393df07  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Mon Nov 27 18:09:59 2017
    14 %% Update Count     : 3143
     13%% Last Modified On : Sun Aug  6 10:24:21 2017
     14%% Update Count     : 3036
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    5959\CFAStyle                                                                                               % use default CFA format-style
    6060\lstnewenvironment{C++}[1][]                            % use C++ style
    61 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}
     61{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®}#1}}
    6262{}
    6363
     
    777777  case 7:
    778778        ...
    779         ®break®                                         §\C{// explicit end of switch (redundant)
     779        ®break®                                         §\C{// redundant explicit end of switch
    780780  default:
    781781        j = 3;
     
    806806                ®int k = 0;®                    §\C{// allowed at different nesting levels}§
    807807                ...
    808           ®case 2:®                                     §\C{// disallow case in nested statements}§
    809808        }
    810809  ...
     
    963962\end{cfa}
    964963
    965 The components in the "with" clause
    966 
    967   with a, b, c { ... }
    968 
    969 serve 2 purposes: each component provides a type and object. The type must be a
    970 structure type. Enumerations are already opened, and I think a union is opened
    971 to some extent, too. (Or is that just unnamed unions?) The object is the target
    972 that the naked structure-fields apply to. The components are open in "parallel"
    973 at the scope of the "with" clause/statement, so opening "a" does not affect
    974 opening "b", etc. This semantic is different from Pascal, which nests the
    975 openings.
    976 
    977 Having said the above, it seems reasonable to allow a "with" component to be an
    978 expression. The type is the static expression-type and the object is the result
    979 of the expression. Again, the type must be an aggregate. Expressions require
    980 parenthesis around the components.
    981 
    982   with( a, b, c ) { ... }
    983 
    984 Does this now make sense?
    985 
    986 Having written more CFA code, it is becoming clear to me that I *really* want
    987 the "with" to be implemented because I hate having to type all those object
    988 names for fields. It's a great way to drive people away from the language.
    989 
    990964
    991965\section{Exception Handling}
     
    1003977try {
    1004978        f(...);
    1005 } catch( E e ; §boolean-predicate§ ) {                  §\C[8cm]{// termination handler}§
     979} catch( E e : §boolean-predicate§ ) {                  §\C[8cm]{// termination handler}§
    1006980        // recover and continue
    1007 } catchResume( E e ; §boolean-predicate§ ) {    §\C{// resumption handler}\CRT§
     981} catchResume( E e : §boolean-predicate§ ) {    §\C{// resumption handler}\CRT§
    1008982        // repair and return
    1009983} finally {
     
    18981872\end{cfa}
    18991873This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa).
    1900 Like C, it is possible to declare multiple routine-prototypes in a single declaration, where the return type is distributed across \emph{all} routine names in the declaration list (see~\VRef{s:Declarations}), \eg:
    1901 \begin{cfa}
    1902 C :             const double bar1(), bar2( int ), bar3( double );
    1903 §\CFA§: [const double] foo(), foo( int ), foo( double ) { return 3.0; }
    1904 \end{cfa}
    1905 \CFA allows the last routine in the list to define its body.
    1906 
     1874It is possible to declare multiple routine-prototypes in a single declaration, but the entire type specification is distributed across \emph{all} routine names in the declaration list (see~\VRef{s:Declarations}), \eg:
     1875\begin{quote2}
     1876\begin{tabular}{@{}l@{\hspace{3em}}l@{}}
     1877\multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
     1878\begin{cfa}
     1879[ int ] f( int ), g;
     1880\end{cfa}
     1881&
     1882\begin{cfa}
     1883int f( int ), g( int );
     1884\end{cfa}
     1885\end{tabular}
     1886\end{quote2}
    19071887Declaration qualifiers can only appear at the start of a \CFA routine declaration,\footref{StorageClassSpecifier} \eg:
    19081888\begin{cfa}
     
    22552235\label{s:MRV_Functions}
    22562236
    2257 In C and most programming languages, functions return at most one value;
    2258 however, many operations have multiple outcomes, some exceptional (see~\VRef{s:ExceptionHandling}).
     2237In standard C, functions can return at most one value.
    22592238To emulate functions with multiple return values, \emph{\Index{aggregation}} and/or \emph{\Index{aliasing}} is used.
    2260 
    2261 In the former approach, a record type is created combining all of the return values.
    2262 For example, consider C's \Indexc{div} function, which returns the quotient and remainder for a division of an integer value.
    2263 \begin{cfa}
    2264 typedef struct { int quot, rem; } div_t;        §\C[7cm]{// from include stdlib.h}§
    2265 div_t div( int num, int den );
    2266 div_t qr = div( 13, 5 );                                        §\C{// return quotient/remainder aggregate}§
    2267 printf( "%d %d\n", qr.quot, qr.rem );           §\C{// print quotient/remainder}§
    2268 \end{cfa}
    2269 This approach requires a name for the return type and fields, where \Index{naming} is a common programming-language issue.
    2270 That is, naming creates an association that must be managed when reading and writing code.
    2271 While effective when used sparingly, this approach does not scale when functions need to return multiple combinations of types.
    2272 
    2273 In the latter approach, additional return values are passed as pointer parameters.
    2274 A pointer parameter is assigned inside the routine to emulate a return.
    2275 For example, consider C's \Indexc{modf} function, which returns the integral and fractional part of a floating-point value.
    2276 \begin{cfa}
    2277 double modf( double x, double * i );            §\C{// from include math.h}§
    2278 double intp, frac = modf( 13.5, &intp );        §\C{// return integral and fractional components}§
    2279 printf( "%g %g\n", intp, frac );                        §\C{// print integral/fractional components}§
    2280 \end{cfa}
    2281 This approach requires allocating storage for the return values, which complicates the call site with a sequence of variable declarations leading to the call.
    2282 Also, while a disciplined use of ©const© can give clues about whether a pointer parameter is used as an \Index{out parameter}, it is not obvious from the routine signature whether the callee expects such a parameter to be initialized before the call.
    2283 Furthermore, while many C routines that accept pointers are safe for a ©NULL© argument, there are many C routines that are not null-safe.
    2284 Finally, C does not provide a mechanism to state that a parameter is going to be used as an additional return value, which makes the job of ensuring that a value is returned more difficult for the compiler.
     2239In the former situation, the function designer creates a record type that combines all of the return values into a single type.
     2240For example, consider a function returning the most frequently occurring letter in a string, and its frequency.
     2241This example is complex enough to illustrate that an array is insufficient, since arrays are homogeneous, and demonstrates a potential pitfall that exists with aliasing.
     2242\begin{cfa}
     2243struct mf_ret {
     2244        int freq;
     2245        char ch;
     2246};
     2247
     2248struct mf_ret most_frequent(const char * str) {
     2249        char freqs [26] = { 0 };
     2250        struct mf_ret ret = { 0, 'a' };
     2251        for (int i = 0; str[i] != '\0'; ++i) {
     2252                if (isalpha(str[i])) {        // only count letters
     2253                        int ch = tolower(str[i]);   // convert to lower case
     2254                        int idx = ch-'a';
     2255                        if (++freqs[idx] > ret.freq) {  // update on new max
     2256                          ret.freq = freqs[idx];
     2257                          ret.ch = ch;
     2258                        }
     2259                }
     2260        }
     2261        return ret;
     2262}
     2263
     2264const char * str = "hello world";
     2265struct mf_ret ret = most_frequent(str);
     2266printf("%s -- %d %c\n", str, ret.freq, ret.ch);
     2267\end{cfa}
     2268Of note, the designer must come up with a name for the return type and for each of its fields.
     2269Unnecessary naming is a common programming language issue, introducing verbosity and a complication of the user's mental model.
     2270That is, adding another named type creates another association in the programmer's mind that needs to be kept track of when reading and writing code.
     2271As such, this technique is effective when used sparingly, but can quickly get out of hand if many functions need to return different combinations of types.
     2272
     2273In the latter approach, the designer simulates multiple return values by passing the additional return values as pointer parameters.
     2274The pointer parameters are assigned inside of the routine body to emulate a return.
     2275Using the same example,
     2276\begin{cfa}
     2277int most_frequent(const char * str, char * ret_ch) {
     2278        char freqs [26] = { 0 };
     2279        int ret_freq = 0;
     2280        for (int i = 0; str[i] != '\0'; ++i) {
     2281                if (isalpha(str[i])) {        // only count letters
     2282                        int ch = tolower(str[i]);   // convert to lower case
     2283                        int idx = ch-'a';
     2284                        if (++freqs[idx] > ret_freq) {  // update on new max
     2285                          ret_freq = freqs[idx];
     2286                          *ret_ch = ch;   // assign to out parameter
     2287                        }
     2288                }
     2289        }
     2290        return ret_freq;  // only one value returned directly
     2291}
     2292
     2293const char * str = "hello world";
     2294char ch;                            // pre-allocate return value
     2295int freq = most_frequent(str, &ch); // pass return value as out parameter
     2296printf("%s -- %d %c\n", str, freq, ch);
     2297\end{cfa}
     2298Notably, using this approach, the caller is directly responsible for allocating storage for the additional temporary return values, which complicates the call site with a sequence of variable declarations leading up to the call.
     2299Also, while a disciplined use of ©const© can give clues about whether a pointer parameter is going to be used as an out parameter, it is not immediately obvious from only the routine signature whether the callee expects such a parameter to be initialized before the call.
     2300Furthermore, while many C routines that accept pointers are designed so that it is safe to pass ©NULL© as a parameter, there are many C routines that are not null-safe.
     2301On a related note, C does not provide a standard mechanism to state that a parameter is going to be used as an additional return value, which makes the job of ensuring that a value is returned more difficult for the compiler.
     2302Interestingly, there is a subtle bug in the previous example, in that ©ret_ch© is never assigned for a string that does not contain any letters, which can lead to undefined behaviour.
     2303In this particular case, it turns out that the frequency return value also doubles as an error code, where a frequency of 0 means the character return value should be ignored.
    22852304Still, not every routine with multiple return values should be required to return an error code, and error codes are easily ignored, so this is not a satisfying solution.
    22862305As with the previous approach, this technique can simulate multiple return values, but in practice it is verbose and error prone.
    22872306
    2288 \CFA allows functions to return multiple values by extending the function declaration syntax.
     2307In \CFA, functions can be declared to return multiple values with an extension to the function declaration syntax.
    22892308Multiple return values are declared as a comma-separated list of types in square brackets in the same location that the return type appears in standard C function declarations.
    2290 \begin{cfa}
    2291 [ char, int, double ] f( ... );
    2292 \end{cfa}
    22932309The ability to return multiple values from a function requires a new syntax for the return statement.
    22942310For consistency, the return statement in \CFA accepts a comma-separated list of expressions in square brackets.
    2295 \begin{cfa}
    2296 return [ c, i, d ];
    2297 \end{cfa}
    2298 The expression resolution ensures the correct form is used depending on the values being returned and the return type of the current function.
     2311The expression resolution phase of the \CFA translator ensures that the correct form is used depending on the values being returned and the return type of the current function.
    22992312A multiple-returning function with return type ©T© can return any expression that is implicitly convertible to ©T©.
    2300 
    2301 A common use of a function's output is input to another function.
    2302 \CFA allows this case, without any new syntax;
    2303 a multiple-returning function can be used in any of the contexts where an expression is allowed.
    2304 When a function call is passed as an argument to another call, the best match of actual arguments to formal parameters is evaluated given all possible expression interpretations in the current scope.
    2305 \begin{cfa}
    2306 void g( int, int );                                                     §\C{// 1}§
    2307 void g( double, double );                                       §\C{// 2}§
    2308 g( div( 13, 5 ) );                                                      §\C{// select 1}§
    2309 g( modf( 13.5 ) );                                                      §\C{// select 2}§
    2310 \end{cfa}
    2311 In this case, there are two overloaded ©g© routines.
    2312 Both calls to ©g© expect two arguments that are matched by the two return values from ©div© and ©modf©. respectively, which are fed directly to the first and second parameters of ©g©.
    2313 As well, both calls to ©g© have exact type matches for the two different versions of ©g©, so these exact matches are chosen.
    2314 When type matches are not exact, conversions are used to find a best match.
    2315 
    2316 The previous examples can be rewritten passing the multiple returned-values directly to the ©printf© function call.
    2317 \begin{cfa}
    2318 [ int, int ] div( int x, int y );                       §\C{// from include stdlib}§
    2319 printf( "%d %d\n", div( 13, 5 ) );                      §\C{// print quotient/remainder}§
    2320 
    2321 [ double, double ] modf( double x );            §\C{// from include math}§
    2322 printf( "%g %g\n", modf( 13.5 ) );                      §\C{// print integral/fractional components}§
    2323 \end{cfa}
    2324 This approach provides the benefits of compile-time checking for appropriate return statements as in aggregation, but without the required verbosity of declaring a new named type.
    2325 
    2326 Finally, the addition of multiple-return-value functions necessitates a syntax for retaining the multiple values at the call-site versus their temporary existence during a call.
     2313Using the running example, the ©most_frequent© function can be written using multiple return values as such,
     2314\begin{cfa}
     2315[int, char] most_frequent(const char * str) {
     2316        char freqs [26] = { 0 };
     2317        int ret_freq = 0;
     2318        char ret_ch = 'a';  // arbitrary default value for consistent results
     2319        for (int i = 0; str[i] != '\0'; ++i) {
     2320                if (isalpha(str[i])) {        // only count letters
     2321                        int ch = tolower(str[i]);   // convert to lower case
     2322                        int idx = ch-'a';
     2323                        if (++freqs[idx] > ret_freq) {  // update on new max
     2324                          ret_freq = freqs[idx];
     2325                          ret_ch = ch;
     2326                        }
     2327                }
     2328        }
     2329        return [ret_freq, ret_ch];
     2330}
     2331\end{cfa}
     2332This approach provides the benefits of compile-time checking for appropriate return statements as in aggregation, but without the required verbosity of declaring a new named type, which precludes the bug seen with out-parameters.
     2333
     2334The addition of multiple-return-value functions necessitates a syntax for accepting multiple values at the call-site.
    23272335The simplest mechanism for retaining a return value in C is variable assignment.
    2328 By assigning the multiple return-values into multiple variables, the values can be retrieved later.
     2336By assigning the return value into a variable, its value can be retrieved later at any point in the program.
    23292337As such, \CFA allows assigning multiple values from a function into multiple variables, using a square-bracketed list of lvalue expressions on the left side.
    23302338\begin{cfa}
    2331 int quot, rem;
    2332 [ quot, rem ] = div( 13, 5 );                           §\C{// assign multiple variables}§
    2333 printf( "%d %d\n", quot, rem );                         §\C{// print quotient/remainder}\CRT§
    2334 \end{cfa}
    2335 Here, the multiple return-values are matched in much the same way as passing multiple return-values to multiple parameters in a call.
    2336 
    2337 
    2338 \subsection{Expressions}
    2339 
     2339const char * str = "hello world";
     2340int freq;
     2341char ch;
     2342[freq, ch] = most_frequent(str);  // assign into multiple variables
     2343printf("%s -- %d %c\n", str, freq, ch);
     2344\end{cfa}
     2345It is also common to use a function's output as the input to another function.
     2346\CFA also allows this case, without any new syntax.
     2347When a function call is passed as an argument to another call, the expression resolver attempts to find the best match of actual arguments to formal parameters given all of the possible expression interpretations in the current scope \cite{Bilson03}.
     2348For example,
     2349\begin{cfa}
     2350void process(int);       // (1)
     2351void process(char);      // (2)
     2352void process(int, char); // (3)
     2353void process(char, int); // (4)
     2354
     2355process(most_frequent("hello world"));  // selects (3)
     2356\end{cfa}
     2357In this case, there is only one option for a function named ©most_frequent© that takes a string as input.
     2358This function returns two values, one ©int© and one ©char©.
     2359There are four options for a function named ©process©, but only two that accept two arguments, and of those the best match is (3), which is also an exact match.
     2360This expression first calls ©most_frequent("hello world")©, which produces the values ©3© and ©'l'©, which are fed directly to the first and second parameters of (3), respectively.
     2361
     2362\section{Tuple Expressions}
    23402363Multiple-return-value functions provide \CFA with a new syntax for expressing a combination of expressions in the return statement and a combination of types in a function signature.
    2341 These notions are generalized to provide \CFA with \newterm{tuple expression}s and \newterm{tuple type}s.
     2364These notions can be generalized to provide \CFA with \emph{tuple expressions} and \emph{tuple types}.
    23422365A tuple expression is an expression producing a fixed-size, ordered list of values of heterogeneous types.
    2343 The type of a tuple expression is the tuple of the subexpression types, or a tuple type.
    2344 
     2366The type of a tuple expression is the tuple of the subexpression types, or a \emph{tuple type}.
    23452367In \CFA, a tuple expression is denoted by a comma-separated list of expressions enclosed in square brackets.
    23462368For example, the expression ©[5, 'x', 10.5]© has type ©[int, char, double]©.
     
    23492371The order of evaluation of the components in a tuple expression is unspecified, to allow a compiler the greatest flexibility for program optimization.
    23502372It is, however, guaranteed that each component of a tuple expression is evaluated for side-effects, even if the result is not used.
    2351 Multiple-return-value functions can equivalently be called \newterm{tuple-returning functions}.
    2352 
    2353 
    2354 \subsection{Variables}
    2355 
    2356 The previous call of ©div© still requires the preallocation of multiple return-variables in a manner similar to the aliasing example.
    2357 In \CFA, it is possible to overcome this restriction by declaring a \newterm{tuple variable}.
    2358 \begin{cfa}
    2359 [int, int] ®qr® = div( 13, 5 );                 §\C{// initialize tuple variable}§
    2360 printf( "%d %d\n", ®qr® );                              §\C{// print quotient/remainder}§
    2361 \end{cfa}
    2362 It is now possible to match the multiple return-values to a single variable, in much the same way as \Index{aggregation}.
    2363 As well, the components of the tuple value are passed as separate parameters to ©printf©, allowing direct printing of tuple variables.
    2364 One way to access the individual components of a tuple variable is with assignment.
    2365 \begin{cfa}
    2366 [ quot, rem ] = qr;                                             §\C{// assign multiple variables}§
    2367 \end{cfa}
    2368 
     2373Multiple-return-value functions can equivalently be called \emph{tuple-returning functions}.
     2374
     2375\subsection{Tuple Variables}
     2376The call-site of the ©most_frequent© routine has a notable blemish, in that it required the preallocation of return variables in a manner similar to the aliasing example, since it is impossible to declare multiple variables of different types in the same declaration in standard C.
     2377In \CFA, it is possible to overcome this restriction by declaring a \emph{tuple variable}.
     2378\begin{cfa}[emph=ret, emphstyle=\color{red}]
     2379const char * str = "hello world";
     2380[int, char] ret = most_frequent(str);  // initialize tuple variable
     2381printf("%s -- %d %c\n", str, ret);
     2382\end{cfa}
     2383It is now possible to accept multiple values into a single piece of storage, in much the same way that it was previously possible to pass multiple values from one function call to another.
     2384These variables can be used in any of the contexts where a tuple expression is allowed, such as in the ©printf© function call.
     2385As in the ©process© example, the components of the tuple value are passed as separate parameters to ©printf©, allowing very simple printing of tuple expressions.
     2386One way to access the individual components is with a simple assignment, as in previous examples.
     2387\begin{cfa}
     2388int freq;
     2389char ch;
     2390[freq, ch] = ret;
     2391\end{cfa}
     2392
     2393\begin{sloppypar}
    23692394In addition to variables of tuple type, it is also possible to have pointers to tuples, and arrays of tuples.
    23702395Tuple types can be composed of any types, except for array types, since array assignment is disallowed, which makes tuple assignment difficult when a tuple contains an array.
    23712396\begin{cfa}
    2372 [ double, int ] di;
    2373 [ double, int ] * pdi
    2374 [ double, int ] adi[10];
     2397[double, int] di;
     2398[double, int] * pdi
     2399[double, int] adi[10];
    23752400\end{cfa}
    23762401This examples declares a variable of type ©[double, int]©, a variable of type pointer to ©[double, int]©, and an array of ten ©[double, int]©.
    2377 
    2378 
    2379 \subsection{Indexing}
    2380 
    2381 It is also possible to access a single component of a tuple-valued expression without creating temporary variables.
    2382 Given a tuple-valued expression $e$np and a compile-time constant integer $i$ where $0 \leq i < n$, where $n$ is the number of components in $e$, $e.i$ accesses the $i^{\:th}$ component of $e$, \eg:
     2402\end{sloppypar}
     2403
     2404\subsection{Tuple Indexing}
     2405
     2406At times, it is desirable to access a single component of a tuple-valued expression without creating unnecessary temporary variables to assign to.
     2407Given a tuple-valued expression ©e© and a compile-time constant integer $i$ where $0 \leq i < n$, where $n$ is the number of components in ©e©, ©e.i© accesses the $i$\textsuperscript{th} component of ©e©.
     2408For example,
    23832409\begin{cfa}
    23842410[int, double] x;
     
    23912417p->0 = 5;                                                               §\C{// access int component of tuple pointed-to by p}§
    23922418g( x.1, x.0 );                                                  §\C{// rearrange x to pass to g}§
    2393 double z = [ x, f() ].0.1;                              §\C{// access second component of first component of tuple expression}§
    2394 \end{cfa}
    2395 Tuple-index expressions can occur on any tuple-typed expression, including tuple-returning functions, square-bracketed tuple expressions, and other tuple-index expressions, provided the retrieved component is also a tuple.
     2419double z = [x, f()].0.1;                                §\C{// access second component of first component of tuple expression}§
     2420\end{cfa}
     2421As seen above, tuple-index expressions can occur on any tuple-typed expression, including tuple-returning functions, square-bracketed tuple expressions, and other tuple-index expressions, provided the retrieved component is also a tuple.
    23962422This feature was proposed for \KWC but never implemented \cite[p.~45]{Till89}.
    23972423
    2398 
    23992424\subsection{Flattening and Structuring}
    2400 
    24012425As evident in previous examples, tuples in \CFA do not have a rigid structure.
    24022426In function call contexts, tuples support implicit flattening and restructuring conversions.
     
    24412465There is only a single definition of ©f©, and 3 arguments with only single interpretations.
    24422466First, the argument alternative list ©[5, 10.2], 4© is flattened to produce the argument list ©5, 10.2, 4©.
    2443 Next, the parameter matching algorithm begins, with $P =$© int© and $A =$© int©, which unifies exactly.
    2444 Moving to the next parameter and argument, $P =$© [double, int]© and $A =$© double©.
    2445 This time, the parameter is a tuple type, so the algorithm applies recursively with $P' =$© double© and $A =$© double©, which unifies exactly.
    2446 Then $P' =$© int© and $A =$© double©, which again unifies exactly.
     2467Next, the parameter matching algorithm begins, with $P = $©int© and $A = $©int©, which unifies exactly.
     2468Moving to the next parameter and argument, $P = $©[double, int]© and $A = $©double©.
     2469This time, the parameter is a tuple type, so the algorithm applies recursively with $P' = $©double© and $A = $©double©, which unifies exactly.
     2470Then $P' = $©int© and $A = $©double©, which again unifies exactly.
    24472471At this point, the end of $P'$ has been reached, so the arguments ©10.2, 4© are structured into the tuple expression ©[10.2, 4]©.
    24482472Finally, the end of the parameter list $P$ has also been reached, so the final expression is ©f(5, [10.2, 4])©.
    24492473
    2450 
    2451 \subsection{Assignment}
     2474\section{Tuple Assignment}
    24522475\label{s:TupleAssignment}
    2453 
    2454 An assignment where the left side of the assignment operator has a tuple type is called \newterm{tuple assignment}.
    2455 There are two kinds of tuple assignment depending on whether the right side of the assignment operator has a non-tuple or tuple type, called \newterm[mass assignment]{mass} and \newterm[multiple assignment]{multiple} assignment, respectively.
     2476An assignment where the left side of the assignment operator has a tuple type is called tuple assignment.
     2477There are two kinds of tuple assignment depending on whether the right side of the assignment operator has a tuple type or a non-tuple type, called \emph{Multiple} and \emph{Mass} Assignment, respectively.
    24562478\begin{cfa}
    24572479int x;
    24582480double y;
    24592481[int, double] z;
    2460 [y, x] = 3.14;                                                  §\C{// mass assignment}§
    2461 [x, y] = z;                                                         §\C{// multiple assignment}§
    2462 z = 10;                                                         §\C{// mass assignment}§
    2463 z = [x, y];                                                             §\C{// multiple assignment}§
     2482[y, x] = 3.14;  // mass assignment
     2483[x, y] = z;     // multiple assignment
     2484z = 10;         // mass assignment
     2485z = [x, y];     // multiple assignment
    24642486\end{cfa}
    24652487Let $L_i$ for $i$ in $[0, n)$ represent each component of the flattened left side, $R_i$ represent each component of the flattened right side of a multiple assignment, and $R$ represent the right side of a mass assignment.
     
    24682490For example, the following is invalid because the number of components on the left does not match the number of components on the right.
    24692491\begin{cfa}
    2470 [ int, int ] x, y, z;
    2471 [ x, y ] = z;                                              §\C{// multiple assignment, invalid 4 != 2}§
     2492[int, int] x, y, z;
     2493[x, y] = z;   // multiple assignment, invalid 4 != 2
    24722494\end{cfa}
    24732495Multiple assignment assigns $R_i$ to $L_i$ for each $i$.
     
    24852507\begin{cfa}
    24862508int x = 10, y = 20;
    2487 [ x, y ] = [ y, x ];
     2509[x, y] = [y, x];
    24882510\end{cfa}
    24892511After executing this code, ©x© has the value ©20© and ©y© has the value ©10©.
     
    25042526        int a, b;
    25052527        double c, d;
    2506         [ void ] f( [ int, int ] );
    2507         f( [ c, a ] = [ b, d ] = 1.5 );  // assignments in parameter list
     2528        [void] f([int, int]);
     2529        f([c, a] = [b, d] = 1.5);  // assignments in parameter list
    25082530\end{cfa}
    25092531The tuple expression begins with a mass assignment of ©1.5© into ©[b, d]©, which assigns ©1.5© into ©b©, which is truncated to ©1©, and ©1.5© into ©d©, producing the tuple ©[1, 1.5]© as a result.
     
    25112533Finally, the tuple ©[1, 1]© is used as an expression in the call to ©f©.
    25122534
    2513 
    2514 \subsection{Construction}
    2515 
     2535\subsection{Tuple Construction}
    25162536Tuple construction and destruction follow the same rules and semantics as tuple assignment, except that in the case where there is no right side, the default constructor or destructor is called on each component of the tuple.
    25172537As constructors and destructors did not exist in previous versions of \CFA or in \KWC, this is a primary contribution of this thesis to the design of tuples.
     
    25492569The initialization of ©s© with ©t© works by default because ©t© is flattened into its components, which satisfies the generated field constructor ©?{}(S *, int, double)© to initialize the first two values.
    25502570
    2551 
    2552 \subsection{Member-Access Expression}
     2571\section{Member-Access Tuple Expression}
    25532572\label{s:MemberAccessTuple}
    2554 
    2555 Tuples may be used to select multiple fields of a record by field name.
     2573It is possible to access multiple fields from a single expression using a \emph{Member-Access Tuple Expression}.
    25562574The result is a single tuple-valued expression whose type is the tuple of the types of the members.
    25572575For example,
    25582576\begin{cfa}
    2559 struct S { char x; int y; double z; } s;
     2577struct S { int x; double y; char * z; } s;
    25602578s.[x, y, z];
    25612579\end{cfa}
    2562 Here, the type of ©s.[ x, y, z ]© is ©[ char, int, double ]©.
    2563 A member tuple expression has the form \emph{e}©.[x, y, z];© where \emph{e} is an expression with type ©T©, where ©T© supports member access expressions, and ©x, y, z© are all members of ©T© with types ©T$_x$©, ©T$_y$©, and ©T$_z$© respectively.
    2564 Then the type of \emph{e}©.[x, y, z]© is ©[T$_x$, T$_y$, T$_z$]©.
    2565 
    2566 A member-access tuple may be used anywhere a tuple can be used, \eg:
    2567 \begin{cfa}
    2568 s.[ y, z, x ] = [ 3, 3.2, 'x' ];                §\C{// equivalent to s.x = 'x', s.y = 3, s.z = 3.2}§
    2569 f( s.[ y, z ] );                                                §\C{// equivalent to f( s.y, s.z )}§
    2570 \end{cfa}
    2571 Note, the fields appearing in a record-field tuple may be specified in any order;
    2572 also, it is unnecessary to specify all the fields of a struct in a multiple record-field tuple.
    2573 
    2574 Since tuple-index expressions are a form of member-access expression, it is possible to use tuple-index expressions in conjunction with member-access expressions to restructure a tuple (\eg, rearrange components, drop components, duplicate components, etc.).
    2575 \begin{cfa}
    2576 [ int, int, long, double ] x;
    2577 void f( double, long );
    2578 
    2579 f( x.[ 0, 3 ] );                                                §\C{// f( x.0, x.3 )}§
    2580 x.[ 0, 1 ] = x.[ 1, 0 ];                                §\C{// [ x.0, x.1 ] = [ x.1, x.0 ]}§
    2581 [ long, int, long ] y = x.[ 2, 0, 2 ];
    2582 \end{cfa}
    2583 
    2584 It is possible for a member tuple expression to contain other member access expressions, \eg:
     2580Here, the type of ©s.[x, y, z]© is ©[int, double, char *]©.
     2581A member tuple expression has the form ©a.[x, y, z];© where ©a© is an expression with type ©T©, where ©T© supports member access expressions, and ©x, y, z© are all members of ©T© with types ©T$_x$©, ©T$_y$©, and ©T$_z$© respectively.
     2582Then the type of ©a.[x, y, z]© is ©[T_x, T_y, T_z]©.
     2583
     2584Since tuple index expressions are a form of member-access expression, it is possible to use tuple-index expressions in conjunction with member tuple expressions to manually restructure a tuple (\eg, rearrange components, drop components, duplicate components, etc.).
     2585\begin{cfa}
     2586[int, int, long, double] x;
     2587void f(double, long);
     2588
     2589f(x.[0, 3]);          // f(x.0, x.3)
     2590x.[0, 1] = x.[1, 0];  // [x.0, x.1] = [x.1, x.0]
     2591[long, int, long] y = x.[2, 0, 2];
     2592\end{cfa}
     2593
     2594It is possible for a member tuple expression to contain other member access expressions.
     2595For example,
    25852596\begin{cfa}
    25862597struct A { double i; int j; };
    25872598struct B { int * k; short l; };
    25882599struct C { int x; A y; B z; } v;
    2589 v.[ x, y.[ i, j ], z.k ];
    2590 \end{cfa}
    2591 This expression is equivalent to ©[ v.x, [ v.y.i, v.y.j ], v.z.k ]©.
    2592 That is, the aggregate expression is effectively distributed across the tuple allowing simple and easy access to multiple components in an aggregate without repetition.
     2600v.[x, y.[i, j], z.k];
     2601\end{cfa}
     2602This expression is equivalent to ©[v.x, [v.y.i, v.y.j], v.z.k]©.
     2603That is, the aggregate expression is effectively distributed across the tuple, which allows simple and easy access to multiple components in an aggregate, without repetition.
    25932604It is guaranteed that the aggregate expression to the left of the ©.© in a member tuple expression is evaluated exactly once.
    2594 As such, it is safe to use member tuple expressions on the result of a function with side-effects.
    2595 \begin{cfa}
    2596 [ int, float, double ] f();
    2597 [ double, float ] x = f().[ 2, 1 ];             §\C{// f() called once}§
     2605As such, it is safe to use member tuple expressions on the result of a side-effecting function.
     2606\begin{cfa}
     2607[int, float, double] f();
     2608[double, float] x = f().[2, 1];
    25982609\end{cfa}
    25992610
     
    26012612Since \CFA permits these tuple-access expressions using structures, unions, and tuples, \emph{member tuple expression} or \emph{field tuple expression} is more appropriate.
    26022613
    2603 
    2604 \subsection{Casting}
    2605 
     2614It is possible to extend member-access expressions further.
     2615Currently, a member-access expression whose member is a name requires that the aggregate is a structure or union, while a constant integer member requires the aggregate to be a tuple.
     2616In the interest of orthogonal design, \CFA could apply some meaning to the remaining combinations as well.
     2617For example,
     2618\begin{cfa}
     2619struct S { int x, y; } s;
     2620[S, S] z;
     2621
     2622s.x;  // access member
     2623z.0;  // access component
     2624
     2625s.1;  // ???
     2626z.y;  // ???
     2627\end{cfa}
     2628One possibility is for ©s.1© to select the second member of ©s©.
     2629Under this interpretation, it becomes possible to not only access members of a struct by name, but also by position.
     2630Likewise, it seems natural to open this mechanism to enumerations as well, wherein the left side would be a type, rather than an expression.
     2631One benefit of this interpretation is familiarity, since it is extremely reminiscent of tuple-index expressions.
     2632On the other hand, it could be argued that this interpretation is brittle in that changing the order of members or adding new members to a structure becomes a brittle operation.
     2633This problem is less of a concern with tuples, since modifying a tuple affects only the code that directly uses the tuple, whereas modifying a structure has far reaching consequences for every instance of the structure.
     2634
     2635As for ©z.y©, one interpretation is to extend the meaning of member tuple expressions.
     2636That is, currently the tuple must occur as the member, \ie to the right of the dot.
     2637Allowing tuples to the left of the dot could distribute the member across the elements of the tuple, in much the same way that member tuple expressions distribute the aggregate across the member tuple.
     2638In this example, ©z.y© expands to ©[z.0.y, z.1.y]©, allowing what is effectively a very limited compile-time field-sections map operation, where the argument must be a tuple containing only aggregates having a member named ©y©.
     2639It is questionable how useful this would actually be in practice, since structures often do not have names in common with other structures, and further this could cause maintainability issues in that it encourages programmers to adopt very simple naming conventions to maximize the amount of overlap between different types.
     2640Perhaps more useful would be to allow arrays on the left side of the dot, which would likewise allow mapping a field access across the entire array, producing an array of the contained fields.
     2641The immediate problem with this idea is that C arrays do not carry around their size, which would make it impossible to use this extension for anything other than a simple stack allocated array.
     2642
     2643Supposing this feature works as described, it would be necessary to specify an ordering for the expansion of member-access expressions versus member-tuple expressions.
     2644\begin{cfa}
     2645struct { int x, y; };
     2646[S, S] z;
     2647z.[x, y];  // ???
     2648// => [z.0, z.1].[x, y]
     2649// => [z.0.x, z.0.y, z.1.x, z.1.y]
     2650// or
     2651// => [z.x, z.y]
     2652// => [[z.0, z.1].x, [z.0, z.1].y]
     2653// => [z.0.x, z.1.x, z.0.y, z.1.y]
     2654\end{cfa}
     2655Depending on exactly how the two tuples are combined, different results can be achieved.
     2656As such, a specific ordering would need to be imposed to make this feature useful.
     2657Furthermore, this addition moves a member-tuple expression's meaning from being clear statically to needing resolver support, since the member name needs to be distributed appropriately over each member of the tuple, which could itself be a tuple.
     2658
     2659A second possibility is for \CFA to have named tuples, as they exist in Swift and D.
     2660\begin{cfa}
     2661typedef [int x, int y] Point2D;
     2662Point2D p1, p2;
     2663p1.x + p1.y + p2.x + p2.y;
     2664p1.0 + p1.1 + p2.0 + p2.1;  // equivalent
     2665\end{cfa}
     2666In this simpler interpretation, a tuple type carries with it a list of possibly empty identifiers.
     2667This approach fits naturally with the named return-value feature, and would likely go a long way towards implementing it.
     2668
     2669Ultimately, the first two extensions introduce complexity into the model, with relatively little perceived benefit, and so were dropped from consideration.
     2670Named tuples are a potentially useful addition to the language, provided they can be parsed with a reasonable syntax.
     2671
     2672
     2673\section{Casting}
    26062674In C, the cast operator is used to explicitly convert between types.
    26072675In \CFA, the cast operator has a secondary use, which is type ascription, since it forces the expression resolution algorithm to choose the lowest cost conversion to the target type.
     
    26572725That is, it is invalid to cast ©[int, int]© to ©[int, int, int]©.
    26582726
    2659 
    2660 \subsection{Polymorphism}
    2661 
     2727\section{Polymorphism}
    26622728Due to the implicit flattening and structuring conversions involved in argument passing, ©otype© and ©dtype© parameters are restricted to matching only with non-tuple types.
    26632729The integration of polymorphism, type assertions, and monomorphic specialization of tuple-assertions are a primary contribution of this thesis to the design of tuples.
     
    27122778Until this point, it has been assumed that assertion arguments must match the parameter type exactly, modulo polymorphic specialization (\ie, no implicit conversions are applied to assertion arguments).
    27132779This decision presents a conflict with the flexibility of tuples.
    2714 
    2715 
    2716 \subsubsection{Assertion Inference}
    2717 
     2780\subsection{Assertion Inference}
    27182781\begin{cfa}
    27192782int f([int, double], double);
     
    28392902Unfortunately, C's syntax for subscripts precluded treating them as tuples.
    28402903The C subscript list has the form ©[i][j]...© and not ©[i, j, ...]©.
    2841 Therefore, there is no syntactic way for a routine returning multiple values to specify the different subscript values, \eg ©f[ g() ]© always means a single subscript value because there is only one set of brackets.
     2904Therefore, there is no syntactic way for a routine returning multiple values to specify the different subscript values, \eg ©f[g()]© always means a single subscript value because there is only one set of brackets.
    28422905Fixing this requires a major change to C because the syntactic form ©M[i, j, k]© already has a particular meaning: ©i, j, k© is a comma expression.
    28432906\end{rationale}
     
    28882951
    28892952
    2890 \subsection{Mass Assignment}
     2953\section{Mass Assignment}
    28912954
    28922955\CFA permits assignment to several variables at once using mass assignment~\cite{CLU}.
     
    29282991
    29292992
    2930 \subsection{Multiple Assignment}
     2993\section{Multiple Assignment}
    29312994
    29322995\CFA also supports the assignment of several values at once, known as multiple assignment~\cite{CLU,Galletly96}.
     
    29693032
    29703033
    2971 \subsection{Cascade Assignment}
     3034\section{Cascade Assignment}
    29723035
    29733036As in C, \CFA mass and multiple assignments can be cascaded, producing cascade assignment.
     
    29853048\end{cfa}
    29863049As in C, the rightmost assignment is performed first, \ie assignment parses right to left.
     3050
     3051
     3052\section{Field Tuples}
     3053
     3054Tuples may be used to select multiple fields of a record by field name.
     3055Its general form is:
     3056\begin{cfa}
     3057§\emph{expr}§ . [ §\emph{fieldlist}§ ]
     3058§\emph{expr}§ -> [ §\emph{fieldlist}§ ]
     3059\end{cfa}
     3060\emph{expr} is any expression yielding a value of type record, \eg ©struct©, ©union©.
     3061Each element of \emph{ fieldlist} is an element of the record specified by \emph{expr}.
     3062A record-field tuple may be used anywhere a tuple can be used. An example of the use of a record-field tuple is
     3063the following:
     3064\begin{cfa}
     3065struct s {
     3066        int f1, f2;
     3067        char f3;
     3068        double f4;
     3069} v;
     3070v.[ f3, f1, f2 ] = ['x', 11, 17 ];      §\C{// equivalent to v.f3 = 'x', v.f1 = 11, v.f2 = 17}§
     3071f( v.[ f3, f1, f2 ] );                          §\C{// equivalent to f( v.f3, v.f1, v.f2 )}§
     3072\end{cfa}
     3073Note, the fields appearing in a record-field tuple may be specified in any order;
     3074also, it is unnecessary to specify all the fields of a struct in a multiple record-field tuple.
     3075
     3076If a field of a ©struct© is itself another ©struct©, multiple fields of this subrecord can be specified using a nested record-field tuple, as in the following example:
     3077\begin{cfa}
     3078struct inner {
     3079        int f2, f3;
     3080};
     3081struct outer {
     3082        int f1;
     3083        struct inner i;
     3084        double f4;
     3085} o;
     3086
     3087o.[ f1, i.[ f2, f3 ], f4 ] = [ 11, 12, 13, 3.14159 ];
     3088\end{cfa}
    29873089
    29883090
  • src/Concurrency/Waitfor.cc

    rd5a52cc r1393df07  
    416416                                makeAccStatement( acceptables, index, "is_dtor", detectIsDtor( clause.target.function )                                    , indexer ),
    417417                                makeAccStatement( acceptables, index, "func"   , new CastExpr( clause.target.function, fptr_t )                            , indexer ),
    418                                 makeAccStatement( acceptables, index, "data"   , new VariableExpr( monitors )                                              , indexer ),
     418                                makeAccStatement( acceptables, index, "list"   , new VariableExpr( monitors )                                              , indexer ),
    419419                                makeAccStatement( acceptables, index, "size"   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ),
    420420                                setter->clone()
  • src/GenPoly/InstantiateGeneric.cc

    rd5a52cc r1393df07  
    217217                PassVisitor<GenericInstantiator> instantiator;
    218218
    219                 // mutateAll( translationUnit, fixer );
     219                mutateAll( translationUnit, fixer );
    220220                mutateAll( translationUnit, instantiator );
    221221        }
  • src/Parser/ParseNode.h

    rd5a52cc r1393df07  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Nov 27 17:33:35 2017
    13 // Update Count     : 824
     12// Last Modified On : Sat Sep 23 18:11:22 2017
     13// Update Count     : 821
    1414//
    1515
     
    292292        DeclarationNode * set_extension( bool exten ) { extension = exten; return this; }
    293293  public:
    294         DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); }
    295 
    296294        struct Variable_t {
    297295//              const std::string * name;
  • src/Parser/parser.yy

    rd5a52cc r1393df07  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Nov 27 17:23:35 2017
    13 // Update Count     : 2992
     12// Last Modified On : Sun Nov 26 11:36:36 2017
     13// Update Count     : 2969
    1414//
    1515
     
    13641364                        $$ = $3->addQualifiers( $1 )->addQualifiers( $2 );
    13651365                }
    1366         | cfa_function_declaration pop ',' push identifier_or_type_name '(' push cfa_parameter_type_list_opt pop ')'
    1367                 {
    1368                         // Append the return type at the start (left-hand-side) to each identifier in the list.
    1369                         DeclarationNode * ret = new DeclarationNode;
    1370                         ret->type = maybeClone( $1->type->base );
    1371                         $$ = $1->appendList( DeclarationNode::newFunction( $5, ret, $8, nullptr, true ) );
     1366        | cfa_function_declaration pop ',' push identifier_or_type_name
     1367                {
     1368                        typedefTable.addToEnclosingScope( *$5, TypedefTable::ID );
     1369                        $$ = $1->appendList( $1->cloneType( $5 ) );
    13721370                }
    13731371        ;
     
    24182416                        typedefTable.addToEnclosingScope( TypedefTable::ID );
    24192417                        typedefTable.leaveScope();
    2420                         // Add the function body to the last identifier in the function definition list, i.e., foo3:
    2421                         //   [const double] foo1(), foo2( int ), foo3( double ) { return 3.0; }
    2422                         $1->get_last()->addFunctionBody( $3 );
    2423                         $$ = $1;
     2418                        $$ = $1->addFunctionBody( $3 );
    24242419                }
    24252420        | declaration_specifier function_declarator with_clause_opt compound_statement
  • src/benchmark/Makefile.am

    rd5a52cc r1393df07  
    9494        ctxswitch-cfa_thread.run        \
    9595        ctxswitch-upp_coroutine.run     \
    96         ctxswitch-upp_thread.run        \
    97         ctxswitch-goroutine.run         \
    98         ctxswitch-java_thread.run
     96        ctxswitch-upp_thread.run
    9997
    10098ctxswitch-cfa_coroutine$(EXEEXT):
     
    113111        @@BACKEND_CC@ ctxswitch/pthreads.c  -DBENCH_N=50000000  -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    114112
    115 ctxswitch-goroutine$(EXEEXT):
    116         @go build -o a.out ctxswitch/goroutine.go
    117 
    118 ctxswitch-java_thread$(EXEEXT):
    119         @javac ctxswitch/JavaThread.java
    120         @echo "#!/bin/sh" > a.out
    121         @echo "cd ctxswitch && java JavaThread" >> a.out
    122         @chmod a+x a.out
    123 
    124113## =========================================================================================================
    125114mutex$(EXEEXT) :\
    126115        mutex-function.run      \
    127         mutex-fetch_add.run     \
    128116        mutex-pthread_lock.run  \
    129117        mutex-upp.run           \
    130118        mutex-cfa1.run          \
    131119        mutex-cfa2.run          \
    132         mutex-cfa4.run          \
    133         mutex-java_thread.run
     120        mutex-cfa4.run
    134121
    135122mutex-function$(EXEEXT):
    136123        @@BACKEND_CC@ mutex/function.c    -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    137124
    138 mutex-fetch_add$(EXEEXT):
    139         @@BACKEND_CC@ mutex/fetch_add.c   -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    140 
    141125mutex-pthread_lock$(EXEEXT):
    142126        @@BACKEND_CC@ mutex/pthreads.c    -DBENCH_N=50000000    -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     
    153137mutex-cfa4$(EXEEXT):
    154138        @${CC}        mutex/cfa4.c        -DBENCH_N=5000000     -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    155 
    156 mutex-java_thread$(EXEEXT):
    157         @javac mutex/JavaThread.java
    158         @echo "#!/bin/sh" > a.out
    159         @echo "cd mutex && java JavaThread" >> a.out
    160         @chmod a+x a.out
    161139
    162140## =========================================================================================================
     
    165143        signal-cfa1.run         \
    166144        signal-cfa2.run         \
    167         signal-cfa4.run         \
    168         signal-java_thread.run
     145        signal-cfa4.run
    169146
    170147signal-upp$(EXEEXT):
     
    179156signal-cfa4$(EXEEXT):
    180157        @${CC}        schedint/cfa4.c     -DBENCH_N=500000      -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    181 
    182 signal-java_thread$(EXEEXT):
    183         @javac schedint/JavaThread.java
    184         @echo "#!/bin/sh" > a.out
    185         @echo "cd schedint && java JavaThread" >> a.out
    186         @chmod a+x a.out
    187 
    188158
    189159## =========================================================================================================
     
    213183        creation-cfa_thread.run                 \
    214184        creation-upp_coroutine.run              \
    215         creation-upp_thread.run                 \
    216         creation-goroutine.run                  \
    217         creation-java_thread.run
     185        creation-upp_thread.run
    218186
    219187creation-cfa_coroutine$(EXEEXT):
     
    234202creation-pthread$(EXEEXT):
    235203        @@BACKEND_CC@ creation/pthreads.c  -DBENCH_N=250000     -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    236 
    237 creation-goroutine$(EXEEXT):
    238         @go build -o a.out creation/goroutine.go
    239 
    240 creation-java_thread$(EXEEXT):
    241         @javac creation/JavaThread.java
    242         @echo "#!/bin/sh" > a.out
    243         @echo "cd creation && java JavaThread" >> a.out
    244         @chmod a+x a.out
    245204
    246205## =========================================================================================================
  • src/benchmark/Makefile.in

    rd5a52cc r1393df07  
    507507        ctxswitch-cfa_thread.run        \
    508508        ctxswitch-upp_coroutine.run     \
    509         ctxswitch-upp_thread.run        \
    510         ctxswitch-goroutine.run         \
    511         ctxswitch-java_thread.run
     509        ctxswitch-upp_thread.run
    512510
    513511ctxswitch-cfa_coroutine$(EXEEXT):
     
    526524        @@BACKEND_CC@ ctxswitch/pthreads.c  -DBENCH_N=50000000  -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    527525
    528 ctxswitch-goroutine$(EXEEXT):
    529         @go build -o a.out ctxswitch/goroutine.go
    530 
    531 ctxswitch-java_thread$(EXEEXT):
    532         @javac ctxswitch/JavaThread.java
    533         @echo "#!/bin/sh" > a.out
    534         @echo "cd ctxswitch && java JavaThread" >> a.out
    535         @chmod a+x a.out
    536 
    537526mutex$(EXEEXT) :\
    538527        mutex-function.run      \
    539         mutex-fetch_add.run     \
    540528        mutex-pthread_lock.run  \
    541529        mutex-upp.run           \
    542530        mutex-cfa1.run          \
    543531        mutex-cfa2.run          \
    544         mutex-cfa4.run          \
    545         mutex-java_thread.run
     532        mutex-cfa4.run
    546533
    547534mutex-function$(EXEEXT):
    548535        @@BACKEND_CC@ mutex/function.c    -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    549536
    550 mutex-fetch_add$(EXEEXT):
    551         @@BACKEND_CC@ mutex/fetch_add.c   -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    552 
    553537mutex-pthread_lock$(EXEEXT):
    554538        @@BACKEND_CC@ mutex/pthreads.c    -DBENCH_N=50000000    -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     
    565549mutex-cfa4$(EXEEXT):
    566550        @${CC}        mutex/cfa4.c        -DBENCH_N=5000000     -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    567 
    568 mutex-java_thread$(EXEEXT):
    569         @javac mutex/JavaThread.java
    570         @echo "#!/bin/sh" > a.out
    571         @echo "cd mutex && java JavaThread" >> a.out
    572         @chmod a+x a.out
    573551
    574552signal$(EXEEXT) :\
     
    589567signal-cfa4$(EXEEXT):
    590568        @${CC}        schedint/cfa4.c     -DBENCH_N=500000      -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    591 
    592 signal-java_thread$(EXEEXT):
    593         @javac schedint/JavaThread.java
    594         @echo "#!/bin/sh" > a.out
    595         @echo "cd schedint && java JavaThread" >> a.out
    596         @chmod a+x a.out
    597569
    598570waitfor$(EXEEXT) :\
     
    620592        creation-cfa_thread.run                 \
    621593        creation-upp_coroutine.run              \
    622         creation-upp_thread.run                 \
    623         creation-goroutine.run                  \
    624         creation-java_thread.run
     594        creation-upp_thread.run
    625595
    626596creation-cfa_coroutine$(EXEEXT):
     
    641611creation-pthread$(EXEEXT):
    642612        @@BACKEND_CC@ creation/pthreads.c  -DBENCH_N=250000     -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    643 
    644 creation-goroutine$(EXEEXT):
    645         @go build -o a.out creation/goroutine.go
    646 
    647 creation-java_thread$(EXEEXT):
    648         @javac creation/JavaThread.java
    649         @echo "#!/bin/sh" > a.out
    650         @echo "cd creation && java JavaThread" >> a.out
    651         @chmod a+x a.out
    652613
    653614compile$(EXEEXT) :\
  • src/benchmark/bench.h

    rd5a52cc r1393df07  
    11#pragma once
    22
    3 #if defined(__cforall)
     3#if defined(__CFORALL__)
    44extern "C" {
    55#endif
     
    88        #include <sys/times.h>                                  // times
    99        #include <time.h>
    10 #if defined(__cforall)
     10#if defined(__CFORALL__)
    1111}
    1212#endif
  • src/libcfa/Makefile.am

    rd5a52cc r1393df07  
    100100        math                            \
    101101        gmp                             \
    102         bits/containers.h               \
    103102        bits/defs.h             \
    104103        bits/locks.h            \
  • src/libcfa/Makefile.in

    rd5a52cc r1393df07  
    264264        containers/result containers/vector concurrency/coroutine \
    265265        concurrency/thread concurrency/kernel concurrency/monitor \
    266         ${shell echo stdhdr/*} math gmp bits/containers.h bits/defs.h \
    267         bits/locks.h concurrency/invoke.h libhdr.h libhdr/libalign.h \
     266        ${shell echo stdhdr/*} math gmp bits/defs.h bits/locks.h \
     267        concurrency/invoke.h libhdr.h libhdr/libalign.h \
    268268        libhdr/libdebug.h libhdr/libtools.h
    269269HEADERS = $(nobase_cfa_include_HEADERS)
     
    437437        math                            \
    438438        gmp                             \
    439         bits/containers.h               \
    440439        bits/defs.h             \
    441440        bits/locks.h            \
  • src/libcfa/bits/containers.h

    rd5a52cc r1393df07  
    1515#pragma once
    1616
    17 #include "bits/defs.h"
     17#include <stddef.h>
     18
    1819#include "libhdr.h"
    19 
    20 //-----------------------------------------------------------------------------
    21 // Array
    22 //-----------------------------------------------------------------------------
    23 
    24 #ifdef __cforall
    25         forall(dtype T)
    26 #else
    27         #define T void
    28 #endif
    29 struct __small_array {
    30         T *           data;
    31         __lock_size_t size;
    32 };
    33 #undef T
    34 
    35 #ifdef __cforall
    36         #define __small_array_t(T) __small_array(T)
    37 #else
    38         #define __small_array_t(T) struct __small_array
    39 #endif
    40 
    41 #ifdef __cforall
    42         // forall(otype T | sized(T))
    43         // static inline void ?{}(__small_array(T) & this) {}
    44 
    45         forall(dtype T | sized(T))
    46         static inline T& ?[?]( __small_array(T) & this, __lock_size_t idx) {
    47                 return ((typeof(this.data))this.data)[idx];
    48         }
    49 
    50         forall(dtype T | sized(T))
    51         static inline T& ?[?]( const __small_array(T) & this, __lock_size_t idx) {
    52                 return ((typeof(this.data))this.data)[idx];
    53         }
    54 
    55         forall(dtype T | sized(T))
    56         static inline T* begin( const __small_array(T) & this ) {
    57                 return ((typeof(this.data))this.data);
    58         }
    59 
    60         forall(dtype T | sized(T))
    61         static inline T* end( const __small_array(T) & this ) {
    62                 return ((typeof(this.data))this.data) + this.size;
    63         }
    64 #endif
    6520
    6621//-----------------------------------------------------------------------------
     
    6823//-----------------------------------------------------------------------------
    6924
    70 #ifdef __cforall
     25#ifdef __CFORALL__
    7126        trait is_node(dtype T) {
    7227                T*& get_next( T& );
     
    7732// Stack
    7833//-----------------------------------------------------------------------------
    79 #ifdef __cforall
     34#ifdef __CFORALL__
    8035        forall(dtype TYPE | is_node(TYPE))
    8136        #define T TYPE
     
    8641        T * top;
    8742};
    88 #undef T
    8943
    90 #ifdef __cforall
     44#ifdef __CFORALL__
    9145#define __stack_t(T) __stack(T)
    9246#else
     
    9448#endif
    9549
    96 #ifdef __cforall
     50#ifdef __CFORALL__
    9751        forall(dtype T | is_node(T))
    98         static inline void ?{}( __stack(T) & this ) {
    99                 (this.top){ NULL };
     52        void ?{}( __stack(T) & this ) {
     53                this.top = NULL;
    10054        }
    10155
    10256        forall(dtype T | is_node(T) | sized(T))
    103         static inline void push( __stack(T) & this, T * val ) {
     57        void push( __stack(T) & this, T * val ) {
    10458                verify( !get_next( *val ) );
    10559                get_next( *val ) = this.top;
     
    10862
    10963        forall(dtype T | is_node(T) | sized(T))
    110         static inline T * pop( __stack(T) & this ) {
     64        T * pop( __stack(T) & this ) {
    11165                T * top = this.top;
    11266                if( top ) {
     
    12175// Queue
    12276//-----------------------------------------------------------------------------
    123 #ifdef __cforall
    124         forall(dtype TYPE | is_node(TYPE))
     77#ifdef __CFORALL__
     78        forall(dtype T | is_node(T))
    12579        #define T TYPE
    12680#else
     
    13185        T ** tail;
    13286};
    133 #undef T
    13487
    135 #ifdef __cforall
    136 #define __queue_t(T) __queue(T)
    137 #else
    138 #define __queue_t(T) struct __queue
    139 #endif
    140 
    141 #ifdef __cforall
     88#ifdef __CFORALL__
    14289        forall(dtype T | is_node(T))
    143         static inline void ?{}( __queue(T) & this ) {
    144                 (this.head){ NULL };
    145                 (this.tail){ &this.head };
     90        void ?{}( __queue(T) & this ) {
     91                this.head = NULL;
     92                this.tail = &this.head;
    14693        }
    14794
    14895        forall(dtype T | is_node(T) | sized(T))
    149         static inline void append( __queue(T) & this, T * val ) {
     96        void append( __queue(T) & this, T * val ) {
    15097                verify(this.tail != NULL);
    15198                *this.tail = val;
     
    154101
    155102        forall(dtype T | is_node(T) | sized(T))
    156         static inline T * pop_head( __queue(T) & this ) {
     103        T * pop_head( __queue(T) & this ) {
    157104                T * head = this.head;
    158105                if( head ) {
     
    167114
    168115        forall(dtype T | is_node(T) | sized(T))
    169         static inline T * remove( __queue(T) & this, T ** it ) {
     116        T * remove( __queue(T) & this, T ** it ) {
    170117                T * val = *it;
    171118                verify( val );
  • src/libcfa/bits/defs.h

    rd5a52cc r1393df07  
    1717
    1818#include <stdbool.h>
    19 #include <stddef.h>
    2019#include <stdint.h>
    2120
     
    2322#define likely  (x)    __builtin_expect(!!(x), 1)
    2423#define thread_local _Thread_local
    25 
    26 typedef void (*fptr_t)();
    27 typedef int_fast16_t __lock_size_t;
    28 
    29 #ifdef __cforall
    30 #define __cfa_anonymous_object
    31 #else
    32 #define __cfa_anonymous_object __cfa_anonymous_object
    33 #endif
  • src/libcfa/bits/locks.h

    rd5a52cc r1393df07  
    5656} __ALIGN__;
    5757
    58 #ifdef __cforall
     58#ifdef __CFORALL__
    5959        extern void yield( unsigned int );
    6060        extern thread_local struct thread_desc *    volatile this_thread;
  • src/libcfa/concurrency/invoke.h

    rd5a52cc r1393df07  
    1414//
    1515
    16 #include "bits/containers.h"
    1716#include "bits/defs.h"
    1817#include "bits/locks.h"
    1918
    20 #ifdef __cforall
     19#ifdef __CFORALL__
    2120extern "C" {
    2221#endif
     
    2625#define _INVOKE_H_
    2726
    28         #ifdef __cforall
     27        typedef void (*fptr_t)();
     28        typedef int_fast16_t __lock_size_t;
     29
     30        struct __thread_queue_t {
     31                struct thread_desc * head;
     32                struct thread_desc ** tail;
     33        };
     34
     35        struct __condition_stack_t {
     36                struct __condition_criterion_t * top;
     37        };
     38
     39        #ifdef __CFORALL__
    2940        extern "Cforall" {
    30                 static inline struct thread_desc             * & get_next( struct thread_desc             & this );
    31                 static inline struct __condition_criterion_t * & get_next( struct __condition_criterion_t & this );
     41                void ?{}( struct __thread_queue_t & );
     42                void append( struct __thread_queue_t &, struct thread_desc * );
     43                struct thread_desc * pop_head( struct __thread_queue_t & );
     44                struct thread_desc * remove( struct __thread_queue_t &, struct thread_desc ** );
     45
     46                void ?{}( struct __condition_stack_t & );
     47                void push( struct __condition_stack_t &, struct __condition_criterion_t * );
     48                struct __condition_criterion_t * pop( struct __condition_stack_t & );
    3249        }
    3350        #endif
     
    83100
    84101                // list of acceptable functions, null if any
    85                 __small_array_t(struct __acceptable_t) __cfa_anonymous_object;
     102                struct __acceptable_t * clauses;
     103
     104                // number of acceptable functions
     105                __lock_size_t size;
    86106        };
    87107
     
    94114
    95115                // queue of threads that are blocked waiting for the monitor
    96                 __queue_t(struct thread_desc) entry_queue;
     116                struct __thread_queue_t entry_queue;
    97117
    98118                // stack of conditions to run next once we exit the monitor
    99                 __stack_t(struct __condition_criterion_t) signal_stack;
     119                struct __condition_stack_t signal_stack;
    100120
    101121                // monitor routines can be called recursively, we need to keep track of that
     
    111131        struct __monitor_group_t {
    112132                // currently held monitors
    113                 __small_array_t(monitor_desc*) __cfa_anonymous_object;
     133                struct monitor_desc ** list;
     134
     135                // number of currently held monitors
     136                __lock_size_t size;
    114137
    115138                // last function that acquired monitors
     
    136159     };
    137160
    138      #ifdef __cforall
     161     #ifdef __CFORALL__
    139162     extern "Cforall" {
    140                 static inline thread_desc * & get_next( thread_desc & this ) {
    141                         return this.next;
     163                static inline monitor_desc * ?[?]( const __monitor_group_t & this, ptrdiff_t index ) {
     164                        return this.list[index];
    142165                }
    143166
    144                 static inline struct __condition_criterion_t * & get_next( struct __condition_criterion_t & this );
    145 
    146                 static inline void ?{}(__monitor_group_t & this) {
    147                         (this.data){NULL};
    148                         (this.size){0};
    149                         (this.func){NULL};
    150                 }
    151 
    152                 static inline void ?{}(__monitor_group_t & this, struct monitor_desc ** data, __lock_size_t size, fptr_t func) {
    153                         (this.data){data};
    154                         (this.size){size};
    155                         (this.func){func};
    156                 }
    157 
    158167                static inline bool ?==?( const __monitor_group_t & lhs, const __monitor_group_t & rhs ) {
    159                         if( (lhs.data != 0) != (rhs.data != 0) ) return false;
     168                        if( (lhs.list != 0) != (rhs.list != 0) ) return false;
    160169                        if( lhs.size != rhs.size ) return false;
    161170                        if( lhs.func != rhs.func ) return false;
     
    168177
    169178                        return true;
    170                 }
    171 
    172                 static inline void ?=?(__monitor_group_t & lhs, const __monitor_group_t & rhs) {
    173                         lhs.data = rhs.data;
    174                         lhs.size = rhs.size;
    175                         lhs.func = rhs.func;
    176179                }
    177180        }
     
    207210#endif //_INVOKE_PRIVATE_H_
    208211#endif //! defined(__CFA_INVOKE_PRIVATE__)
    209 #ifdef __cforall
     212#ifdef __CFORALL__
    210213}
    211214#endif
  • src/libcfa/concurrency/kernel

    rd5a52cc r1393df07  
    2626//-----------------------------------------------------------------------------
    2727// Locks
     28// // Lock the spinlock, spin if already acquired
     29// void lock      ( spinlock * DEBUG_CTX_PARAM2 );
     30
     31// // Lock the spinlock, yield repeatedly if already acquired
     32// void lock_yield( spinlock * DEBUG_CTX_PARAM2 );
     33
     34// // Lock the spinlock, return false if already acquired
     35// bool try_lock  ( spinlock * DEBUG_CTX_PARAM2 );
     36
     37// // Unlock the spinlock
     38// void unlock    ( spinlock * );
     39
    2840struct semaphore {
    2941        __spinlock_t lock;
    3042        int count;
    31         __queue_t(thread_desc) waiting;
     43        __thread_queue_t waiting;
    3244};
    3345
     
    4557
    4658        // Ready queue for threads
    47         __queue_t(thread_desc) ready_queue;
     59        __thread_queue_t ready_queue;
    4860
    4961        // Preemption rate on this cluster
  • src/libcfa/concurrency/kernel.c

    rd5a52cc r1393df07  
    164164
    165165void ?{}(cluster & this) {
    166         (this.ready_queue){};
     166        ( this.ready_queue ){};
    167167        ( this.ready_queue_lock ){};
    168168
     
    611611}
    612612
     613//-----------------------------------------------------------------------------
     614// Queues
     615void ?{}( __thread_queue_t & this ) {
     616        this.head = NULL;
     617        this.tail = &this.head;
     618}
     619
     620void append( __thread_queue_t & this, thread_desc * t ) {
     621        verify(this.tail != NULL);
     622        *this.tail = t;
     623        this.tail = &t->next;
     624}
     625
     626thread_desc * pop_head( __thread_queue_t & this ) {
     627        thread_desc * head = this.head;
     628        if( head ) {
     629                this.head = head->next;
     630                if( !head->next ) {
     631                        this.tail = &this.head;
     632                }
     633                head->next = NULL;
     634        }
     635        return head;
     636}
     637
     638thread_desc * remove( __thread_queue_t & this, thread_desc ** it ) {
     639        thread_desc * thrd = *it;
     640        verify( thrd );
     641
     642        (*it) = thrd->next;
     643
     644        if( this.tail == &thrd->next ) {
     645                this.tail = it;
     646        }
     647
     648        thrd->next = NULL;
     649
     650        verify( (this.head == NULL) == (&this.head == this.tail) );
     651        verify( *this.tail == NULL );
     652        return thrd;
     653}
     654
     655void ?{}( __condition_stack_t & this ) {
     656        this.top = NULL;
     657}
     658
     659void push( __condition_stack_t & this, __condition_criterion_t * t ) {
     660        verify( !t->next );
     661        t->next = this.top;
     662        this.top = t;
     663}
     664
     665__condition_criterion_t * pop( __condition_stack_t & this ) {
     666        __condition_criterion_t * top = this.top;
     667        if( top ) {
     668                this.top = top->next;
     669                top->next = NULL;
     670        }
     671        return top;
     672}
     673
    613674// Local Variables: //
    614675// mode: c //
  • src/libcfa/concurrency/monitor

    rd5a52cc r1393df07  
    3434        this.recursion     = 0;
    3535        this.mask.accepted = NULL;
    36         this.mask.data     = NULL;
     36        this.mask.clauses  = NULL;
    3737        this.mask.size     = 0;
    3838        this.dtor_node     = NULL;
     
    4040
    4141struct monitor_guard_t {
    42         monitor_desc **         m;
    43         __lock_size_t           count;
    44         __monitor_group_t prev;
     42        monitor_desc ** m;
     43        __lock_size_t   count;
     44        monitor_desc ** prev_mntrs;
     45        __lock_size_t   prev_count;
     46        fptr_t          prev_func;
    4547};
    4648
     
    4951
    5052struct monitor_dtor_guard_t {
    51         monitor_desc *    m;
    52         __monitor_group_t prev;
     53        monitor_desc * m;
     54        monitor_desc ** prev_mntrs;
     55        __lock_size_t   prev_count;
     56        fptr_t          prev_func;
    5357};
    5458
     
    7983};
    8084
    81 static inline __condition_criterion_t * & get_next( __condition_criterion_t & this ) {
    82         return this.next;
    83 }
    84 
    8585struct __condition_node_t {
    8686        // Thread that needs to be woken when all criteria are met
     
    100100};
    101101
    102 static inline __condition_node_t * & get_next( __condition_node_t & this ) {
    103         return this.next;
    104 }
     102struct __condition_blocked_queue_t {
     103        __condition_node_t * head;
     104        __condition_node_t ** tail;
     105};
    105106
    106107void ?{}(__condition_node_t & this, thread_desc * waiting_thread, __lock_size_t count, uintptr_t user_info );
     
    108109void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t * owner );
    109110
     111void ?{}( __condition_blocked_queue_t & );
     112void append( __condition_blocked_queue_t &, __condition_node_t * );
     113__condition_node_t * pop_head( __condition_blocked_queue_t & );
     114
    110115struct condition {
    111116        // Link list which contains the blocked threads as-well as the information needed to unblock them
    112         __queue_t(__condition_node_t) blocked;
     117        __condition_blocked_queue_t blocked;
    113118
    114119        // Array of monitor pointers (Monitors are NOT contiguous in memory)
  • src/libcfa/concurrency/monitor.c

    rd5a52cc r1393df07  
    280280static inline void enter( __monitor_group_t monitors ) {
    281281        for( __lock_size_t i = 0; i < monitors.size; i++) {
    282                 __enter_monitor_desc( monitors[i], monitors );
     282                __enter_monitor_desc( monitors.list[i], monitors );
    283283        }
    284284}
     
    303303
    304304        // Save previous thread context
    305         this.prev = this_thread->monitors;
     305        this.[prev_mntrs, prev_count, prev_func] = this_thread->monitors.[list, size, func];
    306306
    307307        // Update thread context (needed for conditions)
    308         (this_thread->monitors){m, count, func};
     308        this_thread->monitors.[list, size, func] = [m, count, func];
    309309
    310310        // LIB_DEBUG_PRINT_SAFE("MGUARD : enter %d\n", count);
     
    328328
    329329        // Restore thread context
    330         this_thread->monitors = this.prev;
     330        this_thread->monitors.[list, size, func] = this.[prev_mntrs, prev_count, prev_func];
    331331}
    332332
     
    338338
    339339        // Save previous thread context
    340         this.prev = this_thread->monitors;
     340        this.[prev_mntrs, prev_count, prev_func] = this_thread->monitors.[list, size, func];
    341341
    342342        // Update thread context (needed for conditions)
    343         (this_thread->monitors){m, 1, func};
     343        this_thread->monitors.[list, size, func] = [m, 1, func];
    344344
    345345        __enter_monitor_dtor( this.m, func );
     
    352352
    353353        // Restore thread context
    354         this_thread->monitors = this.prev;
     354        this_thread->monitors.[list, size, func] = this.[prev_mntrs, prev_count, prev_func];
    355355}
    356356
     
    437437
    438438                for(int i = 0; i < this.monitor_count; i++) {
    439                         if ( this.monitors[i] != this_thrd->monitors[i] ) {
    440                                 abortf( "Signal on condition %p made with different monitor, expected %p got %i", &this, this.monitors[i], this_thrd->monitors[i] );
     439                        if ( this.monitors[i] != this_thrd->monitors.list[i] ) {
     440                                abortf( "Signal on condition %p made with different monitor, expected %p got %i", &this, this.monitors[i], this_thrd->monitors.list[i] );
    441441                        }
    442442                }
     
    510510                "Possible cause is not checking if the condition is empty before reading stored data."
    511511        );
    512         return ((typeof(this.blocked.head))this.blocked.head)->user_info;
     512        return this.blocked.head->user_info;
    513513}
    514514
     
    554554                if( next ) {
    555555                        *mask.accepted = index;
    556                         __acceptable_t& accepted = mask[index];
    557                         if( accepted.is_dtor ) {
     556                        if( mask.clauses[index].is_dtor ) {
    558557                                LIB_DEBUG_PRINT_BUFFER_LOCAL( "Kernel : dtor already there\n");
    559                                 verifyf( accepted.size == 1, "ERROR: Accepted dtor has more than 1 mutex parameter." );
    560 
    561                                 monitor_desc * mon2dtor = accepted[0];
     558                                verifyf( mask.clauses[index].size == 1        , "ERROR: Accepted dtor has more than 1 mutex parameter." );
     559
     560                                monitor_desc * mon2dtor = mask.clauses[index].list[0];
    562561                                verifyf( mon2dtor->dtor_node, "ERROR: Accepted monitor has no dtor_node." );
    563562
     
    597596
    598597                        LIB_DEBUG_PRINT_BUFFER_LOCAL( "Kernel : accepted %d\n", *mask.accepted);
     598
    599599                        return;
    600600                }
     
    671671static inline void reset_mask( monitor_desc * this ) {
    672672        this->mask.accepted = NULL;
    673         this->mask.data = NULL;
     673        this->mask.clauses = NULL;
    674674        this->mask.size = 0;
    675675}
     
    697697
    698698static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & group ) {
    699         __acceptable_t * it = this->mask.data; // Optim
     699        __acceptable_t * it = this->mask.clauses; // Optim
    700700        __lock_size_t count = this->mask.size;
    701701
     
    820820        if( !this.monitors ) {
    821821                // LIB_DEBUG_PRINT_SAFE("Branding\n");
    822                 assertf( thrd->monitors.data != NULL, "No current monitor to brand condition %p", thrd->monitors.data );
     822                assertf( thrd->monitors.list != NULL, "No current monitor to brand condition %p", thrd->monitors.list );
    823823                this.monitor_count = thrd->monitors.size;
    824824
    825825                this.monitors = (monitor_desc **)malloc( this.monitor_count * sizeof( *this.monitors ) );
    826826                for( int i = 0; i < this.monitor_count; i++ ) {
    827                         this.monitors[i] = thrd->monitors[i];
     827                        this.monitors[i] = thrd->monitors.list[i];
    828828                }
    829829        }
     
    832832static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t & mask, monitor_desc * monitors [], __lock_size_t count ) {
    833833
    834         __queue_t(thread_desc) & entry_queue = monitors[0]->entry_queue;
     834        __thread_queue_t & entry_queue = monitors[0]->entry_queue;
    835835
    836836        // For each thread in the entry-queue
     
    841841                // For each acceptable check if it matches
    842842                int i = 0;
    843                 __acceptable_t * end   = end  (mask);
    844                 __acceptable_t * begin = begin(mask);
    845                 for( __acceptable_t * it = begin; it != end; it++, i++ ) {
     843                __acceptable_t * end = mask.clauses + mask.size;
     844                for( __acceptable_t * it = mask.clauses; it != end; it++, i++ ) {
    846845                        // Check if we have a match
    847846                        if( *it == (*thrd_it)->monitors ) {
     
    873872        __lock_size_t max = 0;
    874873        for( __lock_size_t i = 0; i < mask.size; i++ ) {
    875                 __acceptable_t & accepted = mask[i];
    876                 max += accepted.size;
     874                max += mask.clauses[i].size;
    877875        }
    878876        return max;
     
    882880        __lock_size_t size = 0;
    883881        for( __lock_size_t i = 0; i < mask.size; i++ ) {
    884                 __acceptable_t & accepted = mask[i];
    885                 __libcfa_small_sort( accepted.data, accepted.size );
    886                 for( __lock_size_t j = 0; j < accepted.size; j++) {
    887                         insert_unique( storage, size, accepted[j] );
     882                __libcfa_small_sort( mask.clauses[i].list, mask.clauses[i].size );
     883                for( __lock_size_t j = 0; j < mask.clauses[i].size; j++) {
     884                        insert_unique( storage, size, mask.clauses[i].list[j] );
    888885                }
    889886        }
     
    891888        __libcfa_small_sort( storage, size );
    892889        return size;
     890}
     891
     892void ?{}( __condition_blocked_queue_t & this ) {
     893        this.head = NULL;
     894        this.tail = &this.head;
     895}
     896
     897void append( __condition_blocked_queue_t & this, __condition_node_t * c ) {
     898        verify(this.tail != NULL);
     899        *this.tail = c;
     900        this.tail = &c->next;
     901}
     902
     903__condition_node_t * pop_head( __condition_blocked_queue_t & this ) {
     904        __condition_node_t * head = this.head;
     905        if( head ) {
     906                this.head = head->next;
     907                if( !head->next ) {
     908                        this.tail = &this.head;
     909                }
     910                head->next = NULL;
     911        }
     912        return head;
    893913}
    894914
  • src/libcfa/exception.h

    rd5a52cc r1393df07  
    1717
    1818
    19 #ifdef __cforall
     19#ifdef __CFORALL__
    2020extern "C" {
    2121#endif
     
    6868struct __cfaehm__cleanup_hook {};
    6969
    70 #ifdef __cforall
     70#ifdef __CFORALL__
    7171}
    7272#endif
  • src/libcfa/stdhdr/assert.h

    rd5a52cc r1393df07  
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
    6 //
    7 // assert.h --
    8 //
     6// 
     7// assert.h -- 
     8// 
    99// Author           : Peter A. Buhr
    1010// Created On       : Mon Jul  4 23:25:26 2016
     
    1212// Last Modified On : Mon Jul 31 23:09:32 2017
    1313// Update Count     : 13
    14 //
     14// 
    1515
    16 #ifdef __cforall
     16#ifdef __CFORALL__
    1717extern "C" {
    18 #endif //__cforall
     18#endif //__CFORALL__
    1919
    2020#include_next <assert.h>
     
    3030#endif
    3131
    32 #ifdef __cforall
     32#ifdef __CFORALL__
    3333} // extern "C"
    34 #endif //__cforall
     34#endif //__CFORALL__
    3535
    3636// Local Variables: //
  • src/libcfa/virtual.h

    rd5a52cc r1393df07  
    1616#pragma once
    1717
    18 #ifdef __cforall
     18#ifdef __CFORALL__
    1919extern "C" {
    2020#endif
     
    3535                struct __cfa__parent_vtable const * const * child );
    3636
    37 #ifdef __cforall
     37#ifdef __CFORALL__
    3838}
    3939#endif
  • src/tests/Makefile.am

    rd5a52cc r1393df07  
    1111## Created On       : Sun May 31 09:08:15 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Mon Nov 27 21:34:33 2017
    14 ## Update Count     : 48
     13## Last Modified On : Tue Oct 10 14:04:40 2017
     14## Update Count     : 47
    1515###############################################################################
    1616
     
    118118        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
    119119
    120 functions: functions.c @CFA_BINDIR@/@CFA_NAME@
    121         ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
    122 
    123120KRfunctions : KRfunctions.c @CFA_BINDIR@/@CFA_NAME@
    124121        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
  • src/tests/Makefile.in

    rd5a52cc r1393df07  
    871871        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
    872872
    873 functions: functions.c @CFA_BINDIR@/@CFA_NAME@
    874         ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
    875 
    876873KRfunctions : KRfunctions.c @CFA_BINDIR@/@CFA_NAME@
    877874        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
  • src/tests/designations.c

    rd5a52cc r1393df07  
    1717// In particular, since the syntax for designations in Cforall differs from that of C, preprocessor substitution
    1818// is used for the designation syntax
    19 #ifdef __cforall
     19#ifdef __CFORALL__
    2020#define DES :
    2121#else
  • src/tests/functions.c

    rd5a52cc r1393df07  
    1010// Created On       : Wed Aug 17 08:39:58 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Nov 27 18:08:54 2017
    13 // Update Count     : 11
     12// Last Modified On : Wed Aug 17 08:40:52 2016
     13// Update Count     : 1
    1414//
    1515
     
    6666// Cforall extensions
    6767
    68 // [] f( );
     68[] f( );
    6969[int] f( );
    70 // [] f(int);
     70[] f(int);
    7171[int] f(int);
    72 // [] f( ) {}
     72[] f( ) {}
    7373[int] f( ) {}
    74 // [] f(int) {}
     74[] f(int) {}
    7575[int] f(int) {}
    7676
    7777[int x] f( );
    78 // [] f(int x);
    79 //[int x] f(int x);
    80 //[int x] f( ) {}
    81 // [] f(int x) {}
    82 //[int x] f(int x) {}
     78[] f(int x);
     79[int x] f(int x);
     80[int x] f( ) {}
     81[] f(int x) {}
     82[int x] f(int x) {}
    8383
    8484[int, int x] f( );
    85 // [] f(int, int x);
     85[] f(int, int x);
    8686[int, int x] f(int, int x);
    8787[int, int x] f( ) {}
    88 // [] f(int, int x) {}
     88[] f(int, int x) {}
    8989[int, int x] f(int, int x) {}
    9090
    9191[int, int x, int] f( );
    92 // [] f(int, int x, int);
     92[] f(int, int x, int);
    9393[int, int x, int] f(int, int x, int);
    9494[int, int x, int] f( ) {}
    95 // [] f(int, int x, int) {}
     95[] f(int, int x, int) {}
    9696[int, int x, int] f(int, int x, int) {}
    9797
    9898[int, int x, * int y] f( );
    99 // [] f(int, int x, * int y);
     99[] f(int, int x, * int y);
    100100[int, int x, * int y] f(int, int x, * int y);
    101101[int, int x, * int y] f( ) {}
    102 // [] f(int, int x, * int y) {}
     102[] f(int, int x, * int y) {}
    103103[int, int x, * int y] f(int, int x, * int y) {}
    104104
    105 // function prototypes
    106 
    107 [ int ] f11( int ), f12();  // => int f11( int ), f12( void );
    108 
    109 const double bar1(), bar2( int ), bar3( double );               // C version
    110 [const double] foo(), foo( int ), foo( double ) { return 3.0; } // CFA version
    111 struct S { int i; };
    112 [S] rtn( int ) {}
    113 
     105[ int ] f11( int ), f12;  // => int f11( int ), f12( int );
    114106
    115107[int] f(
     
    117109        [int](int)
    118110        ) {
    119         int (*(*pc)[][10])[][3];
     111        int (*(*p)[][10])[][3];
    120112        * [][10] * [][3] int p;
    121113        * [] * [int](int) p;
Note: See TracChangeset for help on using the changeset viewer.