Changeset 7d18733
- Timestamp:
- Feb 15, 2022, 2:50:07 PM (3 years ago)
- Branches:
- ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum
- Children:
- 6dc17a3d
- Parents:
- 1a0b600 (diff), a38bbbc (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/user/user.tex
r1a0b600 r7d18733 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : S un Oct 10 12:45:00 202114 %% Update Count : 5 09513 %% Last Modified On : Sat Feb 12 17:04:03 2022 14 %% Update Count : 5376 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 17 17 % requires tex packages: texlive-base texlive-latex-base tex-common texlive-humanities texlive-latex-extra texlive-fonts-recommended 18 18 19 \documentclass[twoside ,11pt]{article}19 \documentclass[twoside]{article} 20 20 21 21 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 40 40 % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_ 41 41 % green highlighting ¢...¢ (cent symbol) emacs: C-q M-" 42 % LaTex escape §...§ (section symbol) emacs: C-q M-'42 % LaTex escape ...§ (section symbol) emacs: C-q M-' 43 43 % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^ 44 44 % math escape $...$ (dollar symbol) … … 85 85 \newcommand{\B}[1]{{\Textbf[blue]{#1}}} 86 86 \newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}} 87 \newcommand{\Sp}{\R{\textvisiblespace}} 87 88 \newcommand{\KWC}{K-W C\xspace} 88 89 … … 156 157 One of the main design philosophies of \CFA is to ``\Index{describe not prescribe}'', which means \CFA tries to provide a pathway from low-level C programming to high-level \CFA programming, but it does not force programmers to ``do the right thing''. 157 158 Programmers can cautiously add \CFA extensions to their C programs in any order and at any time to incrementally move towards safer, higher-level programming. 158 A programmer is always free to reach back to C from \CFA, for any reason, and in many cases, new \CFA features can be locally switched back to the reC counterpart.159 There is no notion or requirement for \emph{rewriting} a legacy C program in\CFA;159 A programmer is always free to reach back to C from \CFA, for any reason, and in many cases, new \CFA features can be locally switched back to their C counterpart. 160 There is no notion or requirement for \emph{rewriting} a legacy C program to \CFA; 160 161 instead, a programmer evolves a legacy program into \CFA by incrementally incorporating \CFA features. 161 162 As well, new programs can be written in \CFA using a combination of C and \CFA features. … … 163 164 164 165 \Index*[C++]{\CC{}}~\cite{c++:v1} had a similar goal 30 years ago, allowing object-oriented programming to be incrementally added to C. 165 However, \CC currently has the disadvantages of a strong object-oriented bias, multiple legacy design-choices that cannot be updated, and active divergence of the language model from C, requiring significant effort and training to incrementally add \CC to a C-based project.166 However, \CC currently has the disadvantages of a strong object-oriented bias, multiple legacy design-choices that are difficult to update, and active divergence of the language model from C, requiring significant effort and training to incrementally add \CC to a C-based project. 166 167 In contrast, \CFA has 30 years of hindsight and a clean starting point. 167 168 168 169 Like \Index*[C++]{\CC{}}, there may be both old and new ways to achieve the same effect. 169 170 For example, the following programs compare the C, \CFA, and \CC I/O mechanisms, where the programs output the same result. 170 \begin{ center}171 \begin{flushleft} 171 172 \begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}} 172 \multicolumn{1}{ c@{\hspace{1em}}}{\textbf{C}} & \multicolumn{1}{c}{\textbf{\CFA}} & \multicolumn{1}{c}{\textbf{\CC}} \\173 \begin{cfa} 173 \multicolumn{1}{@{}c@{\hspace{1em}}}{\textbf{C}} & \multicolumn{1}{c}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{\CC}} \\ 174 \begin{cfa}[tabsize=3] 174 175 #include <stdio.h>$\indexc{stdio.h}$ 175 176 … … 180 181 \end{cfa} 181 182 & 182 \begin{cfa} 183 \begin{cfa}[tabsize=3] 183 184 #include <fstream>$\indexc{fstream}$ 184 185 … … 189 190 \end{cfa} 190 191 & 191 \begin{cfa} 192 \begin{cfa}[tabsize=3] 192 193 #include <iostream>$\indexc{iostream}$ 193 194 using namespace std; 194 195 int main() { 195 196 int x = 0, y = 1, z = 2; 196 ®cout <<x<<" "<<y<<" "<<z<<endl;®197 ®cout << x << ' ' << y << ' ' << z << endl;® 197 198 } 198 199 \end{cfa} 199 200 \end{tabular} 200 \end{ center}201 \end{flushleft} 201 202 While \CFA I/O \see{\VRef{s:StreamIOLibrary}} looks similar to \Index*[C++]{\CC{}}, there are important differences, such as automatic spacing between variables and an implicit newline at the end of the expression list, similar to \Index*{Python}~\cite{Python}. 202 203 … … 238 239 however, it largely extended the C language, and did not address many of C's existing problems.\footnote{% 239 240 Two important existing problems addressed were changing the type of character literals from ©int© to ©char© and enumerator from ©int© to the type of its enumerators.} 240 \Index*{Fortran}~\cite{Fortran08}, \Index*{ Ada}~\cite{Ada12}, and \Index*{Cobol}~\cite{Cobol14} are examples of programming languages that took an evolutionary approach, where modern language-features (\eg objects, concurrency) are added and problems fixed within the framework of the existing language.241 \Index*{Fortran}~\cite{Fortran08}, \Index*{Cobol}~\cite{Cobol14}, and \Index*{Ada}~\cite{Ada12} are examples of programming languages that took an evolutionary approach, where modern language-features (\eg objects, concurrency) are added and problems fixed within the framework of the existing language. 241 242 \Index*{Java}~\cite{Java8}, \Index*{Go}~\cite{Go}, \Index*{Rust}~\cite{Rust} and \Index*{D}~\cite{D} are examples of the revolutionary approach for modernizing C/\CC, resulting in a new language rather than an extension of the descendent. 242 243 These languages have different syntax and semantics from C, do not interoperate directly with C, and are not systems languages because of restrictive memory-management or garbage collection. … … 333 334 long double _Complex ®abs®( long double _Complex ); 334 335 \end{cfa} 335 The problem is \Index{name clash} between the C name ©abs© and the \CFA names ©abs©, resulting in two name linkages\index{C linkage}: ©extern "C"© and ©extern "Cforall"© (default).336 The problem is a \Index{name clash} between the C name ©abs© and the \CFA names ©abs©, resulting in two name linkages\index{C linkage}: ©extern "C"© and ©extern "Cforall"© (default). 336 337 Overloaded names must use \newterm{name mangling}\index{mangling!name} to create unique names that are different from unmangled C names. 337 338 Hence, there is the same need as in \CC to know if a name is a C or \CFA name, so it can be correctly formed. … … 377 378 The program is linked with the debugging version of the runtime system. 378 379 The debug version performs runtime checks to aid the debugging phase of a \CFA program, but can substantially slow program execution. 379 The runtime checks should only be removed after theprogram is completely debugged.380 The runtime checks should only be removed after a program is completely debugged. 380 381 \textbf{This option is the default.} 381 382 … … 452 453 cfa $test$.cfa -XCFA -P -XCFA parse -XCFA -n # show program parse without prelude 453 454 \end{lstlisting} 455 Alternatively, multiple flages can be specified separated with commas and \emph{without} spaces. 456 \begin{lstlisting}[language=sh,{moredelim=**[is][\protect\color{red}]{®}{®}}] 457 cfa $test$.cfa -XCFA®,®-Pparse®,®-n # show program parse without prelude 458 \end{lstlisting} 454 459 \begin{description}[topsep=5pt,itemsep=0pt,parsep=0pt] 455 460 \item … … 533 538 double ®``®forall = 3.5; 534 539 \end{cfa} 535 536 Existing C programs with keyword clashes can be converted by enclosing keyword identifiers in backquotes, and eventually the identifier name can be changed to a non-keyword name. 540 Existing C programs with keyword clashes can be converted by prefixing the keyword identifiers with double backquotes, and eventually the identifier name can be changed to a non-keyword name. 537 541 \VRef[Figure]{f:HeaderFileInterposition} shows how clashes in existing C header-files \see{\VRef{s:StandardHeaders}} can be handled using preprocessor \newterm{interposition}: ©#include_next© and ©-I filename©. 538 542 Several common C header-files with keyword clashes are fixed in the standard \CFA header-library, so there is a seamless programming-experience. … … 627 631 \subsection{\texorpdfstring{\LstKeywordStyle{if} / \LstKeywordStyle{while} Statement}{if / while Statement}} 628 632 629 The ©if©/©while© expression allows declarations, similar to ©for©declaration expression.\footnote{630 Declarations in the ©do©-©while© condition are not useful because they appear after the loop body.}633 The \Indexc{if}/\Indexc{while} expression allows declarations, similar to \Indexc{for} declaration expression.\footnote{ 634 Declarations in the \Indexc{do}-©while© condition are not useful because they appear after the loop body.} 631 635 \begin{cfa} 632 636 if ( ®int x = f()® ) ... $\C{// x != 0}$ … … 640 644 while ( ®struct S { int i; } x = { f() }; x.i < 4® ) ... $\C{// relational expression}$ 641 645 \end{cfa} 642 Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the ©if©/©while© expression, and the results are combined using the logical ©&&©operator.643 The scope of the declaration(s) is local to the ©if© statement but exist within both the \emph{then} and \emph{else} clauses.646 Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the ©if©/©while© expression, and the results are combined using the logical \Indexc{&&} operator. 647 The scope of the declaration(s) is local to the ©if©/©while© statement, \ie in both \emph{then} and \emph{else} clauses for ©if©, and loop body for ©while©. 644 648 \CC only provides a single declaration always compared ©!=© to 0. 645 649 … … 649 653 \label{s:caseClause} 650 654 651 C restricts the ©case© clause of a ©switch©statement to a single value.655 C restricts the \Indexc{case} clause of a \Indexc{switch} statement to a single value. 652 656 For multiple ©case© clauses associated with the same statement, it is necessary to have multiple ©case© clauses rather than multiple values. 653 Requiring a ©case© clause for each value does not seem to bein the spirit of brevity normally associated with C.654 Therefore, the ©case© clause is extended with a list of values , as in:657 Requiring a ©case© clause for each value is not in the spirit of brevity normally associated with C. 658 Therefore, the ©case© clause is extended with a list of values. 655 659 \begin{cquote} 656 660 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}} … … 703 707 \subsection{\texorpdfstring{\LstKeywordStyle{switch} Statement}{switch Statement}} 704 708 705 C allows a number of questionable forms for the ©switch©statement:709 C allows a number of questionable forms for the \Indexc{switch} statement: 706 710 \begin{enumerate} 707 711 \item 708 By default, the end of a ©case©clause\footnote{712 By default, the end of a \Indexc{case} clause\footnote{ 709 713 In this section, the term \emph{case clause} refers to either a ©case© or ©default© clause.} 710 714 \emph{falls through} to the next ©case© clause in the ©switch© statement; 711 to exit a ©switch© statement from a ©case© clause requires explicitly terminating the clause with a transfer statement, most commonly ©break©:715 to exit a ©switch© statement from a ©case© clause requires explicitly terminating the clause with a transfer statement, most commonly \Indexc{break}: 712 716 \begin{cfa} 713 717 switch ( i ) { 714 718 case 1: 715 719 ... 716 // fall-through720 $\R{\LstCommentStyle{// fall-through}}$ 717 721 case 2: 718 722 ... 719 break;// exit switch statement723 ®break;® // exit switch statement 720 724 } 721 725 \end{cfa} … … 763 767 } 764 768 \end{cfa} 765 This situation better handled without fall-through by allowinga list of case values \see{\VRef{s:caseClause}}.769 This situation is better handled by a list of case values \see{\VRef{s:caseClause}}. 766 770 While fall-through itself is not a problem, the problem occurs when fall-through is the default, as this semantics is unintuitive to many programmers and is different from most programming languages with a ©switch© statement. 767 771 Hence, default fall-through semantics results in a large number of programming errors as programmers often \emph{forget} the ©break© statement at the end of a ©case© clause, resulting in inadvertent fall-through. … … 777 781 ... 778 782 } // if 779 case 2:780 while ( j < 5 ) {781 ...782 ®case 3:® // transfer into "while" statement783 ...784 } // while785 } // switch786 783 \end{cfa} 787 784 This usage branches into control structures, which is known to cause both comprehension and technical difficulties. … … 789 786 The technical problem results from the inability to ensure declaration and initialization of variables when blocks are not entered at the beginning. 790 787 There are few arguments for this kind of control flow, and therefore, there is a strong impetus to eliminate it. 791 Nevertheless, C does have an idiom where this capability is used, known as ``\Index*{Duff's device}''~\cite{Duff83}: 788 789 This C idiom is known as ``\Index*{Duff's device}''~\cite{Duff83}, from this example: 792 790 \begin{cfa} 793 791 register int n = (count + 7) / 8; … … 858 856 still works. 859 857 Nevertheless, reversing the default action would have a non-trivial effect on case actions that compound, such as the above example of processing shell arguments. 860 Therefore, to preserve backwards compatibility, it is necessary to introduce a new kind of ©switch© statement, called ©choose©, with no implicit fall-through semantics and an explicit fall-through if the last statement of a case-clause ends with the new keyword ©fallthrough©/©fallthru©, \eg:858 Therefore, to preserve backwards compatibility, it is necessary to introduce a new kind of ©switch© statement, called \Indexc{choose}, with no implicit fall-through semantics and an explicit fall-through if the last statement of a case-clause ends with the new keyword \Indexc{fallthrough}/\Indexc{fallthru}, \eg: 861 859 \begin{cfa} 862 860 ®choose® ( i ) { … … 885 883 Therefore, no change is made for this issue. 886 884 \item 887 Dealing with unreachable code in a ©switch©/©choose© body is solved by restricting declarations and associatedinitialization to the start of statement body, which is executed \emph{before} the transfer to the appropriate ©case© clause\footnote{885 Dealing with unreachable code in a ©switch©/©choose© body is solved by restricting declarations and initialization to the start of statement body, which is executed \emph{before} the transfer to the appropriate ©case© clause\footnote{ 888 886 Essentially, these declarations are hoisted before the ©switch©/©choose© statement and both declarations and statement are surrounded by a compound statement.} and precluding statements before the first ©case© clause. 889 887 Further declarations at the same nesting level as the statement body are disallowed to ensure every transfer into the body is sound. … … 908 906 \subsection{Non-terminating and Labelled \texorpdfstring{\LstKeywordStyle{fallthrough}}{Non-terminating and Labelled fallthrough}} 909 907 910 The ©fallthrough© clause may be non-terminating within a ©case©clause or have a target label to common code from multiple case clauses.908 The \Indexc{fallthrough} clause may be non-terminating within a \Indexc{case} clause or have a target label to common code from multiple case clauses. 911 909 \begin{center} 912 910 \begin{tabular}{@{}lll@{}} … … 960 958 \end{tabular} 961 959 \end{center} 962 The target label must be below the ©fallthrough©and may not be nested in a control structure, and963 the target label must be at the same or higher level as the containing ©case©clause and located at964 the same level as a ©case© clause; the target label may be case ©default©, but only associated965 with the current ©switch©/©choose©statement.960 The target label must be below the \Indexc{fallthrough} and may not be nested in a control structure, and 961 the target label must be at the same or higher level as the containing \Indexc{case} clause and located at 962 the same level as a ©case© clause; the target label may be case \Indexc{default}, but only associated 963 with the current \Indexc{switch}/\Indexc{choose} statement. 966 964 967 965 \begin{figure} … … 1076 1074 Looping a fixed number of times, possibly with a loop index, occurs frequently. 1077 1075 \CFA condenses simply looping to facilitate coding speed and safety. 1078 The ©for©/©while©/©do-while©loop-control is augmented as follows \see{examples in \VRef[Figure]{f:LoopControlExamples}}:1076 The \Indexc{for}, \Indexc{while}, and \Indexc{do} loop-control is augmented as follows \see{examples in \VRef[Figure]{f:LoopControlExamples}}: 1079 1077 \begin{itemize}[itemsep=0pt] 1080 1078 \item … … 1145 1143 \subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}} 1146 1144 1147 C ©continue© and ©break©statements, for altering control flow, are restricted to one level of nesting for a particular control structure.1145 C \Indexc{continue} and \Indexc{break} statements, for altering control flow, are restricted to one level of nesting for a particular control structure. 1148 1146 This restriction forces programmers to use \Indexc{goto} to achieve the equivalent control-flow for more than one level of nesting. 1149 1147 To prevent having to switch to the ©goto©, \CFA extends the \Indexc{continue}\index{continue@©continue©!labelled}\index{labelled!continue@©continue©} and \Indexc{break}\index{break@©break©!labelled}\index{labelled!break@©break©} with a target label to support static multi-level exit\index{multi-level exit}\index{static multi-level exit}~\cite{Buhr85}, as in Java. 1150 For both ©continue© and ©break©, the target label must be directly associated with a ©for©, ©while© or ©do©statement;1151 for ©break©, the target label can also be associated with a ©switch©, ©if©or compound (©{}©) statement.1148 For both ©continue© and ©break©, the target label must be directly associated with a \Indexc{for}, \Indexc{while} or \Indexc{do} statement; 1149 for ©break©, the target label can also be associated with a \Indexc{switch}, \Indexc{if} or compound (©{}©) statement. 1152 1150 \VRef[Figure]{f:MultiLevelExit} shows a comparison between labelled ©continue© and ©break© and the corresponding C equivalent using ©goto© and labels. 1153 1151 The innermost loop has 8 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s. … … 1224 1222 \end{figure} 1225 1223 1226 Both labelled ©continue© and ©break© are a ©goto©\index{goto@©goto©!restricted} restricted in the following ways:1224 Both labelled \Indexc{continue} and \Indexc{break} are a \Indexc{goto}\index{goto@©goto©!restricted} restricted in the following ways: 1227 1225 \begin{itemize} 1228 1226 \item … … 1240 1238 1241 1239 1240 \subsection{\texorpdfstring{Extended \LstKeywordStyle{else}}{Extended else}} 1241 \label{s:ExtendedElse} 1242 \index{extended ©else©} 1243 1244 The ©if© statement has an optional ©else© clause executed if the conditional is false. 1245 This concept is extended to the \Indexc{while}, \Indexc{for}, and \Indexc{do} looping constructs (like Python). 1246 Hence, if the loop conditional becomes false, looping stops and the corresponding ©else© clause is executed, if present. 1247 1248 The following example is a linear search for the key 3 in an array, where finding the key is handled with a ©break© and not finding with the ©else© clause on the loop construct. 1249 \begin{cquote} 1250 \begin{cfa} 1251 int a[10]; 1252 \end{cfa} 1253 \begin{tabular}{@{}lll@{}} 1254 \begin{cfa} 1255 1256 while ( int i = 0; i < 10 ) { 1257 if ( a[i] == 3 ) break; // found 1258 i += 1; 1259 } ®else® { // i == 10 1260 sout | "not found"; 1261 } 1262 \end{cfa} 1263 & 1264 \begin{cfa} 1265 1266 for ( i; 10 ) { 1267 if ( a[i] == 3 ) break; // found 1268 1269 } ®else® { // i == 10 1270 sout | "not found"; 1271 } 1272 \end{cfa} 1273 & 1274 \begin{cfa} 1275 int i = 0; 1276 do { 1277 if ( a[i] == 3 ) break; // found 1278 i += 1; 1279 } while( i < 10 ) ®else® { // i == 10 1280 sout | "not found"; 1281 } 1282 \end{cfa} 1283 \end{tabular} 1284 \end{cquote} 1285 Note, \Index{dangling else} now occurs with \Indexc{if}, \Indexc{while}, \Indexc{for}, \Indexc{do}, and \Indexc{waitfor}. 1286 1287 1242 1288 %\subsection{\texorpdfstring{\protect\lstinline{with} Statement}{with Statement}} 1243 1289 \subsection{\texorpdfstring{\LstKeywordStyle{with} Statement}{with Statement}} … … 1266 1312 Therefore, reducing aggregate qualification is a useful language design goal. 1267 1313 1268 C allows unnamed nested aggregates thatopen their scope into the containing aggregate.1314 C partially addresses the problem by eliminating qualification for enumerated types and unnamed \emph{nested} aggregates, which open their scope into the containing aggregate. 1269 1315 This feature is used to group fields for attributes and/or with ©union© aggregates. 1270 1316 \begin{cfa} 1271 1317 struct S { 1272 struct { int g, h; } __attribute__(( aligned(64) ));1318 struct $\R{\LstCommentStyle{/* unnamed */}}$ { int g, h; } __attribute__(( aligned(64) )); 1273 1319 int tag; 1274 union {1320 union $\R{\LstCommentStyle{/* unnamed */}}$ { 1275 1321 struct { char c1, c2; } __attribute__(( aligned(128) )); 1276 1322 struct { int i1, i2; }; 1277 1323 struct { double d1, d2; }; 1278 1324 }; 1279 }; 1280 s.g; s.h; s.tag; s.c1; s.c2; s.i1; s.i2; s.d1; s.d2; 1325 } s; 1326 enum { R, G, B }; 1327 s.g; s.h; s.tag = R; s.c1; s.c2; s.i1 = G; s.i2 = B; s.d1; s.d2; 1281 1328 \end{cfa} 1282 1329 … … 1323 1370 \end{cfa} 1324 1371 where qualification is only necessary to disambiguate the shadowed variable ©i©. 1325 1326 In detail, the ©with© statement may appear as the body of a function or nested within a function body. 1372 In detail, the ©with© statement may form a function body or be nested within a function body. 1373 1327 1374 The ©with© clause takes a list of expressions, where each expression provides an aggregate type and object. 1328 1375 (Enumerations are already opened.) … … 1333 1380 \end{cfa} 1334 1381 The expression object is the implicit qualifier for the open structure-fields. 1382 1335 1383 \CFA's ability to overload variables \see{\VRef{s:VariableOverload}} and use the left-side of assignment in type resolution means most fields with the same name but different types are automatically disambiguated, eliminating qualification. 1336 1384 All expressions in the expression list are open in parallel within the compound statement. … … 1362 1410 \end{cfa} 1363 1411 A cast or qualification can be used to disambiguate variables within a ©with© \emph{statement}. 1364 A cast can be used to disambiguate among overload variables in a ©with© \emph{expression}:1412 A cast can also be used to disambiguate among overload variables in a ©with© \emph{expression}: 1365 1413 \begin{cfa} 1366 1414 with ( w ) { ... } $\C{// ambiguous, same name and no context}$ … … 1371 1419 Finally, there is an interesting problem between parameters and the function-body ©with©, \eg: 1372 1420 \begin{cfa} 1373 void ?{}( S & s, int i ) with ( s ) { $\C{// constructor}$ 1374 ®s.i = i;® j = 3; m = 5.5; $\C{// initialize fields}$ 1375 } 1376 \end{cfa} 1377 Here, the assignment ©s.i = i© means ©s.i = s.i©, which is meaningless, and there is no mechanism to qualify the parameter ©i©, making the assignment impossible using the function-body ©with©. 1378 To solve this problem, parameters are treated like an initialized aggregate: 1379 \begin{cfa} 1380 struct Params { 1381 S & s; 1382 int i; 1421 void f( S & s, char c ) with ( s ) { 1422 ®s.c = c;® i = 3; d = 5.5; $\C{// initialize fields}$ 1423 } 1424 \end{cfa} 1425 Here, the assignment ©s.c = c© means ©s.c = s.c©, which is meaningless, and there is no mechanism to qualify the parameter ©c©, making the assignment impossible using the function-body ©with©. 1426 To solve this problem, parameters \emph{not} explicitly opened are treated like an initialized aggregate: 1427 \begin{cfa} 1428 struct Params { $\C{// s explicitly opened so S \& s elided}$ 1429 char c; 1383 1430 } params; 1384 1431 \end{cfa} 1385 1432 and implicitly opened \emph{after} a function-body open, to give them higher priority: 1386 1433 \begin{cfa} 1387 void ?{}( S & s, int ®i® ) with ( s ) ®with( $\emph{\R{params}}$ )® { // syntax not allowed, illustration only1388 s. i = ®i®; j = 3; m= 5.5;1434 void f( S & s, char ®c® ) with ( s ) ®with( $\emph{\R{params}}$ )® { // syntax not allowed, illustration only 1435 s.c = ®c;® i = 3; d = 5.5; 1389 1436 } 1390 1437 \end{cfa} 1391 1438 This implicit semantic matches with programmer expectation. 1392 1393 1439 1394 1440 … … 3397 3443 This requirement is the same as for comma expressions in argument lists. 3398 3444 3399 Type qualifiers, \ie const and volatile, may modify a tuple type.3400 The meaning is t he same as for a type qualifier modifying an aggregate type [Int99, x 6.5.2.3(7),x 6.7.3(11)], \ie the qualifier is distributedacross all of the types in the tuple, \eg:3445 Type qualifiers, \ie ©const© and ©volatile©, may modify a tuple type. 3446 The meaning is to distribute the qualifier across all of the types in the tuple, \eg: 3401 3447 \begin{cfa} 3402 3448 const volatile [ int, float, const int ] x; … … 3597 3643 Stream ©exit© implicitly returns ©EXIT_FAILURE© to the shell. 3598 3644 \begin{cfa} 3599 ®exit® | "x (" | x | ") negative value."; // terminate and return EXIT_FAILURE to shell3600 ®abort® | "x (" | x | ") negative value."; // terminate and generate stack trace and core file3645 ®exit® | "x (" | x | ") negative value."; // terminate and return EXIT_FAILURE to shell 3646 ®abort® | "x (" | x | ") negative value."; // terminate and generate stack trace and core file 3601 3647 \end{cfa} 3602 3648 Note, \CFA stream variables ©stdin©, ©stdout©, ©stderr©, ©exit©, and ©abort© overload C variables ©stdin©, ©stdout©, ©stderr©, and functions ©exit© and ©abort©, respectively. … … 4267 4313 sout | '1' | '2' | '3'; 4268 4314 sout | 1 | "" | 2 | "" | 3; 4269 sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x¥"4270 | 7 | "x ¡" | 8 | "x ¿" | 9 | "x«" | 10;4315 sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x Â¥" 4316 | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10; 4271 4317 sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x" 4272 | 7 | " ¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x";4318 | 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x"; 4273 4319 sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx"; 4274 4320 sout | "x ( " | 1 | " ) x" | 2 | " , x" | 3 | " :x: " | 4; … … 4446 4492 The common usage is the short form of the mutex statement\index{ostream@©ostream©!mutex@©mutex©} to lock a stream during a single cascaded I/O expression, \eg: 4447 4493 \begin{cfa} 4448 $\emph{thread\(_1\)}$ : ®mutex( )® sout | "abc " | "def ";4449 $\emph{thread\(_2\)}$ : ®mutex( )® sout | "uvw " | "xyz ";4494 $\emph{thread\(_1\)}$ : ®mutex( sout )® sout | "abc " | "def "; 4495 $\emph{thread\(_2\)}$ : ®mutex( sout )® sout | "uvw " | "xyz "; 4450 4496 \end{cfa} 4451 4497 Now, the order of the thread execution is still non-deterministic, but the output is constrained to two possible lines in either order. … … 4470 4516 ®mutex( sout )® { 4471 4517 sout | 1; 4472 ®mutex( ) sout® | 2 | 3; $\C{// unnecessary, but ok because of recursive lock}$4518 ®mutex( sout ) sout® | 2 | 3; $\C{// unnecessary, but ok because of recursive lock}$ 4473 4519 sout | 4; 4474 4520 } // implicitly release sout lock … … 4482 4528 int x, y, z, w; 4483 4529 sin | x; 4484 ®mutex( ) sin® | y | z;$\C{// unnecessary, but ok because of recursive lock}$4530 ®mutex( sin )® sin | y | z; $\C{// unnecessary, but ok because of recursive lock}$ 4485 4531 sin | w; 4486 4532 } // implicitly release sin lock … … 4491 4537 \Textbf{WARNING:} The general problem of \Index{nested locking} can occur if routines are called in an I/O sequence that block, \eg: 4492 4538 \begin{cfa} 4493 ®mutex( ) sout®| "data:" | rtn( mon ); $\C{// mutex call on monitor}$4539 ®mutex( sout )® sout | "data:" | rtn( mon ); $\C{// mutex call on monitor}$ 4494 4540 \end{cfa} 4495 4541 If the thread executing the I/O expression blocks in the monitor with the ©sout© lock, other threads writing to ©sout© also block until the thread holding the lock is unblocked and releases it. … … 4498 4544 \begin{cfa} 4499 4545 int ®data® = rtn( mon ); 4500 mutex() sout | "data:" | ®data®; 4501 \end{cfa} 4546 mutex( sout ) sout | "data:" | ®data®; 4547 \end{cfa} 4548 4549 4550 \subsection{Locale} 4551 \index{stream!locale} 4552 \index{locale!stream} 4553 4554 Cultures use different syntax, called a \newterm{locale}, for printing numbers so they are easier to read, \eg: 4555 \begin{cfa} 4556 12®,®345®.®123 $\C[1.25in]{// comma separator, period decimal-point}$ 4557 12®.®345®,®123 $\C{// period separator, comma decimal-point}$ 4558 12$\Sp$345®,®123®.® $\C{// space separator, comma decimal-point, period terminator}\CRT$ 4559 \end{cfa} 4560 A locale is selected with function ©setlocale©, and the corresponding locale package \emph{must} be installed on the underlying system; 4561 ©setlocale© returns ©0p© if the requested locale is unavailable. 4562 Furthermore, a locale covers the syntax for many cultural items, \eg address, measurement, money, etc. 4563 This discussion applies to item ©LC_NUMERIC© for formatting non-monetary integral and floating-point values. 4564 \VRef[Figure]{f:StreamLocale} shows selecting different cultural syntax, which may be associated with one or more countries. 4565 4566 \begin{figure} 4567 \begin{cfa} 4568 #include <fstream.hfa> 4569 #include <locale.h> $\C{// setlocale}$ 4570 #include <stdlib.h> $\C{// getenv}$ 4571 4572 int main() { 4573 void print() { 4574 sout | 12 | 123 | 1234 | 12345 | 123456 | 1234567; 4575 sout | 12. | 123.1 | 1234.12 | 12345.123 | 123456.1234 | 1234567.12345; 4576 sout | nl; 4577 } 4578 sout | "Default locale off"; 4579 print(); 4580 sout | "Locale on" | ®setlocale( LC_NUMERIC, getenv( "LANG" ) )®; // enable local locale 4581 print(); 4582 sout | "German" | ®setlocale( LC_NUMERIC, "de_DE.UTF-8" )®; // enable German locale 4583 print(); 4584 sout | "Ukraine" | ®setlocale( LC_NUMERIC, "uk_UA.utf8" )®; // enable Ukraine locale 4585 print(); 4586 sout | "Default locale off" | ®setlocale( LC_NUMERIC, "C" )®; // disable locale 4587 print(); 4588 } 4589 4590 Default locale off 4591 12 123 1234 12345 123456 1234567 4592 12. 123.1 1234.12 12345.123 123456.1234 1234567.12345 4593 4594 Locale on en_US.UTF-8 4595 12 123 1®,®234 12®,®345 123®,®456 1®,®234®,®567 4596 12®.® 123®.®1 1®,®234®.®12 12®,®345®.®123 123®,®456®.®1234 1®,®234®,®567®.®12345 4597 4598 German de_DE.UTF-8 4599 12 123 1®.®234 12®.®345 123®.®456 1®.®234®.®567 4600 12®.® 123®,®1®.® 1®.®234®,®12 12®.®345®,®123 123®.®456®,®1234 1®.®234®.®567®,®12345 4601 4602 Ukraine uk_UA.utf8 4603 12 123 1 234 12 345 123 456 1 234 567 4604 12®.® 123®,®1®.® 1$\Sp$234®,®12®.® 12$\Sp$ 345®,®123®.® 123$\Sp$ 456®,®1234®.® 1$\Sp$ 234$\Sp$567®,®12345®.® 4605 4606 Default locale off C 4607 12 123 1234 12345 123456 1234567 4608 12. 123.1 1234.12 12345.123 123456.1234 1234567.12345 4609 \end{cfa} 4610 \caption{Stream Locale} 4611 \label{f:StreamLocale} 4612 \end{figure} 4502 4613 4503 4614 … … 4555 4666 \end{figure} 4556 4667 4668 4557 4669 \begin{comment} 4558 4670 \section{Types} … … 4637 4749 4638 4750 4639 \s ubsection{Structures}4751 \section{Structures} 4640 4752 4641 4753 Structures in \CFA are basically the same as structures in C. … … 5270 5382 \subsection{Coroutine} 5271 5383 5272 \Index{Coroutines} are the precursor to t asks.5384 \Index{Coroutines} are the precursor to threads. 5273 5385 \VRef[Figure]{f:FibonacciCoroutine} shows a coroutine that computes the \Index*{Fibonacci} numbers. 5274 5386 … … 5372 5484 5373 5485 5374 \subsection{T asks}5486 \subsection{Threads} 5375 5487 5376 5488 \CFA also provides a simple mechanism for creating and utilizing user level threads. 5377 A t askprovides mutual exclusion like a monitor, and also has its own execution state and a thread of control.5378 Similar to a monitor, a t askis defined like a structure:5489 A thread provides mutual exclusion like a monitor, and also has its own execution state and a thread of control. 5490 Similar to a monitor, a thread is defined like a structure: 5379 5491 5380 5492 \begin{figure} … … 5420 5532 } 5421 5533 \end{cfa} 5422 \caption{Simple T asks}5423 \label{f:SimpleT asks}5534 \caption{Simple Threads} 5535 \label{f:SimpleThreads} 5424 5536 \end{figure} 5425 5537 … … 6788 6900 In \CFA, there are ambiguous cases with dereference and operator identifiers, \eg ©int *?*?()©, where the string ©*?*?© can be interpreted as: 6789 6901 \begin{cfa} 6790 *?$\ R{\textvisiblespace}$*? $\C{// dereference operator, dereference operator}$6791 *$\ R{\textvisiblespace}$?*? $\C{// dereference, multiplication operator}$6902 *?$\Sp$*? $\C{// dereference operator, dereference operator}$ 6903 *$\Sp$?*? $\C{// dereference, multiplication operator}$ 6792 6904 \end{cfa} 6793 6905 By default, the first interpretation is selected, which does not yield a meaningful parse. … … 6813 6925 Therefore, it is necessary to disambiguate these cases with a space: 6814 6926 \begin{cfa} 6815 i++$\ R{\textvisiblespace}$? i : 0;6816 i?$\ R{\textvisiblespace}$++i : 0;6927 i++$\Sp$? i : 0; 6928 i?$\Sp$++i : 0; 6817 6929 \end{cfa} 6818 6930 … … 7430 7542 char random( void );$\indexc{random}$ 7431 7543 char random( char u ); $\C{// [0,u)}$ 7432 char random( char l, char u ); $\C{// [l,u )}$7544 char random( char l, char u ); $\C{// [l,u]}$ 7433 7545 int random( void ); 7434 7546 int random( int u ); $\C{// [0,u)}$ 7435 int random( int l, int u ); $\C{// [l,u )}$7547 int random( int l, int u ); $\C{// [l,u]}$ 7436 7548 unsigned int random( void ); 7437 7549 unsigned int random( unsigned int u ); $\C{// [0,u)}$ 7438 unsigned int random( unsigned int l, unsigned int u ); $\C{// [l,u )}$7550 unsigned int random( unsigned int l, unsigned int u ); $\C{// [l,u]}$ 7439 7551 long int random( void ); 7440 7552 long int random( long int u ); $\C{// [0,u)}$ 7441 long int random( long int l, long int u ); $\C{// [l,u )}$7553 long int random( long int l, long int u ); $\C{// [l,u]}$ 7442 7554 unsigned long int random( void ); 7443 7555 unsigned long int random( unsigned long int u ); $\C{// [0,u)}$ 7444 unsigned long int random( unsigned long int l, unsigned long int u ); $\C{// [l,u )}$7556 unsigned long int random( unsigned long int l, unsigned long int u ); $\C{// [l,u]}$ 7445 7557 float random( void ); $\C{// [0.0, 1.0)}$ 7446 7558 double random( void ); $\C{// [0.0, 1.0)}$ … … 8106 8218 8107 8219 8220 \section{Pseudo Random Number Generator} 8221 \label{s:PRNG} 8222 8223 Random numbers are values generated independently, i.e., new values do not depend on previous values (independent trials), \eg lottery numbers, shuffled cards, dice roll, coin flip. 8224 While a primary goal of programming is computing values that are \emph{not} random, random values are useful in simulation, cryptography, games, etc. 8225 A random-number generator is an algorithm computing independent values. 8226 If the algorithm uses deterministic computation (predictable sequence of values), it generates \emph{pseudo} random numbers versus \emph{true} random numbers. 8227 8228 All \newterm{pseudo random-number generators} (\newterm{PRNG}) involve some technique to scramble bits of a value, \eg multiplicative recurrence: 8229 \begin{cfa} 8230 rand = 36973 * (rand & 65535) + (rand >> 16); // scramble bits 8231 \end{cfa} 8232 Multiplication of large values adds new least-significant bits and drops most-significant bits. 8233 \begin{quote} 8234 \begin{tabular}{@{}r|l@{}} 8235 bits 63--32 (most) & bits 31--0 (least) \\ 8236 \hline 8237 0x0 & 0x3e8e36 \\ 8238 0x5f & 0x718c25e1 \\ 8239 0xad3e & 0x7b5f1dbe \\ 8240 0xbc3b & 0xac69ff19 \\ 8241 0x1070f & 0x2d258dc6 \\ 8242 \end{tabular} 8243 \end{quote} 8244 By dropping bits 63--32, bits 31--0 become scrambled after each multiply. 8245 The least-significant bits \emph{appear} random but the same bits are always generated given a fixed starting value, called the \newterm{seed} (value 0x3e8e36 above). 8246 Hence, if a program uses the same seed, the same sequence of pseudo-random values is generated from the PRNG. 8247 Often the seed is set to another random value like a program's process identifier (©getpid©\index{getpid@©getpid©}) or time when the program is run; 8248 hence, one random value bootstraps another. 8249 Finally, a PRNG usually generates a range of large values, \eg ©[0, UINT_MAX]©, which are scaled using the modulus operator, \eg ©prng() % 5© produces random values in the range 0--4. 8250 8251 \CFA provides a sequential and concurrent PRNGs. 8252 \begin{itemize} 8253 \item 8254 For sequential programs, like coroutining, the PRNG is used to randomize behaviour or values during execution, \eg in games, a character makes a random move or an object takes on a random value. 8255 \begin{cfa} 8256 struct PRNG { ... }; $\C[3.75in]{// opaque type}$ 8257 void ?{}( PRNG & prng ); $\C{// random seed}$ 8258 void ?{}( PRNG & prng, uint32_t seed ); $\C{// fixed seed}$ 8259 void set_seed( PRNG & prng, uint32_t seed ); $\C{// set seed}$ 8260 uint32_t get_seed( PRNG & prng ); $\C{// get seed}$ 8261 uint32_t prng( PRNG & prng ); $\C{// [0,UINT\_MAX]}$ 8262 uint32_t prng( PRNG & prng, uint32_t u ); $\C{// [0,u)}$ 8263 uint32_t prng( PRNG & prng, uint32_t l, uint32_t u ); $\C{// [l,u]}$ 8264 uint32_t calls( PRNG & prng ); $\C{// number of calls}\CRT$ 8265 \end{cfa} 8266 Sequential execution is repeatable given the same starting seeds for all ©PRNG©s. 8267 In this scenario, it is useful to have multiple ©PRNG©, \eg one per player or object so a type is provided to generate multiple instances. 8268 \VRef[Figure]{f:SequentialPRNG} shows an example that creates two sequential ©PRNG©s, sets both to the same seed (1009), and illustrates the three forms for generating random values, where both ©PRNG©s generate the same sequence of values. 8269 8270 \begin{figure} 8271 \begin{cfa} 8272 PRNG prng1, prng2; 8273 ®set_seed( prng1, 1009 )®; ®set_seed( prng2, 1009 )®; 8274 for ( 10 ) { 8275 // Do not cascade prng calls because side-effect functions called in arbitrary order. 8276 sout | nlOff | ®prng( prng1 )®; sout | ®prng( prng1, 5 )®; sout | ®prng( prng1, 0, 5 )® | '\t'; 8277 sout | ®prng( prng2 )®; sout | ®prng( prng2, 5 )®; sout | ®prng( prng2, 0, 5 )® | nlOn; 8278 } 8279 \end{cfa} 8280 \begin{cquote} 8281 \begin{tabular}{@{}ll@{}} 8282 \begin{cfa} 8283 37301721 2 2 8284 1681308562 1 3 8285 290112364 3 2 8286 1852700364 4 3 8287 733221210 1 3 8288 1775396023 2 3 8289 123981445 2 3 8290 2062557687 2 0 8291 283934808 1 0 8292 672325890 1 3 8293 \end{cfa} 8294 & 8295 \begin{cfa} 8296 37301721 2 2 8297 1681308562 1 3 8298 290112364 3 2 8299 1852700364 4 3 8300 733221210 1 3 8301 1775396023 2 3 8302 123981445 2 3 8303 2062557687 2 0 8304 283934808 1 0 8305 672325890 1 3 8306 \end{cfa} 8307 \end{tabular} 8308 \end{cquote} 8309 \vspace{-10pt} 8310 \caption{Sequential PRNG} 8311 \label{f:SequentialPRNG} 8312 \end{figure} 8313 8314 \item 8315 For concurrent programs, it is important the PRNG is thread-safe and not a point of contention. 8316 A PRNG in concurrent programs is often used to randomize execution in short-running programs, \eg ©yield( prng() % 5 )©. 8317 8318 Because concurrent execution is non-deterministic, seeding the concurrent PRNG is less important, as repeatable execution is impossible. 8319 Hence, there is one system-wide PRNG (global seed) but each \CFA thread has its own non-contended PRNG state. 8320 If the global seed is set, threads start with this seed, until it is reset and than threads start with the reset seed. 8321 Hence, these threads generate the same sequence of random numbers from their specific starting seed. 8322 If the global seed is \emph{not} set, threads start with a random seed, until the global seed is set. 8323 Hence, these threads generate different sequences of random numbers. 8324 If each thread needs its own seed, use a sequential ©PRNG© in each thread. 8325 8326 There are two versions of the PRNG functions to manipulate the thread-local PRNG-state, which are differentiated by performance. 8327 \begin{cfa} 8328 void set_seed( uint32_t seed ); $\C[3.75in]{// set global seed}$ 8329 uint32_t get_seed(); $\C{// get global seed}$ 8330 // SLOWER 8331 uint32_t prng(); $\C{// [0,UINT\_MAX]}$ 8332 uint32_t prng( uint32_t u ); $\C{// [0,u)}$ 8333 uint32_t prng( uint32_t l, uint32_t u ); $\C{// [l,u]}$ 8334 // FASTER 8335 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th ); $\C{// [0,UINT\_MAX]}$ 8336 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t u ); $\C{// [0,u)}$ 8337 uint32_t prng( $thread\LstStringStyle{\textdollar}$ & th, uint32_t l, uint32_t u ); $\C{// [l,u]}\CRT$ 8338 \end{cfa} 8339 The slower ©prng© functions call ©active_thread© internally to access the thread-local PRNG-state, while the faster ©prng© functions are passed a pointer to the active thread. 8340 If the thread pointer is known, \eg in a thread ©main©, eliminating the call to ©active_thread© significantly reduces the cost for accessing the thread's PRNG state. 8341 \VRef[Figure]{f:ConcurrentPRNG} shows an example using the slower/faster concurrent PRNG in the program main and a thread. 8342 8343 \begin{figure} 8344 \begin{cfa} 8345 thread T {}; 8346 void main( ®T & th® ) { // thread address 8347 for ( i; 10 ) { 8348 sout | nlOff | ®prng()®; sout | ®prng( 5 )®; sout | ®prng( 0, 5 )® | '\t'; // SLOWER 8349 sout | nlOff | ®prng( th )®; sout | ®prng( th, 5 )®; sout | ®prng( th, 0, 5 )® | nlOn; // FASTER 8350 } 8351 } 8352 int main() { 8353 set_seed( 1009 ); 8354 $\R{thread\LstStringStyle{\textdollar}}$ ®& th = *active_thread()®; // program-main thread-address 8355 for ( i; 10 ) { 8356 sout | nlOff | ®prng()®; sout | ®prng( 5 )®; sout | ®prng( 0, 5 )® | '\t'; // SLOWER 8357 sout | nlOff | ®prng( th )®; sout | ®prng( th, 5 )®; sout | ®prng( th, 0, 5 )® | nlOn; // FASTER 8358 } 8359 sout | nl; 8360 T t; // run thread 8361 } 8362 \end{cfa} 8363 \begin{cquote} 8364 \begin{tabular}{@{}ll@{}} 8365 \begin{cfa} 8366 37301721 2 2 8367 290112364 3 2 8368 733221210 1 3 8369 123981445 2 3 8370 283934808 1 0 8371 1414344101 1 3 8372 871831898 3 4 8373 2142057611 4 4 8374 802117363 0 4 8375 2346353643 1 3 8376 \end{cfa} 8377 & 8378 \begin{cfa} 8379 1681308562 1 3 8380 1852700364 4 3 8381 1775396023 2 3 8382 2062557687 2 0 8383 672325890 1 3 8384 873424536 3 4 8385 866783532 0 1 8386 17310256 2 5 8387 492964499 0 0 8388 2143013105 3 2 8389 \end{cfa} 8390 \end{tabular} 8391 \begin{cfa} 8392 // same output as above from thread t 8393 \end{cfa} 8394 \end{cquote} 8395 \caption{Concurrent PRNG} 8396 \label{f:ConcurrentPRNG} 8397 \end{figure} 8398 \end{itemize} 8399 8400 8108 8401 \section{Multi-precision Integers} 8109 8402 \label{s:MultiPrecisionIntegers} … … 8310 8603 \end{tabular} 8311 8604 \end{cquote} 8312 \small 8605 8313 8606 \begin{cfa} 8314 8607 Factorial Numbers -
libcfa/src/concurrency/kernel/startup.cfa
r1a0b600 r7d18733 18 18 19 19 // C Includes 20 #include <errno.h> 20 #include <errno.h> // errno 21 21 #include <signal.h> 22 #include <string.h> 23 #include <unistd.h> 22 #include <string.h> // strerror 23 #include <unistd.h> // sysconf 24 24 25 25 extern "C" { 26 #include <limits.h>// PTHREAD_STACK_MIN27 #include <unistd.h> 28 #include <sys/eventfd.h> 29 #include <sys/mman.h>// mprotect30 #include <sys/resource.h>// getrlimit26 #include <limits.h> // PTHREAD_STACK_MIN 27 #include <unistd.h> // syscall 28 #include <sys/eventfd.h> // eventfd 29 #include <sys/mman.h> // mprotect 30 #include <sys/resource.h> // getrlimit 31 31 } 32 32 33 33 // CFA Includes 34 34 #include "kernel_private.hfa" 35 #include "startup.hfa" 35 #include "startup.hfa" // STARTUP_PRIORITY_XXX 36 36 #include "limits.hfa" 37 37 #include "math.hfa" … … 102 102 extern void __wake_proc(processor *); 103 103 extern int cfa_main_returned; // from interpose.cfa 104 extern uint32_t __global_random_seed;104 uint32_t __global_random_prime = 4_294_967_291u, __global_random_mask = false; 105 105 106 106 //----------------------------------------------------------------------------- … … 490 490 preferred = ready_queue_new_preferred(); 491 491 last_proc = 0p; 492 random_state = __global_random_ seed;492 random_state = __global_random_mask ? __global_random_prime : __global_random_prime ^ rdtscl(); 493 493 #if defined( __CFA_WITH_VERIFY__ ) 494 494 canary = 0x0D15EA5E0D15EA5Ep; -
libcfa/src/concurrency/thread.cfa
r1a0b600 r7d18733 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jan 15 14:34:58 202213 // Update Count : 4512 // Last Modified On : Sat Feb 12 15:24:18 2022 13 // Update Count : 66 14 14 // 15 15 … … 25 25 #include "invoke.h" 26 26 27 extern uint32_t __global_random_seed ;27 extern uint32_t __global_random_seed, __global_random_prime, __global_random_mask; 28 28 29 29 //----------------------------------------------------------------------------- … … 45 45 preferred = ready_queue_new_preferred(); 46 46 last_proc = 0p; 47 random_state = __global_random_ seed;47 random_state = __global_random_mask ? __global_random_prime : __global_random_prime ^ rdtscl(); 48 48 #if defined( __CFA_WITH_VERIFY__ ) 49 49 canary = 0x0D15EA5E0D15EA5Ep; … … 176 176 177 177 void set_seed( uint32_t seed ) { 178 active_thread()->random_state = __global_random_seed = seed; 179 GENERATOR( active_thread()->random_state ); 178 uint32_t & state = active_thread()->random_state; 179 state = __global_random_seed = seed; 180 GENERATOR( state ); 181 __global_random_prime = state; 182 __global_random_mask = true; 180 183 } // set_seed 181 184 -
libcfa/src/concurrency/thread.hfa
r1a0b600 r7d18733 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Feb 9 22:10:14202213 // Update Count : 1412 // Last Modified On : Fri Feb 11 16:34:07 2022 13 // Update Count : 20 14 14 // 15 15 … … 131 131 132 132 //---------- 133 // prng 133 134 static inline { 134 135 uint32_t prng( thread$ & th ) __attribute__(( warn_unused_result )) { return LCG( th.random_state ); } // [0,UINT_MAX] 135 136 uint32_t prng( thread$ & th, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th ) % u; } // [0,u) 136 137 uint32_t prng( thread$ & th, uint32_t l, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th, u - l + 1 ) + l; } // [l,u] 137 } // prng 138 forall( T & | is_thread(T) ) { 139 uint32_t prng( T & th ) __attribute__(( warn_unused_result )) { return prng( (thread &)th ); } // [0,UINT_MAX] 140 uint32_t prng( T & th, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th ) % u; } // [0,u) 141 uint32_t prng( T & th, uint32_t l, uint32_t u ) __attribute__(( warn_unused_result )) { return prng( th, u - l + 1 ) + l; } // [l,u] 142 } // distribution 143 } // distribution 138 144 139 145 // Local Variables: // -
libcfa/src/stdlib.hfa
r1a0b600 r7d18733 10 10 // Created On : Thu Jan 28 17:12:35 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 10 18:34:58202213 // Update Count : 64 112 // Last Modified On : Sat Feb 12 17:22:25 2022 13 // Update Count : 643 14 14 // 15 15 … … 412 412 void set_seed( PRNG & prng, uint32_t seed_ ); 413 413 static inline { 414 void ?{}( PRNG & prng ) { set_seed( prng, rdtscl() ); }// random seed415 void ?{}( PRNG & prng, uint32_t seed ) {set_seed( prng, seed ); } // fixed seed414 void ?{}( PRNG & prng ) with( prng ) { callcnt = 0; set_seed( prng, rdtscl() ); } // random seed 415 void ?{}( PRNG & prng, uint32_t seed ) with( prng ) { callcnt = 0; set_seed( prng, seed ); } // fixed seed 416 416 uint32_t get_seed( PRNG & prng ) __attribute__(( warn_unused_result )) with( prng ) { return seed; } // get seed 417 417 uint32_t prng( PRNG & prng ) __attribute__(( warn_unused_result )) with( prng ) { callcnt += 1; return LCG( state ); } // [0,UINT_MAX] -
src/AST/Pass.hpp
r1a0b600 r7d18733 239 239 private: 240 240 241 // Regular nodes 241 __pass::result1<ast::Stmt> call_accept( const ast::Stmt * ); 242 __pass::result1<ast::Expr> call_accept( const ast::Expr * ); 243 244 /// This has a `type` member that is the return type for the 245 /// generic call_accept if the generic call_accept is defined. 242 246 template< typename node_t > 243 struct result1 { 244 bool differs; 245 const node_t * value; 246 247 template< typename object_t, typename super_t, typename field_t > 248 void apply(object_t *, field_t super_t::* field); 249 }; 250 251 result1<ast::Stmt> call_accept( const ast::Stmt * ); 252 result1<ast::Expr> call_accept( const ast::Expr * ); 247 using generic_call_accept_result = 248 std::enable_if< 249 !std::is_base_of<ast::Expr, node_t>::value && 250 !std::is_base_of<ast::Stmt, node_t>::value 251 , __pass::result1< 252 typename std::remove_pointer< typename std::result_of< 253 decltype(&node_t::accept)(node_t*, type&) >::type >::type 254 > 255 >; 253 256 254 257 template< typename node_t > 255 258 auto call_accept( const node_t * node ) 256 -> typename std::enable_if< 257 !std::is_base_of<ast::Expr, node_t>::value && 258 !std::is_base_of<ast::Stmt, node_t>::value 259 , result1< 260 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 261 > 262 >::type; 259 -> typename generic_call_accept_result<node_t>::type; 263 260 264 261 // requests WithStmtsToAdd directly add to this statement, as if it is a compound. 265 result1<ast::Stmt> call_accept_as_compound(const ast::Stmt *); 266 267 // Container of statements 262 __pass::result1<ast::Stmt> call_accept_as_compound(const ast::Stmt *); 263 268 264 template< template <class...> class container_t > 269 struct resultNstmt { 270 struct delta { 271 ptr<Stmt> nval; 272 ssize_t old_idx; 273 bool is_old; 274 275 delta(const Stmt * s, ssize_t i, bool old) : nval{s}, old_idx{i}, is_old{old} {} 276 }; 277 278 bool differs; 279 container_t< delta > values; 280 281 resultNstmt() : differs(false), values{} {} 282 resultNstmt(bool diff, container_t< delta > && vals) : differs(diff), values(vals) {} 283 284 template< typename object_t, typename super_t, typename field_t > 285 void apply(object_t *, field_t super_t::* field); 286 287 template< template <class...> class incontainer_t > 288 void take_all( incontainer_t<ast::ptr<ast::Stmt>> * stmts ) { 289 if(!stmts || stmts->empty()) return; 290 291 std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ), [](ast::ptr<ast::Stmt>& decl) -> delta { 292 return delta( decl.release(), -1, false ); 293 }); 294 stmts->clear(); 295 differs = true; 296 } 297 298 template< template <class...> class incontainer_t > 299 void take_all( incontainer_t<ast::ptr<ast::Decl>> * decls ) { 300 if(!decls || decls->empty()) return; 301 302 std::transform(decls->begin(), decls->end(), std::back_inserter( values ), [](ast::ptr<ast::Decl>& decl) -> auto { 303 auto loc = decl->location; 304 auto stmt = new DeclStmt( loc, decl.release() ); 305 return delta( stmt, -1, false ); 306 }); 307 decls->clear(); 308 differs = true; 309 } 310 }; 311 312 template< template <class...> class container_t > 313 resultNstmt<container_t> call_accept( const container_t< ptr<Stmt> > & ); 314 315 // Container of something 265 __pass::resultNstmt<container_t> call_accept( const container_t< ptr<Stmt> > & ); 266 316 267 template< template <class...> class container_t, typename node_t > 317 struct resultN { 318 bool differs; 319 container_t<ptr<node_t>> values; 320 321 template< typename object_t, typename super_t, typename field_t > 322 void apply(object_t *, field_t super_t::* field); 323 }; 324 325 template< template <class...> class container_t, typename node_t > 326 resultN< container_t, node_t > call_accept( const container_t< ptr<node_t> > & container ); 268 __pass::resultN< container_t, node_t > call_accept( const container_t< ptr<node_t> > & container ); 327 269 328 270 public: -
src/AST/Pass.impl.hpp
r1a0b600 r7d18733 111 111 } 112 112 113 114 113 //------------------------------ 115 114 /// Check if value was mutated, different for pointers and containers … … 125 124 } 126 125 127 128 template< typename core_t >129 126 template< typename node_t > 130 127 template< typename object_t, typename super_t, typename field_t > 131 void ast::Pass< core_t >::result1< node_t >::apply(object_t * object, field_t super_t::* field) {128 void __pass::result1< node_t >::apply( object_t * object, field_t super_t::* field ) { 132 129 object->*field = value; 133 130 } … … 136 133 template< typename node_t > 137 134 auto ast::Pass< core_t >::call_accept( const node_t * node ) 138 -> typename std::enable_if< 139 !std::is_base_of<ast::Expr, node_t>::value && 140 !std::is_base_of<ast::Stmt, node_t>::value 141 , ast::Pass< core_t >::result1< 142 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 143 > 144 >::type 135 -> typename ast::Pass< core_t >::template generic_call_accept_result<node_t>::type 145 136 { 146 137 __pedantic_pass_assert( __visit_children() ); … … 151 142 152 143 auto nval = node->accept( *this ); 153 ast::Pass< core_t >::result1<144 __pass::result1< 154 145 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 155 146 > res; … … 160 151 161 152 template< typename core_t > 162 typename ast::Pass< core_t >::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {153 __pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) { 163 154 __pedantic_pass_assert( __visit_children() ); 164 155 __pedantic_pass_assert( expr ); … … 174 165 175 166 template< typename core_t > 176 typename ast::Pass< core_t >::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {167 __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) { 177 168 __pedantic_pass_assert( __visit_children() ); 178 169 __pedantic_pass_assert( stmt ); … … 183 174 184 175 template< typename core_t > 185 typename ast::Pass< core_t >::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {176 __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) { 186 177 __pedantic_pass_assert( __visit_children() ); 187 178 __pedantic_pass_assert( stmt ); … … 233 224 } 234 225 235 template< typename core_t >236 226 template< template <class...> class container_t > 237 227 template< typename object_t, typename super_t, typename field_t > 238 void ast::Pass< core_t >::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) {228 void __pass::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) { 239 229 auto & container = object->*field; 240 230 __pedantic_pass_assert( container.size() <= values.size() ); … … 243 233 244 234 container_t<ptr<Stmt>> nvals; 245 for (delta & d : values) {246 if ( d.is_old ) {235 for (delta & d : values) { 236 if ( d.is_old ) { 247 237 __pedantic_pass_assert( cit.idx <= d.old_idx ); 248 238 std::advance( cit, d.old_idx - cit.idx ); 249 239 nvals.push_back( std::move( (*cit).val) ); 250 240 } else { 251 nvals.push_back( std::move(d.n val) );241 nvals.push_back( std::move(d.new_val) ); 252 242 } 253 243 } 254 244 255 object->*field = std::move(nvals); 245 container = std::move(nvals); 246 } 247 248 template< template <class...> class container_t > 249 template< template <class...> class incontainer_t > 250 void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Stmt>> * stmts ) { 251 if (!stmts || stmts->empty()) return; 252 253 std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ), 254 [](ast::ptr<ast::Stmt>& stmt) -> delta { 255 return delta( stmt.release(), -1, false ); 256 }); 257 stmts->clear(); 258 differs = true; 259 } 260 261 template< template<class...> class container_t > 262 template< template<class...> class incontainer_t > 263 void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Decl>> * decls ) { 264 if (!decls || decls->empty()) return; 265 266 std::transform(decls->begin(), decls->end(), std::back_inserter( values ), 267 [](ast::ptr<ast::Decl>& decl) -> delta { 268 auto loc = decl->location; 269 auto stmt = new DeclStmt( loc, decl.release() ); 270 return delta( stmt, -1, false ); 271 }); 272 decls->clear(); 273 differs = true; 256 274 } 257 275 258 276 template< typename core_t > 259 277 template< template <class...> class container_t > 260 typename ast::Pass< core_t >::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {278 __pass::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 261 279 __pedantic_pass_assert( __visit_children() ); 262 280 if( statements.empty() ) return {}; … … 285 303 pass_visitor_stats.avg->push(pass_visitor_stats.depth); 286 304 287 resultNstmt<container_t> new_kids;305 __pass::resultNstmt<container_t> new_kids; 288 306 for( auto value : enumerate( statements ) ) { 289 307 try { … … 327 345 } 328 346 329 template< typename core_t >330 347 template< template <class...> class container_t, typename node_t > 331 348 template< typename object_t, typename super_t, typename field_t > 332 void ast::Pass< core_t >::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) {349 void __pass::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) { 333 350 auto & container = object->*field; 334 351 __pedantic_pass_assert( container.size() == values.size() ); … … 346 363 template< typename core_t > 347 364 template< template <class...> class container_t, typename node_t > 348 typename ast::Pass< core_t >::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {365 __pass::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) { 349 366 __pedantic_pass_assert( __visit_children() ); 350 367 if( container.empty() ) return {}; … … 378 395 if ( ! errors.isEmpty() ) { throw errors; } 379 396 380 return ast:: Pass< core_t >::resultN<container_t, node_t>{ mutated,new_kids };397 return ast::__pass::resultN<container_t, node_t>{ mutated, new_kids }; 381 398 } 382 399 -
src/AST/Pass.proto.hpp
r1a0b600 r7d18733 123 123 static constexpr bool value = std::is_void< ret_t >::value || 124 124 std::is_base_of<const node_t, typename std::remove_pointer<ret_t>::type >::value; 125 }; 126 127 /// The result is a single node. 128 template< typename node_t > 129 struct result1 { 130 bool differs; 131 const node_t * value; 132 133 template< typename object_t, typename super_t, typename field_t > 134 void apply( object_t *, field_t super_t::* field ); 135 }; 136 137 /// The result is a container of statements. 138 template< template<class...> class container_t > 139 struct resultNstmt { 140 /// The delta/change on a single node. 141 struct delta { 142 ptr<Stmt> new_val; 143 ssize_t old_idx; 144 bool is_old; 145 146 delta(const Stmt * s, ssize_t i, bool old) : 147 new_val(s), old_idx(i), is_old(old) {} 148 }; 149 150 bool differs; 151 container_t< delta > values; 152 153 template< typename object_t, typename super_t, typename field_t > 154 void apply( object_t *, field_t super_t::* field ); 155 156 template< template<class...> class incontainer_t > 157 void take_all( incontainer_t<ptr<Stmt>> * stmts ); 158 159 template< template<class...> class incontainer_t > 160 void take_all( incontainer_t<ptr<Decl>> * decls ); 161 }; 162 163 /// The result is a container of nodes. 164 template< template<class...> class container_t, typename node_t > 165 struct resultN { 166 bool differs; 167 container_t<ptr<node_t>> values; 168 169 template< typename object_t, typename super_t, typename field_t > 170 void apply( object_t *, field_t super_t::* field ); 125 171 }; 126 172 -
src/Common/CodeLocation.h
r1a0b600 r7d18733 25 25 /// Create a new unset CodeLocation. 26 26 CodeLocation() = default; 27 28 27 29 28 /// Create a new CodeLocation with the given values. -
src/Parser/parser.yy
r1a0b600 r7d18733 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 1 11:06:13202213 // Update Count : 51 6712 // Last Modified On : Fri Feb 11 14:26:15 2022 13 // Update Count : 5174 14 14 // 15 15 … … 1197 1197 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); } 1198 1198 | WHILE '(' conditional_declaration ')' statement ELSE statement // CFA 1199 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }1200 1199 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ), $7 ) ); } 1201 1200 | DO statement WHILE '(' ')' ';' // CFA => do while( 1 ) … … 1204 1203 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); } 1205 1204 | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA 1206 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }1207 1205 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); } 1208 1206 | FOR '(' ')' statement // CFA => for ( ;; ) … … 1211 1209 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); } 1212 1210 | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA 1213 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }1214 1211 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ), $7 ) ); } 1215 1212 ; … … 2729 2726 | ASM '(' string_literal ')' ';' // GCC, global assembler statement 2730 2727 { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, 0 ) ) ); } 2728 | EXTERN STRINGliteral 2729 { 2730 linkageStack.push( linkage ); // handle nested extern "C"/"Cforall" 2731 linkage = LinkageSpec::update( yylloc, linkage, $2 ); 2732 } 2733 up external_definition down 2734 { 2735 linkage = linkageStack.top(); 2736 linkageStack.pop(); 2737 $$ = $5; 2738 } 2731 2739 | EXTERN STRINGliteral // C++-style linkage specifier 2732 2740 { -
tests/PRNG.cfa
r1a0b600 r7d18733 8 8 // Created On : Wed Dec 29 09:38:12 2021 9 9 // Last Modified By : Peter A. Buhr 10 // Last Modified On : Fri Feb 11 08:16:43202211 // Update Count : 3 2810 // Last Modified On : Sat Feb 12 12:23:57 2022 11 // Update Count : 342 12 12 // 13 13 … … 20 20 #include <malloc.h> // malloc_stats 21 21 #include <locale.h> // setlocale 22 #include <mutex_stmt.hfa> 22 23 23 24 // FIX ME: spurious characters appear in output … … 50 51 } // for 51 52 double std = sqrt( sum / BUCKETS ); 52 sout | "trials" | TRIALS | "buckets" | BUCKETS53 54 53 mutex( sout ) sout | "trials" | TRIALS | "buckets" | BUCKETS 54 | "min" | min | "max" | max 55 | "avg" | wd(0,1, avg) | "std" | wd(0,1, std) | "rstd" | wd(0,1, (avg == 0 ? 0.0 : std / avg * 100)) | "%"; 55 56 } // avgstd 56 57 58 57 59 uint32_t seed = 1009; 58 59 60 60 61 thread T1 {}; … … 94 95 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 95 96 for ( TRIALS ) { 96 buckets[prng( (thread$ &)th ) % BUCKETS] += 1; // concurrent97 buckets[prng( th ) % BUCKETS] += 1; // concurrent 97 98 } // for 98 99 avgstd( buckets );
Note: See TracChangeset
for help on using the changeset viewer.