Changeset b195498
- Timestamp:
- Apr 24, 2025, 6:35:41 PM (5 months ago)
- Branches:
- master
- Children:
- 6b33e89, f85de47
- Parents:
- f632bd50
- Location:
- doc/theses/mike_brooks_MMath
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/mike_brooks_MMath/array.tex
rf632bd50 rb195498 90 90 91 91 92 \section{Dependent typing}92 \section{Dependent Typing} 93 93 94 94 General dependent typing allows the type system to encode arbitrary predicates (\eg behavioural specifications for functions), … … 103 103 104 104 105 \section{Features added}105 \section{Features Added} 106 106 107 107 This section shows more about using the \CFA array and dimension parameters, demonstrating their syntax and semantics by way of motivating examples. … … 782 782 783 783 784 Figure~\ref{f:DimexprRuleCompare} gives a case-by-case comparison of the consequences of these rule sets.784 \VRef[Figure]{f:DimexprRuleCompare} gives a case-by-case comparison of the consequences of these rule sets. 785 785 It demonstrates that the \CFA false alarms occur in the same cases as C treats unsafe. 786 786 It also shows that C-incompatibilities only occur in cases that C treats unsafe. … … 859 859 860 860 861 \section{Multidimensional array implementation}861 \section{Multidimensional Array Implementation} 862 862 \label{s:ArrayMdImpl} 863 863 … … 978 978 \end{figure} 979 979 980 Figure~\ref{fig:subscr-all} shows one element (in the shaded band) accessed two different ways: as @x[2][3]@ and as @x[all][3][2]@.980 \VRef[Figure]{fig:subscr-all} shows one element (in the shaded band) accessed two different ways: as @x[2][3]@ and as @x[all][3][2]@. 981 981 In both cases, value 2 selects from the coarser dimension (rows of @x@), 982 982 while the value 3 selects from the finer dimension (columns of @x@). … … 1024 1024 % The choice to implement this style-1 system upon C's style-2 arrays, rather than its style-3 pointer arithmetic, reduces the attack surface of unsafe code. 1025 1025 % My casting is unsafe, but I do not do any pointer arithmetic. 1026 % When a programmer works in the common-case style-2 subset (in the no-@[all]@ top of Figure~\ref{fig:subscr-all}), my casts are identities, and the C compiler is doing its usual displacement calculations.1026 % When a programmer works in the common-case style-2 subset (in the no-@[all]@ top of \VRef[Figure]{fig:subscr-all}), my casts are identities, and the C compiler is doing its usual displacement calculations. 1027 1027 % If I had implemented my system upon style-3 pointer arithmetic, then this common case would be circumventing C's battle-hardened displacement calculations in favour of my own. 1028 1028 … … 1067 1067 1068 1068 1069 \section{Bound checks, added and removed}1069 \section{Bound Checks, Added and Removed} 1070 1070 1071 1071 \CFA array subscripting is protected with runtime bound checks. … … 1089 1089 1090 1090 1091 \section{Array lifecycle}1091 \section{Array Lifecycle} 1092 1092 1093 1093 An array is an aggregate, like a structure; … … 1341 1341 % note to Mike, I have more fragments on some details available in push24\fragments\uNoCtor.txt 1342 1342 1343 \section{Comparison with other arrays}1343 \section{Comparison with Other Arrays} 1344 1344 1345 1345 … … 1457 1457 1458 1458 1459 \subsection{Levels of dependently typed arrays}1459 \subsection{Levels of Dependently Typed Arrays} 1460 1460 1461 1461 The \CFA array and the field of ``array language'' comparators all leverage dependent types to improve on the expressiveness over C and Java, accommodating examples such as: … … 1504 1504 Having no instances means there is no type for a variable @i@ that constrains @i@ to be in the range for @N@, unlike Dex, [TODO: verify], but like Futhark. 1505 1505 1506 \subsection{Static safety in C extensions}1507 1508 1509 \section{Future work}1510 1511 \subsection{Declaration syntax}1512 1513 \subsection{Range slicing}1514 1515 \subsection{With a module system}1516 1517 \subsection{With described enumerations}1506 \subsection{Static Safety in C Extensions} 1507 1508 1509 \section{Future Work} 1510 1511 \subsection{Declaration Syntax} 1512 1513 \subsection{Range Slicing} 1514 1515 \subsection{With a Module System} 1516 1517 \subsection{With Described Enumerations} 1518 1518 1519 1519 A project in \CFA's current portfolio will improve enumerations. … … 1602 1602 In the case of adapting this pattern to \CFA, my current work provides an adapter from ``successively subscripted'' to ``subscripted by tuple,'' so it is likely that generalizing my adapter beyond ``subscripted by @ptrdiff_t@'' is sufficient to make a user-provided adapter unnecessary. 1603 1603 1604 \subsection{Retire pointer arithmetic}1604 \subsection{Retire Pointer Arithmetic} 1605 1605 1606 1606 … … 1614 1614 (For later: That's what I offer with array.hfa, but in the future-work vision for arrays, the fix includes helping programmers stop accidentally using a broken C-ism.) 1615 1615 1616 \subsection{\CFA features interacting with arrays}1616 \subsection{\CFA Features Interacting with Arrays} 1617 1617 1618 1618 Prior work on \CFA included making C arrays, as used in C code from the wild, -
doc/theses/mike_brooks_MMath/background.tex
rf632bd50 rb195498 4 4 5 5 6 \section{Ill- typed expressions}6 \section{Ill-Typed Expressions} 7 7 8 8 C reports many ill-typed expressions as warnings. … … 24 24 Clearly, @gcc@ understands these ill-typed case, and yet allows the program to compile, which seems inappropriate. 25 25 Compiling with flag @-Werror@, which turns warnings into errors, is often too pervasive, because some warnings are just warnings, \eg an unused variable. 26 In the following discussion, ``ill-typed''means giving a nonzero @gcc@ exit condition with a message that discusses typing.26 In the following discussion, \emph{ill-typed} means giving a nonzero @gcc@ exit condition with a message that discusses typing. 27 27 Note, \CFA's type-system rejects all these ill-typed cases as type mismatch errors. 28 28 … … 37 37 % *1 TAPL-pg1 definition of a type system 38 38 39 40 \section{Reading declarations} 41 42 A significant area of confusion for reading C declarations results from: 43 \begin{itemize} 39 % reading C declaration: https://c-faq.com/decl/spiral.anderson.html 40 41 42 \section{Reading Declarations} 43 44 A significant area of confusion is reading C declarations, which results from interesting design choices. 45 \begin{itemize}[leftmargin=*] 44 46 \item 45 C is unique in having dimension be higher priority than pointer in declarations.\footnote{ 46 For consistency, subscript has higher priority than dereference, yielding \lstinline{(*arp)[3]} rather than \lstinline{*arp[3]}.} 47 In C, it is possible to have a value and a pointer to it. 48 \begin{cfa} 49 int i = 3, * pi = &i; 50 \end{cfa} 51 Extending this idea, it should be possible to have an array of values and pointer to it. 52 \begin{cfa} 53 int a[5] = { 1, 2, 3, 4, 5 }, * pa[5] = &a; 54 \end{cfa} 55 However, the declaration of @pa@ is incorrect because dimension has higher priority than pointer, so the declaration means an array of 5 pointers to integers. 56 The declarations for the two interpretations of @* [5]@ are: 57 \begin{cquote} 58 \begin{tabular}[t]{@{}ll@{\hspace{15pt}}|@{\hspace{15pt}}ll@{}} 59 \begin{cfa} 60 int (* pa)[5] 61 \end{cfa} 62 & 63 \raisebox{-0.4\totalheight}{\includegraphics{PtrToArray.pdf}} 64 & 65 \begin{cfa} 66 int * ap[5] 67 \end{cfa} 68 & 69 \raisebox{-0.75\totalheight}{\includegraphics{ArrayOfPtr.pdf}} 70 \end{tabular} 71 \end{cquote} 72 If the priorities of dimension and pointer were reversed, the declarations become more intuitive: @int * pa[5]@ and @int * (ap[5])@. 47 73 \item 48 Embedding a declared variable in a declaration, mimics the way the variable is used in executable statements. 74 This priority inversion extends into an expression between dereference and subscript, so usage syntax mimics declaration. 75 \begin{cquote} 76 \setlength{\tabcolsep}{20pt} 77 \begin{tabular}{@{}ll@{}} 78 \begin{cfa} 79 int (* pa)[5] 80 (*pa)[i] += 1; 81 \end{cfa} 82 & 83 \begin{cfa} 84 int * ap[5] 85 *ap[i] += 1; 86 \end{cfa} 87 \end{tabular} 88 \end{cquote} 89 (\VRef{s:ArraysDecay} shows pointer decay allows the first form to be written @pa[i] += 1@, which is further syntax confusion.) 90 Again, if the priorities were reversed, the expressions become more intuitive: @*pa[i] += 1@ and @*(ap[i]) += 1@. 91 Note, a similar priority inversion exists between deference @*@ and field selection @.@ (period), so @*ps.f@ means @*(ps.f)@; 92 this anomaly is \emph{fixed} with operator @->@, which performs the two operations in the more intuitive order: @sp->f@ $\Rightarrow$ @(*sp).f@. 49 93 \end{itemize} 50 \begin{cquote} 51 \begin{tabular}{@{}ll@{}} 52 \multicolumn{1}{@{}c}{\textbf{Array}} & \multicolumn{1}{c@{}}{\textbf{Function Pointer}} \\ 53 \begin{cfa} 54 int @(*@ar@)[@5@]@; // definition 55 ... @(*@ar@)[@3@]@ += 1; // usage 56 \end{cfa} 57 & 58 \begin{cfa} 59 int @(*@f@())[@5@]@ { ... }; // definition 60 ... @(*@f@())[@3@]@ += 1; // usage 61 \end{cfa} 62 \end{tabular} 63 \end{cquote} 64 The parenthesis are necessary to achieve a pointer to a @T@, and the type is wrapped around the name in successive layers (like an \Index{onion}) to match usage in an expression. 65 While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice, even though Dennis Richie believed otherwise: 94 While attempting to make the declaration and expression contexts consistent is a laudable goal, it has not worked out in practice, even though Dennis Richie believed otherwise: 66 95 \begin{quote} 67 96 In spite of its difficulties, I believe that the C's approach to declarations remains plausible, and am comfortable with it; it is a useful unifying principle.~\cite[p.~12]{Ritchie93} 68 97 \end{quote} 69 98 After all, reading a C array type is easy: just read it from the inside out, and know when to look left and when to look right! 70 71 \CFA provides its own type, variable and routine declarations, using a simpler syntax. 99 Unfortunately, \CFA cannot correct these operator priority inversions without breaking C compatibility. 100 101 The alternative solution is for \CFA to provide its own type, variable and routine declarations, using a more intuitive syntax. 72 102 The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right of the base type. 73 The qualifiers have the same syntax and semantics in \CFA as in C .74 Then, a \CFA declaration is read left to right, where a function return 103 The qualifiers have the same syntax and semantics in \CFA as in C, so there is nothing to learn. 104 Then, a \CFA declaration is read left to right, where a function return-type is enclosed in brackets @[@\,@]@. 75 105 \begin{cquote} 76 106 \begin{tabular}{@{}l@{\hspace{3em}}ll@{}} … … 98 128 \end{tabular} 99 129 \end{cquote} 100 As declaration size increases, it becomes corresponding difficult to read and understand the C declaration form, whereas reading and understanding a \CFA declaration has linear complexity as the declaration size increases.130 As declaration size increases, it becomes corresponding difficult to read and understand the C form, whereas reading and understanding a \CFA declaration has linear complexity. 101 131 Note, writing declarations left to right is common in other programming languages, where the function return-type is often placed after the parameter declarations, \eg \CC \lstinline[language=C++]{auto f( int ) -> int}. 102 Unfortunately, \CFA cannot interchange the priorities of subscript and dereference in expressions without breaking C compatibility. 132 (Note, putting the return type at the end deviates from where the return value logically appears in an expression, @x = f(...)@ versus @f(...) = x@.) 133 Interestingly, programmers normally speak a declaration from left to right, regardless of how it is written. 134 (It is unclear if Hebrew or Arabic speakers, say declarations right to left.) 103 135 104 136 \VRef[Table]{bkgd:ar:usr:avp} introduces the many layers of the C and \CFA array story, where the \CFA story is discussion in \VRef[Chapter]{c:Array}. … … 168 200 The conjoining of pointers and arrays could also be applied to structures, where a pointer references a structure field like an array element. 169 201 Finally, while subscripting involves pointer arithmetic (as does a field reference @x.y.z@), the computation is complex for multi-dimensional arrays and requires array descriptors to know stride lengths along dimensions. 170 Many C errors result from manually performing pointer arithmetic instead of using language subscripting, letting the compiler perform any arithmetic. 171 172 Some C textbooks erroneously suggest manual pointer arithmetic is faster than subscripting. 173 A sound and efficient C program does not require explicit pointer arithmetic. 174 TODO: provide an example, explain the belief, and give modern refutation 175 176 C semantics wants a programmer to \emph{believe} an array variable is a ``pointer to its first element.'' 202 Many C errors result from manually performing pointer arithmetic instead of using language subscripting so the compiler performs the arithmetic. 203 204 Some modern C textbooks and web sites erroneously suggest manual pointer arithmetic is faster than subscripting. 205 When compiler technology was young, this statement might have been true. 206 However, a sound and efficient C program coupled with a modern C compiler does not require explicit pointer arithmetic. 207 For example, the @gcc@ compiler at @-O3@ generates identical code for the following two summation loops. 208 \begin{cquote} 209 \vspace*{-10pt} 210 \begin{cfa} 211 int a[1000], sum; 212 \end{cfa} 213 \setlength{\tabcolsep}{20pt} 214 \begin{tabular}{@{}ll@{}} 215 \begin{cfa} 216 for ( int i = 0; i < 1000; i += 1 ) { 217 sum += a[i]; 218 } 219 \end{cfa} 220 & 221 \begin{cfa} 222 for ( int * ip = a ; ip < &a[1000]; ip += 1 ) { 223 sum += *ip; 224 } 225 \end{cfa} 226 \end{tabular} 227 \end{cquote} 228 I believe it is possible to refute any code examples purporting to show pointer arithmetic is faster than subscripting. 229 This believe stems from the performance work I did on \CFA arrays, where it is possible to generate equivalent \CFA subscripting and performance to C subscripting. 230 231 Unfortunately, C semantics want a programmer to \emph{believe} an array variable is a \emph{pointer to its first element}. 177 232 This desire becomes apparent by a detailed inspection of an array declaration. 178 233 \lstinput{34-34}{bkgd-carray-arrty.c} … … 224 279 225 280 226 \subsection{Arrays decay and pointers diffract} 281 \subsection{Arrays Decay and Pointers Diffract} 282 \label{s:ArraysDecay} 227 283 228 284 The last section established the difference among these four types: … … 247 303 Thus, subscripting happens on pointers not arrays. 248 304 249 Subscripting proceeds first with pointer decay, if needed. Next, \cite[\S~6.5.2.1.2]{C11} explains that @ar[i]@ is treated as if it were @(*((a)+(i)))@. 250 \cite[\S~6.5.6.8]{C11} explains that the addition, of a pointer with an integer type, is defined only when the pointer refers to an element that is in an array, with a meaning of ``@i@ elements away from,'' which is valid if @ar@ is big enough and @i@ is small enough. 305 Subscripting proceeds first with pointer decay, if needed. 306 Next, \cite[\S~6.5.2.1.2]{C11} explains that @ar[i]@ is treated as if it were @(*((a)+(i)))@. 307 \cite[\S~6.5.6.8]{C11} explains that the addition, of a pointer with an integer type, is defined only when the pointer refers to an element that is in an array, with a meaning of @i@ elements away from, which is valid if @ar@ is big enough and @i@ is small enough. 251 308 Finally, \cite[\S~6.5.3.2.4]{C11} explains that the @*@ operator's result is the referenced element. 252 309 Taken together, these rules illustrate that @ar[i]@ and @i[a]@ mean the same thing! … … 285 342 \end{cfa} 286 343 287 The shortened parameter syntax @T x[]@ is a further way to spell ``pointer.''344 The shortened parameter syntax @T x[]@ is a further way to spell \emph{pointer}. 288 345 Note the opposite meaning of this spelling now, compared with its use in local variable declarations. 289 346 This point of confusion is illustrated in: … … 321 378 \begin{table} 322 379 \caption{Syntactic Reference for Decay during Parameter-Passing. 323 Includes interaction with \lstinline{const}ness, where ``immutable''refers to a restriction on the callee's ability.}380 Includes interaction with \lstinline{const}ness, where \emph{immutable} refers to a restriction on the callee's ability.} 324 381 \label{bkgd:ar:usr:decay-parm} 325 382 \centering … … 357 414 358 415 359 \subsection{Variable Length Arrays}416 \subsection{Variable-length Arrays} 360 417 361 418 As of C99, the C standard supports a \newterm{variable length array} (VLA)~\cite[\S~6.7.5.2.5]{C99}, providing a dynamic-fixed array feature \see{\VRef{s:ArrayIntro}}. … … 379 436 % TODO: introduce multidimensional array feature and approaches 380 437 381 When working with arrays, \eg linear algebra, array dimensions are referred to as ``rows'' and ``columns'' for a matrix, adding ``planes''for a cube.438 When working with arrays, \eg linear algebra, array dimensions are referred to as \emph{rows} and \emph{columns} for a matrix, adding \emph{planes} for a cube. 382 439 (There is little terminology for higher dimensional arrays.) 383 440 For example, an acrostic poem\footnote{A type of poetry where the first, last or other letters in a line spell out a particular word or phrase in a vertical column.} … … 433 490 Many languages allow multidimensional arrays-of-arrays, \eg in Pascal or \CC. 434 491 \begin{cquote} 492 \setlength{\tabcolsep}{15pt} 435 493 \begin{tabular}{@{}ll@{}} 436 494 \begin{pascal} … … 467 525 468 526 \VRef[Figure]{f:ContiguousNon-contiguous} shows a powerful extension made in C99 for manipulating contiguous \vs non-contiguous arrays.\footnote{C90 also supported non-contiguous arrays.} 469 For contiguous-array (including VLA) arguments, C99 conjoins one or more of the parameters as a downstream dimension(s), \eg @cols@, implicitly using this parameter to compute the row stride of @m@.527 For contiguous-array arguments (including VLA), C99 conjoins one or more of the parameters as a downstream dimension(s), \eg @cols@, implicitly using this parameter to compute the row stride of @m@. 470 528 There is now sufficient information to support array copying and subscript checking along the columns to prevent changing the argument or buffer-overflow problems, but neither feature is provided. 471 529 If the declaration of @fc@ is changed to: … … 517 575 518 576 519 \subsection{Multi-dimensional arrays decay and pointers diffract} 520 521 As for single-dimension arrays, multi-dimensional arrays have similar issues. 577 \subsection{Multi-Dimensional Arrays Decay and Pointers Diffract} 578 579 As for single-dimension, multi-dimensional arrays have similar issues \see{\VRef{s:Array}}. 580 Again, the inspection begins by using @sizeof@ to provide program semantics for the intuition of an expression's type. 522 581 \lstinput{16-18}{bkgd-carray-mdim.c} 523 The significant axis of deriving expressions from @ar@ is now ``itself,'' ``first element'' or ``first grand-element (meaning, first element of first element).'' 524 \PAB{Explain, explain, explain.} 582 There are now three axis for deriving expressions from @mx@: \emph{itself}, \emph{first element}, and \emph{first grand-element} (meaning, first element of first element). 525 583 \lstinput{20-26}{bkgd-carray-mdim.c} 526 \PAB{Explain, explain, explain.} 584 Given that arrays are contiguous and the size of @float@ is 4, then the size of @mx@ with 3 $\times$ 10 floats is 120 bytes, the size of its first element (row) is 40 bytes, and the size of the first element of the first row is 4. 585 Again, an array and a point to each of its axes are different. 527 586 \lstinput{28-36}{bkgd-carray-mdim.c} 528 \PAB{Explain, explain, explain.} 587 As well, there is pointer decay from each of the matrix axes to pointers, which all have the same address. 529 588 \lstinput{38-44}{bkgd-carray-mdim.c} 589 Finally, subscripting on a @malloc@ result, where the referent may or may not allow subscripting or have the right number of subscripts. 530 590 531 591 … … 533 593 534 594 Passing an array as an argument to a function is necessary. 535 Assume a parameter is an array whe nthe function intends to subscript it.536 This section asserts that a more satisfactory/formal characterization does not exist in C, surveys the ways that C API authors communicate ``@p@ has zero or more dimensions'' andcalls out the minority cases where the C type system is using or verifying such claims.537 538 A C parameter declaration s look different,from the caller's and callee's perspectives.595 Assume a parameter is an array where the function intends to subscript it. 596 This section asserts that a more satisfactory/formal characterization does not exist in C, then surveys the ways that C API authors communicate @p@ has zero or more dimensions, and finally calls out the minority cases where the C type system is using or verifying such claims. 597 598 A C parameter declaration looks different from the caller's and callee's perspectives. 539 599 Both perspectives consist of the text read by a programmer and the semantics enforced by the type system. 540 The caller's perspective is available from a function declaration, which allow definition-before-use and separate compilation, but can also be read from (the non-body part of) a function definition.600 The caller's perspective is available from a function declaration, which allows definition-before-use and separate compilation, but can also be read from (the non-body part of) a function definition. 541 601 The callee's perspective is what is available inside the function. 542 602 \begin{cfa} 543 int foo( int, float, char ); $\C{// declaration, names optional}$544 int bar( int i, float f, char c ) { $\C{// definition, names mandatory}$545 // calle r's perspective of foo; callee's perspective ofbar603 int foo( int, float, char ); $\C{// declaration, parameter names optional}$ 604 int bar( int i, float f, char c ) { $\C{// definition, parameter names mandatory}$ 605 // callee's perspective of foo and bar 546 606 } 547 // caller's perspectives of foo 's and bar's548 \end{cfa} 549 In caller's perspective, the parameter names (by virtue of being optional) are reallycomments;550 inthe callee's perspective, parameter names are semantically significant.607 // caller's perspectives of foo and bar 608 \end{cfa} 609 From the caller's perspective, the parameter names (by virtue of being optional) are (useful) comments; 610 From the callee's perspective, parameter names are semantically significant. 551 611 Array parameters introduce a further, subtle, semantic difference and considerable freedom to comment. 552 612 553 613 At the semantic level, there is no such thing as an array parameter, except for one case (@T [static 5]@) discussed shortly. 554 614 Rather, there are only pointer parameters. 555 This fact probably shares considerable responsibility for the common sense of ``an array is just a pointer,''which has been refuted in non-parameter contexts.615 This fact probably shares considerable responsibility for the common sense of \emph{an array is just a pointer}, which has been refuted in non-parameter contexts. 556 616 This fact holds in both the caller's and callee's perspectives. 557 However, a parameter's type can include ``array of .'', \eg the type ``pointer to array of 5 ints'' (@T (*)[5]@) is a pointer type.617 However, a parameter's type can include ``array of'', \eg the type ``pointer to array of 5 ints'' (@T (*)[5]@) is a pointer type. 558 618 This type is fully meaningful in the sense that its description does not contain any information that the type system ignores, and the type appears the same in the caller's \vs callee's perspectives. 559 In fact, the outermost type constructor (syntactically first dimension) is really the one that determines the flavour of parameter. 560 561 Yet, C allows array syntax for the outermost type constructor, from which comes the freedom to comment. 562 An array parameter declaration can specify the outermost dimension with a dimension value, @[10]@ (which is ignored), an empty dimension list, @[ ]@, or a pointer, @*@, as seen in \VRef[Figure]{f:ArParmEquivDecl}. 563 The rationale for rejecting the first ``invalid'' row follows shortly, while the second ``invalid'' row is simple nonsense, included to complete the pattern; its syntax hints at what the final row actually achieves. 619 In fact, the outermost type constructor (syntactically first dimension) is really the one that determines the parameter flavour. 564 620 565 621 \begin{figure} 566 \begin{cquote}567 622 \begin{tabular}{@{}llll@{}} 568 623 \begin{cfa} 569 624 float sum( float a[5] ); 570 float sum( float a[5][4] );625 float sum( float m[5][4] ); 571 626 float sum( float a[5][] ); 572 627 float sum( float a[5]* ); … … 576 631 \begin{cfa} 577 632 float sum( float a[] ); 578 float sum( float a[][4] );633 float sum( float m[][4] ); 579 634 float sum( float a[][] ); 580 635 float sum( float a[]* ); … … 584 639 \begin{cfa} 585 640 float sum( float *a ); 586 float sum( float (* a)[4] );641 float sum( float (*m)[4] ); 587 642 float sum( float (*a)[] ); 588 643 float sum( float (*a)* ); … … 591 646 & 592 647 \begin{cfa} 593 // ar of float594 // mat of float648 // array of float 649 // matrix of float 595 650 // invalid 596 651 // invalid 597 // ar of ptr to float 598 \end{cfa} 599 \end{tabular} 600 \end{cquote} 652 // array of ptr to float 653 \end{cfa} 654 \end{tabular} 601 655 \caption{Multiple ways to declare an array parameter. 602 656 Across a valid row, every declaration is equivalent. … … 606 660 \end{figure} 607 661 608 In the leftmost style, the typechecker ignores the actual value in most practical cases. 609 This value is allowed to be a dynamic expression, and then it has practical cases. 610 \begin{cfa} 611 void foo( int @n@ ) { 612 float _42( float @a[n]@ ) { // nested function 613 a[0] = 42; 614 } 615 float b[n]; 616 _42( b ); 617 } 662 Yet, C allows array syntax for the outermost type constructor, from which comes the freedom to comment. 663 An array parameter declaration can specify the outermost dimension with a dimension value, @[10]@ (which is ignored), an empty dimension list, @[ ]@, or a pointer, @*@, as seen in \VRef[Figure]{f:ArParmEquivDecl}. 664 The rationale for rejecting the first invalid row follows shortly, while the second invalid row is simple nonsense, included to complete the pattern; its syntax hints at what the final row actually achieves. 665 Note, in the leftmost style, the typechecker ignores the actual value even in a dynamic expression. 666 \begin{cfa} 667 int N; 668 void foo( float @a[N] ) ; // N is ignored 618 669 \end{cfa} 619 670 … … 622 673 % So are @float[5]*@, @float[]*@ and @float (*)*@. These latter ones are simply nonsense, though they hint at ``1d array of pointers'', whose equivalent syntax options are, @float *[5]@, @float *[]@, and @float **@. 623 674 624 It is a matter of taste as to whether a programmer should use a form as far left as possible (getting the most out of possible subscripting and dimension sizes), sticking to the right (avoiding false comfort from suggesting the typechecker is checking more than it is), or compromising in the middle (reducing unchecked information, yet clearly stating, ``I will subscript ).675 It is a matter of taste as to whether a programmer should use a form as far left as possible (getting the most out of possible subscripting and dimension sizes), sticking to the right (avoiding false comfort from suggesting the typechecker is checking more than it is), or compromising in the middle (reducing unchecked information, yet clearly stating, ``I will subscript''). 625 676 626 677 Note that this equivalence of pointer and array declarations is special to parameters. … … 635 686 } 636 687 \end{cfa} 637 This equivalence has the consequence that the type system does not help a caller get it right.688 Unfortunately, this equivalence has the consequence that the type system does not help a caller get it right. 638 689 \begin{cfa} 639 690 float sum( float v[] ); … … 656 707 void foo( int [@const volatile@ 5] ); $\C{// 5 is ignored}$ 657 708 \end{cfa} 658 659 709 To make the first dimension size meaningful, C adds this form. 660 710 \begin{cquote} … … 667 717 \end{cfa} 668 718 Here, the @static@ storage qualifier defines the minimum array size for its argument. 669 @gcc@ ignores this dimension qualifier, \ie it gives no warning if the argument array size is less than the parameter minimum. However, @clang@ implements the check, in accordance with the standard. TODO: be specific about versions 719 Earlier versions of @gcc@ ($<$ 11) and possibly @clang@ ignore this dimension qualifier, while later versions implement the check, in accordance with the standard. 720 670 721 671 722 Note that there are now two different meanings for modifiers in the same position. In … … 685 736 Here, the distance between the first and second elements of each array depends on the inner dimension size. 686 737 687 Th issignificance of an inner dimension's length is a fact of the callee's perspective.688 In the caller's perspective, the type sy tem is quite lax.738 The significance of an inner dimension's length is a fact of the callee's perspective. 739 In the caller's perspective, the type system is quite lax. 689 740 Here, there is (some, but) little checking that what is being passed, matches. 690 741 % void f( float [][10] ); … … 709 760 \end{cfa} 710 761 The cases without comments are rejections, but simply because the array ranks do not match; in the commented cases, the ranks match and the rules being discussed apply. 711 The cases @f( b)@ and @f(&a)@ show where some length checking occurs.712 But this checking misses the cases @f( d)@ and @f(&c)@, allowing the calls with mismatched lengths, actually 100 for 10.762 The cases @f( b )@ and @f( &a )@ show where some length checking occurs. 763 But this checking misses the cases @f( d )@ and @f( &c )@, allowing the calls with mismatched lengths, actually 100 for 10. 713 764 The C checking rule avoids false alarms, at the expense of safety, by allowing any combinations that involve dynamic values. 714 765 Ultimately, an inner dimension's size is a callee's \emph{assumption} because the type system uses declaration details in the callee's perspective that it does not enforce in the caller's perspective. 715 766 716 Finally, to handle higher-dimensional VLAs, C repurposed the @*@ \emph{within} the dimension in a declaration to mean that the callee has make an assumption about the size, but no ( unchecked, possibly wrong) information about this assumption is included for the caller-programmer's benefit/over-confidence.767 Finally, to handle higher-dimensional VLAs, C repurposed the @*@ \emph{within} the dimension in a declaration to mean that the callee has make an assumption about the size, but no (checked, possibly wrong) information about this assumption is included for the caller-programmer's benefit/\-over-confidence. 717 768 \begin{cquote} 718 769 @[@ \textit{type-qualifier-list$_{opt}$} @* ]@ … … 731 782 732 783 733 \subsection{Arrays could be values}784 \subsection{Arrays Could be Values} 734 785 735 786 All arrays have a know runtime size at their point of declaration. … … 751 802 \begin{cfa} 752 803 Jmp_Buf jb1, jb2; 753 jb1 = jb2; 804 jb1 = jb2; // copy 754 805 void foo( Jmp_Buf ); 755 foo( jb2 ); 806 foo( jb2 ); // copy 756 807 \end{cfa} 757 808 758 809 This same argument applies to returning arrays from functions. 759 There can be sufficient information to return an array by value but it is notsupported.760 Again, array wrapping allows an array to be returned from a function and copied into variable.810 There can be sufficient information to return an array by value but it is unsupported. 811 Again, array wrapping allows an array to be returned from a function and copied into a variable. 761 812 762 813 … … 772 823 773 824 774 \subsection{Design issues}825 \subsection{Design Issues} 775 826 \label{toc:lst:issue} 776 827 777 828 This thesis focuses on a reduced design space for linked lists that target \emph{system programmers}. 778 829 Within this restricted space, all design-issue discussions assume the following invariants; 779 alternatives to the assumptions are discussed under Future Work ( Section~\ref{toc:lst:futwork}).830 alternatives to the assumptions are discussed under Future Work (\VRef{toc:lst:futwork}). 780 831 \begin{itemize} 781 832 \item A doubly-linked list is being designed. 782 833 Generally, the discussed issues apply similarly for singly-linked lists. 783 Circular \vs ordered linking is discussed under List identity ( Section~\ref{toc:lst:issue:ident}).834 Circular \vs ordered linking is discussed under List identity (\VRef{toc:lst:issue:ident}). 784 835 \item Link fields are system-managed. 785 836 The user works with the system-provided API to query and modify list membership. … … 790 841 791 842 792 \subsection{Preexisting linked-list libraries}843 \subsection{Preexisting Linked-List Libraries} 793 844 \label{s:PreexistingLinked-ListLibraries} 794 845 … … 799 850 \item \CC Standard Template Library's (STL)\footnote{The term STL is contentious as some people prefer the term standard library.} @std::list@\cite{lst:stl} 800 851 \end{enumerate} 801 %A general comparison of libraries' abilities is given under Related Work ( Section~\ref{toc:lst:relwork}).852 %A general comparison of libraries' abilities is given under Related Work (\VRef{toc:lst:relwork}). 802 853 For the discussion, assume the fictional type @req@ (request) is the user's payload in examples. 803 854 As well, the list library is helping the user manage (organize) requests, \eg a request can be work on the level of handling a network arrival-event or scheduling a thread. 804 855 805 856 806 \subsection{Link attachment: intrusive vs.\ wrapped}857 \subsection{Link Attachment: Intrusive \vs Wrapped} 807 858 \label{toc:lst:issue:attach} 808 859 … … 837 888 Three styles of link attachment: (a)~intrusive, (b)~wrapped reference, and (c)~wrapped value. 838 889 The diagrams show the memory layouts that result after the code runs, eliding the head object \lstinline{reqs}; 839 head objects are discussed in Section~\ref{toc:lst:issue:ident}.890 head objects are discussed in \VRef{toc:lst:issue:ident}. 840 891 In (a), the field \lstinline{req.x} names a list direction; 841 these are discussed in Section~\ref{toc:lst:issue:simultaneity}.892 these are discussed in \VRef{toc:lst:issue:simultaneity}. 842 893 In (b) and (c), the type \lstinline{node} represents a system-internal type, 843 894 which is \lstinline{std::_List_node} in the GNU implementation. … … 889 940 % \protect\subref*{f:Intrusive}~intrusive, \protect\subref*{f:WrappedRef}~wrapped reference, and \protect\subref*{f:WrappedValue}~wrapped value. 890 941 The diagrams show the memory layouts that result after the code runs, eliding the head object \lstinline{reqs}; 891 head objects are discussed in Section~\ref{toc:lst:issue:ident}.942 head objects are discussed in \VRef{toc:lst:issue:ident}. 892 943 In \protect\subref*{f:Intrusive}, the field \lstinline{req.d} names a list direction; 893 these are discussed in Section~\ref{toc:lst:issue:simultaneity}.944 these are discussed in \VRef{toc:lst:issue:simultaneity}. 894 945 In \protect\subref*{f:WrappedRef} and \protect\subref*{f:WrappedValue}, the type \lstinline{node} represents a 895 946 library-internal type, which is \lstinline{std::_List_node} in the GNU implementation … … 905 956 In all three cases, a @req@ object can enter and leave a list many times. 906 957 However, in intrusive a @req@ can only be on one list at a time, unless there are separate link-fields for each simultaneous list. 907 In wrapped reference, a @req@ can appear multiple times on the same or different lists simultaneously, but since @req@ is shared via the pointer, care must be taken if updating data also occurs simultaneously, \eg concurrency.958 In wrapped reference, a @req@ can appear multiple times on the same or different lists, but since @req@ is shared via the pointer, care must be taken if updating data also occurs simultaneously, \eg concurrency. 908 959 In wrapped value, the @req@ is copied, which increases storage usage, but allows independent simultaneous changes; 909 however, knowing which of the @req@ object is the ``true''object becomes complex.960 however, knowing which of the @req@ object is the \emph{true} object becomes complex. 910 961 \see*{\VRef{toc:lst:issue:simultaneity} for further discussion.} 911 962 912 963 The implementation of @LIST_ENTRY@ uses a trick to find the links and the node containing the links. 913 The macro @LIST_INSERT_HEAD( &reqs, &r2, d);@ takes the list header, a pointer to the node, and the offset of the link fields in the node.964 The macro @LIST_INSERT_HEAD( &reqs, &r2, d )@ takes the list header, a pointer to the node, and the offset of the link fields in the node. 914 965 One of the fields generated by @LIST_ENTRY@ is a pointer to the node, which is set to the node address, \eg @r2@. 915 966 Hence, the offset to the link fields provides an access to the entire node, \ie the node points at itself. 916 For list traversal, @LIST_FOREACH( cur, &reqs_pri, by_pri)@, there is the node cursor, the list, and the offset of the link fields within the node.967 For list traversal, @LIST_FOREACH( cur, &reqs_pri, by_pri )@, there is the node cursor, the list, and the offset of the link fields within the node. 917 968 The traversal actually moves from link fields to link fields within a node and sets the node cursor from the pointer within the link fields back to the node. 918 969 … … 926 977 Another subtle advantage of intrusive arrangement is that a reference to a user-level item (@req@) is sufficient to navigate or manage the item's membership. 927 978 In LQ, the intrusive @req@ pointer is the right argument type for operations @LIST_NEXT@ or @LIST_REMOVE@; 928 there is no distinguishing a @req@ from ``a @req@ in a list.''979 there is no distinguishing a @req@ from a @req@ in a list. 929 980 The same is not true of STL, wrapped reference or value. 930 981 There, the analogous operations, @iterator::operator++()@, @iterator::operator*()@, and @list::erase(iterator)@, work on a parameter of type @list<T>::iterator@; … … 946 997 the LQ C macros do not expand to valid C++ when instantiated with template parameters---there is no \lstinline{struct El}. 947 998 When using a custom-patched version of LQ to work around this issue, 948 the programs of Figure~\ref{f:WrappedRef} and wrapped value work with this shim in place of real STL.999 the programs of \VRef[Figure]{f:WrappedRef} and wrapped value work with this shim in place of real STL. 949 1000 Their executions lead to the same memory layouts. 950 1001 } … … 952 1003 \end{figure} 953 1004 954 It is possible to simulate wrapped using intrusive, illustrated in Figure~\ref{fig:lst-issues-attach-reduction}.1005 It is possible to simulate wrapped using intrusive, illustrated in \VRef[Figure]{fig:lst-issues-attach-reduction}. 955 1006 This shim layer performs the implicit dynamic allocations that pure intrusion avoids. 956 1007 But there is no reduction going the other way. … … 961 1012 An intrusive-primitive library like LQ lets users choose when to make this tradeoff. 962 1013 A wrapped-primitive library like STL forces users to incur the costs of wrapping, whether or not they access its benefits. 963 964 965 \subsection{Simultaneity: single vs.\ multi-static vs.\ dynamic} 1014 \CFA is capable of supporting a wrapped library, if need arose. 1015 1016 1017 \subsection{Simultaneity: Single \vs Multi-Static \vs Dynamic} 966 1018 \label{toc:lst:issue:simultaneity} 967 1019 … … 986 1038 \newterm{Simultaneity} deals with the question: 987 1039 In how many different lists can a node be stored, at the same time? 988 Figure~\ref{fig:lst-issues-multi-static} shows an example that can traverse all requests in priority order (field @pri@) or navigate among requests with the same request value (field @rqr@).1040 \VRef[Figure]{fig:lst-issues-multi-static} shows an example that can traverse all requests in priority order (field @pri@) or navigate among requests with the same request value (field @rqr@). 989 1041 Each of ``by priority'' and ``by common request value'' is a separate list. 990 1042 For example, there is a single priority-list linked in order [1, 2, 2, 3, 3, 4], where nodes may have the same priority, and there are three common request-value lists combining requests with the same values: [42, 42], [17, 17, 17], and [99], giving four head nodes one for each list. … … 996 1048 This feature is used in the \CFA runtime, where a thread node may be on a blocked or running list, but never on both simultaneously. 997 1049 998 Now consider the STL in the wrapped-reference arrangement of Figure~\ref{f:WrappedRef}.1050 Now consider the STL in the wrapped-reference arrangement of \VRef[Figure]{f:WrappedRef}. 999 1051 Here it is possible to construct the same simultaneity by creating multiple STL lists, each pointing at the appropriate nodes. 1000 1052 Each group of intrusive links become the links for each separate STL list. … … 1003 1055 Note, it might be possible to wrap the multiple lists in another type to hide this implementation issue. 1004 1056 1005 Now consider the STL in the wrapped-value arrangement of Figure~\ref{f:WrappedValue}.1057 Now consider the STL in the wrapped-value arrangement of \VRef[Figure]{f:WrappedValue}. 1006 1058 Again, it is possible to construct the same simultaneity by creating multiple STL lists, each copying the appropriate nodes, where the intrusive links become the links for each separate STL list. 1007 1059 The upside is the same as for wrapped-reference arrangement with an unlimited number of list bindings. … … 1015 1067 % LQ's ergonomics are well-suited to the uncommon case of multiple list directions. 1016 1068 % Its intrusion declaration and insertion operation both use a mandatory explicit parameter naming the direction. 1017 % This decision works well in Figure~\ref{fig:lst-issues-multi-static}, where the names @by_pri@ and @by_rqr@ work well,1018 % but it clutters Figure~\ref{f:Intrusive}, where a contrived name must be invented and used.1069 % This decision works well in \VRef[Figure]{fig:lst-issues-multi-static}, where the names @by_pri@ and @by_rqr@ work well, 1070 % but it clutters \VRef[Figure]{f:Intrusive}, where a contrived name must be invented and used. 1019 1071 % The example uses @x@; @reqs@ would be a more readily ignored choice. \PAB{wording?} 1020 1072 … … 1089 1141 1090 1142 1091 \subsection{User integration: preprocessed vs.\ type-system mediated} 1092 1093 \PAB{What do you want to say here?} 1143 \subsection{User Integration: Preprocessed \vs Type-System Mediated} 1144 1145 While the syntax for LQ is reasonably succinct, it comes at the cost of using C preprocessor macros for generics, which are not part of the language type-system, like \CC templates. 1146 Hence, small errors in macro arguments can lead to large substitution mistakes, as the arguments maybe textually written in many places and/or concatenated with other arguments/text to create new names and expressions. 1147 This can lead to a cascade of error messages that are confusing and difficult to debug. 1148 For example, argument errors like @a.b,c@, comma instead of period, or @by-pri@, minus instead of underscore, can produce many error messages. 1149 1150 Instead, language function calls (even with inlining) handled argument mistakes locally at the call, giving very specific error message. 1151 \CC @concepts@ were introduced in @templates@ to deal with just this problem. 1094 1152 1095 1153 % example of poor error message due to LQ's preprocessed integration … … 1101 1159 1102 1160 1103 \subsection{List identity: headed vs.\ ad-hoc}1161 \subsection{List Identity: Headed \vs Ad-Hoc} 1104 1162 \label{toc:lst:issue:ident} 1105 1163 1106 All examples so far use distinct user-facing types: 1107 an item found in a list (type @req@ of variable @r1@, see \VRef[Figure]{fig:lst-issues-attach}), and a list (type @reql@ of variable @reqs_pri@, see \VRef[Figure]{fig:lst-issues-ident}). 1108 The latter type is a head. 1109 The resulting identity model (empty list) is just the head. 1110 A bespoke ``pointer to next @req@'' implementation often omits the header; 1111 hence, a pointer to any node can traverse its link fields: right or left and around, depending on the data structure. 1112 The resulting identity model is ad-hoc. 1113 1114 Figure~\ref{fig:lst-issues-ident} shows the identity model's impact on 1115 the existence of certain conceptual constructs, like zero-lengths lists and unlisted elements. 1116 In headed thinking, there are length-zero lists (heads with no elements), and an element can be listed or not listed. 1117 In ad-hoc thinking, there are no length-zero lists and every element belongs to a list of length at least one. 1118 By omitting the head, elements can enter into an adjacency relationship, without requiring allocation for a head for the list, or finding a correct existing head. 1164 All examples so far use two distinct types for: 1165 an item found in a list (type @req@ of variable @r1@, see \VRef[Figure]{fig:lst-issues-attach}), and the list (type @reql@ of variable @reqs_pri@, see \VRef[Figure]{fig:lst-issues-ident}). 1166 This kind of list is ``headed'', where the empty list is just a head. 1167 An alternate ``ad-hoc'' approach omits the header, where the empty list is no nodes. 1168 Here, a pointer to any node can traverse its link fields: right or left and around, depending on the data structure. 1169 Note, a headed list is superset of an ad-hoc list, and can normally perform all of the ad-hoc operations. 1170 \VRef[Figure]{fig:lst-issues-ident} shows both approaches for different list lengths and unlisted elements. 1171 For headed, there are length-zero lists (heads with no elements), and an element can be listed or not listed. 1172 For ad-hoc, there are no length-zero lists and every element belongs to a list of length at least one. 1119 1173 1120 1174 \begin{figure} … … 1128 1182 \end{figure} 1129 1183 1130 A head defines one or more element roles, among elements that share a transitive adjacency.1131 ``First'' and ``last'' are element roles.1132 One moment's ``first'' need not be the next moment's.1133 1134 There is a cost to maintaining these roles.1184 The purpose of a header is to provide specialized but implicit node access, such as the first/last nodes in the list, where accessing these nodes is deemed a commonly occurring operation and should be $O(1)$ for performance of certain operations. 1185 For example, without a last pointer in a singly-linked list, adding to the end of the list is an $O(N)$ operation to traverse the list to find the last node. 1186 Without the header, this specialized information must be managed explicitly, where the programmer builds their own external, equivalent header information. 1187 However, external management of particular nodes might not be beneficial because the list does not provide operations that can take advantage of them, such as using an external pointer to update an internal link. 1188 Clearly, there is a cost maintaining this specialized information, which needs to be amortized across the list operations that use it, \eg rarely adding to the end of a list. 1135 1189 A runtime component of this cost is evident in LQ's offering the choice of type generators @LIST@ \vs @TAILQ@. 1136 Its @LIST@ maintains a ``first,'' but not a ``last;'' its @TAILQ@ maintains both roles. 1190 Its @LIST@ maintains a \emph{first}, but not a \emph{last}; 1191 its @TAILQ@ maintains both roles. 1137 1192 (Both types are doubly linked and an analogous choice is available for singly linked.) 1138 1193 1139 TODO: finish making this point 1140 1141 See WIP in lst-issues-adhoc-*.ignore.*. 1142 1143 The code-complexity component of the cost ... 1144 1145 Ability to offer heads is good. Point: Does maintaining a head mean that the user has to provide more state when manipulating the list? Requiring the user to do so is bad, because the user may have lots of "list" typed variables in scope, and detecting that the user passed the wrong one requires testing all the listing edge cases. 1146 1147 1148 \subsection{End treatment: cased vs.\ uniform } 1149 1150 A linear (non-circular), nonempty linked-list has a first element and a last element, whether or not the list is headed. 1151 A first element has no predecessor and a last element has no successor. 1194 1195 \subsection{End Treatment: Cased \vs Uniform } 1196 1197 All lists must have a logical \emph{beginning/ending}, otherwise list traversal is infinite. 1198 \emph{End treatment} refers to how the list represents the lack of a predecessor/successor to demarcate end point(s). 1199 For example, in a doubly-linked list containing a single node, the next/prev links have no successor/predecessor nodes. 1200 Note, a list does not need to use links to denote its size; 1201 it can use a node counter in the header, where $N$ node traversals indicates complete navigation of the list. 1202 However, managing the number of nodes is an additional cost, as the links must always be managed. 1203 1204 The following discussion refers to the LQ representations, detailed in \VRef[Figure]{fig:lst-issues-end}, using a null pointer to mark end points. 1205 LQ uses this representation for its successor/last. 1206 For example, consider the operation of inserting after a given element. 1207 A doubly-linked list must update the given node's successor, to make its predecessor-pointer refer to the new node. 1208 This step must happen when the given node has a successor (when its successor pointer is non-null), 1209 and must be skipped when it does not (when its successor pointer cannot be navigated). 1210 So this operation contains a branch, to decide which case is happening. 1211 All branches have pathological cases where branch prediction's success rate is low and the execution pipeline stalls often. 1212 Hence, this issue is relevant to achieving high performance. 1152 1213 1153 1214 \begin{figure} … … 1164 1225 \end{figure} 1165 1226 1166 End treatment refers to how the list represents the lack of a predecessor/successor. 1167 The following elaboration refers to the LQ representations, detailed in Figure~\ref{fig:lst-issues-end}. 1168 The most obvious representation, a null pointer, mandates a cased end treatment. 1169 LQ uses this representation for its successor/last. 1170 Consider the operation of inserting after a given element. 1171 A doubly-linked list must update the given node's successor, to make its predecessor-pointer refer to the new node. 1172 This step must happen when the given node has a successor (when its successor pointer is non-null), 1173 and must be skipped when it does not (when its successor pointer cannot be navigated). 1174 So this operation contains a branch, to decide which case is happening. 1175 All branches have pathological cases where branch prediction's success rate is low and the execution pipeline is stalling often. 1176 Hence, this issue is implementation-level, relevant to achieving high performance. 1177 1178 This branch is sometimes avoidable; the result is a uniform end treatment. 1179 Here is one example of such an implementation that works for a headed list. 1180 LQ uses this representation for its predecessor/first. (All LQ offerings are headed at the front.) 1227 Interestingly, this branch is sometimes avoidable, giving a uniform end-treatment in the code. 1228 For example, LQ is headed at the front. 1181 1229 For predecessor/first navigation, the relevant operation is inserting before a given element. 1182 1230 LQ's predecessor representation is not a pointer to a node, but a pointer to a pseudo-successor pointer. 1183 1231 When there is a predecessor node, that node contains a real-successor pointer; it is the target of the reference node's predecessor pointer. 1184 1232 When there is no predecessor node, the reference node (now known to be first node) acts as the pseudo-successor of the list head. 1185 The list head contains a pointer to the first node.1233 Now, the list head contains a pointer to the first node. 1186 1234 When inserting before the first node, the list head's first-pointer is the one that must change. 1187 So, the first node's ``predecessor''pointer (to a pseudo-successor pointer) is set as the list head's first-pointer.1235 So, the first node's \emph{predecessor} pointer (to a pseudo-successor pointer) is set as the list head's first-pointer. 1188 1236 Now, inserting before a given element does the same logic in both cases: 1189 follow the guaranteed-non-null predecessor pointer, and update what you find thereto refer to the new node.1237 follow the guaranteed-non-null predecessor pointer, and update that location to refer to the new node. 1190 1238 Applying this trick makes it possible to have list management routines that are completely free of conditional control-flow. 1191 1239 Considering a path length of only a few instructions (less than the processor's pipeline length), -
doc/theses/mike_brooks_MMath/benchmarks/list/_classic.c
rf632bd50 rb195498 232 232 for ( t = 0; t < Times; t += 1 ) { 233 233 Repeat( insert_last( lst, s[i] ) ); 234 Repeat( remove( lst`first) );234 Repeat( remove( first( lst ) ) ); 235 235 } 236 236 end = clock(); -
doc/theses/mike_brooks_MMath/benchmarks/list/fx-cfa-cfa.h
rf632bd50 rb195498 11 11 #define BFX_INSERT_BEFORE(S, lst, item, refIter) (insert_before(*refIter, item), (S*)&(item)) 12 12 #define BFX_INSERT_AFTER(S, lst, item, refIter) (insert_after (*refIter, item), (S*)&(item)) 13 #define BFX_REMOVE_FIRST(S, lst) remove( lst`first)14 #define BFX_REMOVE_LAST(S, lst) remove( lst`last)13 #define BFX_REMOVE_FIRST(S, lst) remove( first( lst ) ) 14 #define BFX_REMOVE_LAST(S, lst) remove( last( lst ) ) 15 15 #define BFX_REMOVE_HERE(S, lst, refIter) remove(*refIter) 16 16 #define BFX_INIT(S, lst) 17 17 18 #define BFX_GET_AFTER(S, lst, iter) (& (*iter)`next)19 #define BFX_GET_BEFORE(S, lst, iter) (& (*iter)`prev)18 #define BFX_GET_AFTER(S, lst, iter) (&next( *iter)) 19 #define BFX_GET_BEFORE(S, lst, iter) (&prev( *iter )) 20 20 #define BFX_IS_VALID_POS(S, lst, iter) ((iter)!=NULL) 21 21 #define BFX_DEREF_POS(S, lst, iter) (iter) -
doc/theses/mike_brooks_MMath/conclusion.tex
rf632bd50 rb195498 7 7 \section{Strings} 8 8 9 \section{Future work}9 \section{Future Work} -
doc/theses/mike_brooks_MMath/intro.tex
rf632bd50 rb195498 27 27 28 28 29 \section{Linked list}29 \section{Linked List} 30 30 31 31 A linked-list provides a homogeneous container often with $O(log N)$ or $O(N)$ access to elements using successor and predecessor operations that normally involve pointer chasing. … … 42 42 hash search table consisting of a key (string) with associated data (@<search.h>@) 43 43 \end{itemize} 44 Because these libraries are simple, awkward to use, and unsafe, C programmers commonly build linked-list behaviours into their bespoke datastructures.44 Because these libraries are simple, awkward to use, and unsafe, C programmers commonly build bespoke linked data-structures. 45 45 46 46 … … 54 54 In some cases, string management is separate from heap management, \ie strings roll their own heap. 55 55 56 The C string type requires user storage-management of a language-provided character array.56 The C string type is just a character array and requires user storage-management to handle varying size. 57 57 The character array uses the convention of marking its (variable) array length by placing the 0-valued control character at the end (null-terminated). 58 58 The C standard library includes a number of high-level operations for working with this representation. 59 Most of these operations are awkward and error prone. 59 60 60 61 … … 84 85 While multiple new languages purport to be systems languages replacing C, the reality is that rewriting massive C code-bases is impractical and a non-starter if the new runtime uses garage collection. 85 86 Furthermore, new languages must still interact with the underlying C operating system through fragile, type-unsafe, interlanguage-communication. 86 Switching to \CC is equally impractical as its complex and interdependent type-system (\eg objects, overloading, inheritance, templates) means idiomatic \CC code is difficult to use from C, and C programmers must expend significant effort learning \CC.87 Switching to \CC is equally impractical as its complex and interdependent type-system (\eg objects, overloading, inheritance, templates) means idiomatic \CC code is difficult to use from C, and C programmers must expend significant effort learning new \CC. 87 88 Hence, rewriting and retraining costs for these languages can be prohibitive for companies with a large C software-base (Google, Apple, Microsoft, Amazon, AMD, Nvidia). 88 89 … … 93 94 However, most programming languages are only partially explained by their standard's manual(s). 94 95 When it comes to explaining how C works, the definitive source is the @gcc@ compiler, which is mimicked by other C compilers, such as Clang~\cite{clang}. 95 Often other C compilers mustmimic @gcc@ because a large part of the C library (runtime) system (@glibc@ on Linux) contains @gcc@ features.96 Often other C compilers \emph{must} mimic @gcc@ because a large part of the C library (runtime) system (@glibc@ on Linux) contains @gcc@ features. 96 97 Some key aspects of C need to be explained and understood by quoting from the language reference manual. 97 98 However, to illustrate actual program semantics, this thesis constructs multiple small programs whose behaviour exercises a particular point and then confirms the behaviour by running the program using multiple @gcc@ compilers. … … 100 101 \item if the compiler accepts or rejects certain syntax, 101 102 \item prints output to buttress a behavioural claim, 102 \item or executes without triggering anyembedded assertions testing pre/post-assertions or invariants.103 \item or fails to trigger embedded assertions testing pre/post-assertions or invariants. 103 104 \end{itemize} 104 105 These programs are tested across @gcc@ versions 8--14 and clang versions 10--14 running on ARM, AMD, and Intel architectures. … … 120 121 Introduce a small number of subtle changes to the typing rules for the C array, while still achieving significant backwards compatibility 121 122 \item 122 Create a new polymorphic mechanism in to the \CFA @forall@ clause for specifyingarray dimension values, similar to a fixed-typed parameter in a \CC \lstinline[language=C++]{template}.123 Create a new polymorphic mechanism in the \CFA @forall@ clause to specify array dimension values, similar to a fixed-typed parameter in a \CC \lstinline[language=C++]{template}. 123 124 \item 124 125 Construct a new standard-library array-type, available through @#include <array.hfa>@. … … 130 131 131 132 132 \subsection{Linked list}133 \subsection{Linked List} 133 134 134 135 The linked list is a new runtime library, available through @#include <dlist.hfa>@. … … 141 142 \subsection{String} 142 143 143 The string is a new runtime library,available through @#include <string.hfa>@.144 The new string type and its runtime library are available through @#include <string.hfa>@. 144 145 The library offers a type where basic usage is comparable to the \CC @string@ type, including analogous coexistence with raw-character pointers. 145 146 Its implementation, however, follows different principles, enabling programs to work with strings by value, without incurring excessive copying. 146 147 Mutability is retained. 147 148 Substrings are supported, including the ability for overlapping ranges to share edits transparently. 148 Ultimately, the implementation is a set of strings rolled into their own specialized heap.149 The implementation allows a set of strings to use an optimized, shared, custom heap or to use the regular heap for thread safety. 149 150 150 The string library includes writing and reading strings via the preexisting \CFA I/O stream library.151 Enabling transparent reading (of unknown length into a managed allocation) included revision of the stream library's existing handling of character arrays.152 All reasonable stream manipulators are supported, \eg width, justification (left/right), printing characters as their numeric values, and complex input scanning to isolate strings .151 The string library includes reading and writing strings via the preexisting \CFA I/O stream library. 152 Enabling transparent reading of unknown length strings using managed allocation required revision of the stream library's existing handling of character arrays. 153 All reasonable stream manipulators are supported, \eg width, justification (left/right), printing characters as their numeric values, and complex input scanning to isolate strings in the input stream. 153 154 154 155 … … 159 160 Hence, the infamous \CC bug of iterator invalidation, where structural changes cause legitimate operations to fail, \eg iterator over a list and deleting each element. 160 161 161 Further design provides a home for Liskov-style iterators in \CFA.162 Further design provides a home for Liskov-style iterators (stackless-coroutine) in \CFA. 162 163 This design extends a preexisting proposal to adapt the \CFA (fixed) for-each loop to be more user-pluggable, and builds upon preexisting \CFA coroutines. 163 164 Overall, it simplifies the work a programmer must do to leverage the suspended-state abstraction during iteration. -
doc/theses/mike_brooks_MMath/list.tex
rf632bd50 rb195498 15 15 16 16 The doubly-linked list attaches links intrusively, supports multiple link directions, integrates with user code via the type system, treats its ends uniformly, and identifies a list using an explicit head. 17 This design covers system and data management issues stated in Section~\ref{toc:lst:issue}.18 19 Figure~\ref{fig:lst-features-intro} continues the running @req@ example from Figure~\ref{fig:lst-issues-attach} using the \CFA list.20 The \CFA link attachment is intrusive so the resulting memory layout is per user node, as for the LQ version of Figure~\ref{f:Intrusive}.17 This design covers system and data management issues stated in \VRef{toc:lst:issue}. 18 19 \VRef[Figure]{fig:lst-features-intro} continues the running @req@ example from \VRef[Figure]{fig:lst-issues-attach} using the \CFA list. 20 The \CFA link attachment is intrusive so the resulting memory layout is per user node, as for the LQ version of \VRef[Figure]{f:Intrusive}. 21 21 The \CFA framework provides generic type @dlink( T, T )@ for the two link fields (front and back). 22 22 A user inserts the links into the @req@ structure via \CFA inline-inheritance from the Plan-9 C dialect~\cite[\S~3.3]{Thompson90new}. … … 34 34 \caption[Multiple link directions in \CFA list library]{ 35 35 Demonstration of the running \lstinline{req} example, done using the \CFA list library. 36 This example is equivalent to the three approaches in Figure~\ref{fig:lst-issues-attach}.36 This example is equivalent to the three approaches in \VRef[Figure]{fig:lst-issues-attach}. 37 37 } 38 38 \label{fig:lst-features-intro} 39 39 \end{figure} 40 40 41 Figure~\ref{fig:lst-features-multidir} shows how the \CFA library supports multi-inline links, so a node can be on one or more lists simultaneously.41 \VRef[Figure]{fig:lst-features-multidir} shows how the \CFA library supports multi-inline links, so a node can be on one or more lists simultaneously. 42 42 The declaration of @req@ has two inline-inheriting @dlink@ occurrences. 43 43 The first of these gives a type named @req.by_pri@, @req@ inherits from it, and it inherits from @dlink@. … … 48 48 The type of the variable @reqs_pri_global@ is @dlist(req, req.by_pri)@, meaning operations called on @reqs_pri_global@ are implicitly disambiguated. 49 49 In the example, the calls @insert_first(reqs_pri_global, ...)@ imply, ``here, we are working by priority.'' 50 As in Figure~\ref{fig:lst-issues-multi-static}, three lists are constructed, a priority list containing all nodes, a list with only nodes containing the value 42, and a list with only nodes containing the value 17.50 As in \VRef[Figure]{fig:lst-issues-multi-static}, three lists are constructed, a priority list containing all nodes, a list with only nodes containing the value 42, and a list with only nodes containing the value 17. 51 51 52 52 \begin{figure} … … 63 63 \caption{ 64 64 Demonstration of multiple static link directions done in the \CFA list library. 65 The right example is from Figure~\ref{fig:lst-issues-multi-static}.65 The right example is from \VRef[Figure]{fig:lst-issues-multi-static}. 66 66 The left \CFA example does the same job. 67 67 } … … 70 70 71 71 The \CFA library also supports the common case, of single directionality, more naturally than LQ. 72 Figure~\ref{fig:lst-features-intro} shows a single-direction list done with no contrived name for the link direction,73 where Figure~\ref{f:Intrusive} adds the unnecessary field name, @d@.74 In \CFA, a user doing a single direction ( Figure~\ref{fig:lst-features-intro}) sets up a simple inheritance with @dlink@, and declares a list head to have the simpler type @dlist( T )@.75 In contrast, ( Figure~\ref{fig:lst-features-multidir}) sets up a diamond inheritance with @dlink@, and declares a list head to have the more-informed type @dlist( T, DIR )@.72 \VRef[Figure]{fig:lst-features-intro} shows a single-direction list done with no contrived name for the link direction, 73 where \VRef[Figure]{f:Intrusive} adds the unnecessary field name, @d@. 74 In \CFA, a user doing a single direction (\VRef[Figure]{fig:lst-features-intro}) sets up a simple inheritance with @dlink@, and declares a list head to have the simpler type @dlist( T )@. 75 In contrast, (\VRef[Figure]{fig:lst-features-multidir}) sets up a diamond inheritance with @dlink@, and declares a list head to have the more-informed type @dlist( T, DIR )@. 76 76 77 77 The directionality issue also has an advanced corner-case that needs treatment. … … 118 118 By using a larger scope, a user can put code within that acts as if there is only one list direction. 119 119 This boost is needed only when operating on a list with several directions, using operations that do not take the list head. 120 Otherwise, the sole applicable list direction ``just works.''120 Otherwise, the sole applicable list direction \emph{just works}. 121 121 122 122 Unlike \CC templates container-types, the \CFA library works completely within the type system; … … 138 138 @isEmpty@ returns true if the list has no nodes and false otherwise. 139 139 \item 140 @first@ returns a pointer to the first node of the list without removing it or @0p@ if the list is empty. 141 \item 142 @last@ returns a pointer to the last node of the list without removing it or @0p@ if the list is empty. 143 \item 144 @next@ returns a pointer to the next (successor, towards last) node after the specified node or @0p@ if the specified node is the last node in the list. 145 \item 146 @pred@ returns a pointer to the previous (predecessor, towards first) node before the specified node or @0p@ if the specified node is the first node in the list. 140 @first@ returns a reference to the first node of the list without removing it or @0p@ if the list is empty. 141 \item 142 @last@ returns a reference to the last node of the list without removing it or @0p@ if the list is empty. 147 143 \item 148 144 @insert_before@ adds a node before the specified node and returns the added node for cascading. … … 150 146 @insert_after@ adds a node after the specified node and returns the added node for cascading. 151 147 \item 152 @remove@ removes the specified node from the list (any location) and returns a pointer to the node. 153 \item 154 @insert_first@ adds a node to the start of the list so it becomes the first node and returns a pointer to the node for cascading. 155 \item 156 @insert_last@ adds a node to the end of the list so it becomes the last node and returns returns a pointer to the node for cascading. 157 \item 158 @insert@ is a synonym for @insert_last@. 159 \item 160 @remove_first@ removes the first node and returns a pointer to it or @0p@ if the list is empty. 161 \item 162 @remove_last@ removes the last node and returns a pointer to it or @0p@ if the list is emptyy. 148 @remove@ removes the specified node from the list (any location) and returns a reference to the node. 149 \item 150 @iter@ create an iterator for the list. 151 \item 152 @recede@ returns true if the iterator cursor is advanced to the previous (predecessor, towards first) node before the prior cursor node and false otherwise. 153 \item 154 @advance@ returns true if the iterator cursor is advanced to the next (successor, towards last) node after the prior cursor node and false otherwise. 155 \item 156 @isFirst@ returns true if the node is the first node in the list and false otherwise. 157 \item 158 @isLast@ returns true if the node is the last node in the list and false otherwise. 159 \item 160 @pred@ returns a reference to the previous (predecessor, towards first) node before the specified node or @0p@ if the specified node is the first node in the list. 161 \item 162 @next@ returns a reference to the next (successor, towards last) node after the specified node or @0p@ if the specified node is the last node in the list. 163 \item 164 @insert_first@ adds a node to the start of the list so it becomes the first node and returns a reference to the node for cascading. 165 \item 166 @insert_last@ adds a node to the end of the list so it becomes the last node and returns returns a reference to the node for cascading. 167 \item 168 @remove_first@ removes the first node and returns a reference to it or @0p@ if the list is empty. 169 \item 170 @remove_last@ removes the last node and returns a reference to it or @0p@ if the list is empty. 163 171 \item 164 172 @transfer@ transfers all nodes from the @from@ list to the end of the @to@ list; the @from@ list is empty after the transfer. … … 170 178 \begin{figure} 171 179 \begin{cfa} 172 E & ?`isEmpty( dlist( E ) & list ); 173 E & ?`isListed( E & node ); 174 E & ?`first( dlist( E ) & list ); 175 E & ?`last( dlist( E ) & list ); 176 E & ?`next( E & node ); 177 E & ?`prev( E & node ); 180 E & isListed( E & node ); 181 E & isEmpty( dlist( E ) & list ); 182 E & first( dlist( E ) & list ); 183 E & last( dlist( E ) & list ); 178 184 E & insert_before( E & before, E & node ); 179 185 E & insert_after( E & after, E & node ); 180 186 E & remove( E & node ); 181 E & ?`elems( dlist( E ) & list ); 182 E & ?`head( dlist( E ) & list ); 183 bool ?`moveNext( E && refx ); 184 bool ?`next( E && refx ); // alternate name 185 bool ?`movePrev( E && refx ); 186 bool ?`prev( E && refx ); // alternate name 187 bool ?`hasNext( E & node ); 188 bool ?`hasPrev( E & node ); 187 E & iter( dlist( E ) & list ); 188 bool advance( E && refx ); 189 bool recede( E && refx ); 190 bool isFirst( E & node ); 191 bool isLast( E & node ); 192 E & prev( E & node ); 193 E & next( E & node ); 189 194 E & insert_first( dlist( E ) & list, E & node ); 190 195 E & insert_last( dlist( E ) & list, E & node ); 191 E & insert( dlist( E ) & list, E & node ); // alternate name192 196 E & remove_first( dlist( E ) & list ); 193 197 E & remove_last( dlist( E ) & list ); 194 198 void transfer( dlist( E ) & to, dlist( E ) & from ) { 195 199 void split( dlist( E ) & to, dlist( E ) & from, E & node ) { 196 E & try_pop_front( dlist( E ) & list );197 E & try_pop_back( dlist( E ) & list );198 200 \end{cfa} 199 201 \caption{\CFA List API} … … 205 207 206 208 It is possible to iterate through a list manually or using a set of standard macros. 207 \VRef[Figure]{f:Iterator Example} shows the iterator template, managing a list of nodes, used throughout the following iterator examples.209 \VRef[Figure]{f:IteratorTemple} shows the iterator template, managing a list of nodes, used throughout the following iterator examples. 208 210 Each example assumes its loop body prints the value in the current node. 209 211 … … 222 224 insert( list, n1 ); insert( list, n2 ); insert( list, n3 ); insert( list, n4 ); 223 225 sout | nlOff; 224 for ( node & it = list`first; ⁢ &it = &it`next ) @sout | it.v | ","; sout | nl;@ 225 // other iterator examples 226 for ( ... ) @sout | it.v | ","; sout | nl;@ // iterator examples in text 226 227 remove( n1 ); remove( n2 ); remove( n3 ); remove( n4 ); 227 228 } 228 229 \end{cfa} 229 \caption{Iterator Example}230 \label{f:Iterator Example}230 \caption{Iterator Temple} 231 \label{f:IteratorTemple} 231 232 \end{figure} 232 233 … … 243 244 \begin{tabular}{@{}l|l@{}} 244 245 \begin{cfa} 245 for ( node & it = list`@first@; &it /* != 0p */ ; &it = &it`@next@) ...246 for ( node & it = list`@last@; ⁢ &it = &it`@prev@) ...246 for ( node & it = @first@( list ); &it /* != 0p */ ; &it = &@next@( it ) ... 247 for ( node & it = @last@( list ); ⁢ &it = &@prev@( it ) ) ... 247 248 \end{cfa} 248 249 & … … 258 259 \begin{tabular}{@{}l|l@{}} 259 260 \begin{cfa} 260 for ( node & it = @n2@; ⁢ &it = & it`@next@) ...261 for ( node & it = @n3@; ⁢ &it = & it`@prev@) ...261 for ( node & it = @n2@; ⁢ &it = &@next@( it ) ) ... 262 for ( node & it = @n3@; ⁢ &it = &@prev@( it ) ) ... 262 263 \end{cfa} 263 264 & … … 268 269 \end{tabular} 269 270 \end{cquote} 270 Iterating forward and reverse from a starting node to an ending node through the remaininglist.271 \begin{cquote} 272 \setlength{\tabcolsep}{15pt} 273 \begin{tabular}{@{}l|l@{}} 274 \begin{cfa} 275 for ( node & it = @n2@; &it @!= &n4@; &it = & it`@next@) ...276 for ( node & it = @n4@; &it @!= &n2@; &it = & it`@prev@) ...271 Iterating forward and reverse from a starting node to an ending node through the contained list. 272 \begin{cquote} 273 \setlength{\tabcolsep}{15pt} 274 \begin{tabular}{@{}l|l@{}} 275 \begin{cfa} 276 for ( node & it = @n2@; &it @!= &n4@; &it = &@next@( it ) ) ... 277 for ( node & it = @n4@; &it @!= &n2@; &it = &@prev@( it ) ) ... 277 278 \end{cfa} 278 279 & … … 284 285 \end{cquote} 285 286 Iterating forward and reverse through the entire list using the shorthand start at the list head and pick a direction. 286 In this case, @ next@ and @prev@ return a boolean, like \CC @while ( cin >> i )@.287 \begin{cquote} 288 \setlength{\tabcolsep}{15pt} 289 \begin{tabular}{@{}l|l@{}} 290 \begin{cfa} 291 for ( node & it = list`@head@; it`@next@; ) ...292 for ( node & it = list`@head@; it`@prev@; ) ...287 In this case, @advance@ and @recede@ return a boolean, like \CC @while ( cin >> i )@. 288 \begin{cquote} 289 \setlength{\tabcolsep}{15pt} 290 \begin{tabular}{@{}l|l@{}} 291 \begin{cfa} 292 for ( node & it = @iter@( list ); @advance@( it ); ) ... 293 for ( node & it = @iter@( list ); @recede@( it ); ) ... 293 294 \end{cfa} 294 295 & … … 330 331 \end{tabular} 331 332 \end{cquote} 332 The ability to provide a language-level @foreach@ is a future \CFA project.333 Macros are not ideal, so future work is to provide a language-level @foreach@ statement, like \CC. 333 334 Finally, a predicate can be added to any of the manual iteration loops. 334 335 \begin{cquote} … … 336 337 \begin{tabular}{@{}l|l@{}} 337 338 \begin{cfa} 338 for ( node & it = list`first; &it @&& !(it.v == 3)@; &it = &it`next) ...339 for ( node & it = l ist`last; &it @&& !(it.v == 1)@; &it = &it`prev) ...340 for ( node & it = list`head; it`next@&& !(it.v == 3)@; ) ...341 for ( node & it = list`head; it`prev@&& !(it.v == 1)@; ) ...339 for ( node & it = first( list ); &it @&& !(it.v == 3)@; &it = &next( it ) ) ... 340 for ( node & it = last( list ); &it @&& !(it.v == 1)@; &it = &prev( it ) ) ... 341 for ( node & it = iter( list ); advance( it ) @&& !(it.v == 3)@; ) ... 342 for ( node & it = iter( list ); recede( it ) @&& !(it.v == 1)@; ) ... 342 343 \end{cfa} 343 344 & … … 439 440 440 441 441 442 442 \section{Implementation} 443 444 \subsection{Links}445 443 446 444 \VRef[Figure]{fig:lst-impl-links} continues the running @req@ example, now showing the \CFA list library's internal representation. 447 445 The @dlink@ structure contains exactly two pointers: @next@ and @prev@, which are opaque to a user. 448 Even though the user-facing list model is ordered (linear), the CFA library implements all listing as circular.446 Even though the user-facing list model is linear, the CFA library implements all listing as circular. 449 447 This choice helps achieve uniform end treatment and TODO finish summarizing benefit. 450 448 A link pointer targets a neighbouring @dlink@ structure, rather than a neighbouring @req@. … … 460 458 \end{figure} 461 459 462 Link pointers are internally tagged according to whether the link is user-visible. 463 Links among user-requested neighbours are left natural, with the tag bit not set. 464 System-added links, which produce the circular implementation, have the tag bit set. 460 System-added link pointers (dashed lines) are internally tagged to indicate linear endpoints that are the circular pointers. 461 Links among neighbour nodes are not tagged. 465 462 Iteration reports ``has more elements'' when crossing natural links, and ``no more elements'' upon reaching a tagged link. 466 463 467 464 In a headed list, the list head (@dlist(req)@) acts as an extra element in the implementation-level circularly-linked list. 468 The content of a @dlist@ is a (private) @dlink@, with the @next@ pointer purposed for the first element, and the @prev@ pointer purposed forthe last element.469 Since the head wraps a @dlink@, since a @req@ does too, and since a link-pointer targets a @dlink@, the resulting cycle is among @dlink@ structures, situated inside of other things.470 The tags on the links say what the wrapper is: untagged (user link) means the targeted @dlink@ is within a @req@, while tagged (system link) means the targeted @dlink@ is within a list head.471 472 In a headless list, the circular backing list is only among @dlink@s within @req@s.The tags are set on the links that a user cannot navigate.473 474 No distinction is made between an unlisted item under a headed model and a singleton list under a headless model. Both are represented as an item referring to itself, with both tags set.475 465 The content of a @dlist@ is a (private) @dlink@, with the @next@ pointer to the first element, and the @prev@ pointer to the last element. 466 Since the head wraps a @dlink@, as does a @req@ does too, and since a link-pointer targets a @dlink@, the resulting cycle is among @dlink@ structures, situated inside of header/node. 467 An untagged pointer points within a @req@, while a tagged pointer points within a list head. 468 In a headless list, the circular backing list is only among @dlink@s within @req@s. 469 The tags are set on the links that a user cannot navigate. 470 471 No distinction is made between an unlisted item under a headed model and a singleton list under a headless model. 472 Both are represented as an item referring to itself, with both tags set. 476 473 477 474 -
doc/theses/mike_brooks_MMath/programs/bkgd-carray-mdim.c
rf632bd50 rb195498 14 14 15 15 int main() { 16 float ar[3][10];17 static_assert( sizeof(float) == 4 ); $\C {// floats (atomic elements) are 4 bytes}$18 static_assert( sizeof(void *) == 8 ); $\C{// pointers are 8 bytes}$16 float mx[3][10]; 17 static_assert( sizeof(float) == 4 ); $\C[3.25in]{// floats (atomic elements) are 4 bytes}$ 18 static_assert( sizeof(void *) == 8 ); $\C{// pointers are 8 bytes}$ 19 19 20 static_assert( sizeof( ar) == 120 ); $\C{// the array, float[3][10]}$21 static_assert( sizeof( ar[0]) == 40 ); $\C{// its first element, float[10]}$22 static_assert( sizeof( ar[0][0]) == 4 ); $\C{// its first grand element, float}$20 static_assert( sizeof(mx) == 120 ); $\C{// the array, float[3][10]}$ 21 static_assert( sizeof(mx[0]) == 40 ); $\C{// its first element, float[10]}$ 22 static_assert( sizeof(mx[0][0]) == 4 ); $\C{// its first grand element, float}$ 23 23 24 static_assert( sizeof(&( ar)) == 8 ); $\C{// pointer to the array, float(*)[3][10]}$25 static_assert( sizeof(&( ar[0])) == 8 ); $\C{// pointer to its first element, float(*)[10]}$26 static_assert( sizeof(&( ar[0][0])) == 8 ); $\C{// pointer to its first grand-element, float*}$24 static_assert( sizeof(&(mx)) == 8 ); $\C{// pointer to the array, float(*)[3][10]}$ 25 static_assert( sizeof(&(mx[0])) == 8 ); $\C{// pointer to its first element, float(*)[10]}$ 26 static_assert( sizeof(&(mx[0][0])) == 8 ); $\C{// pointer to its first grand-element, float*}\CRT$ 27 27 28 float (*p a)[3][10] = &(ar);29 float (*p a0)[10] = &(ar[0]);30 float *p a00 = &(ar[0][0]);28 float (*pm)[3][10] = &(mx); 29 float (*pm0)[10] = &(mx[0]); 30 float *pm00 = &(mx[0][0]); 31 31 32 static_assert( (void *)&ar == (void*)&(ar[0] ) );33 static_assert( (void *)&ar == (void*)&(ar[0][0]) );32 static_assert( (void *)&mx == (void *)&(mx[0] ) ); 33 static_assert( (void *)&mx == (void *)&(mx[0][0]) ); 34 34 35 assert( (void *) p a == (void *) pa0 );36 assert( (void *) p a == (void *) pa00 );35 assert( (void *) pm == (void *) pm0 ); 36 assert( (void *) pm == (void *) pm00 ); 37 37 38 38 // float (*b[3])[10]; 39 float * b[3];39 float * b[3]; 40 40 for (int i = 0; i < 3; i ++) { 41 41 b[i] = malloc(sizeof(float[10])); 42 42 } 43 ar[2][3];43 mx[2][3]; 44 44 b[2][3]; 45 45 /* -
doc/theses/mike_brooks_MMath/programs/lst-features-intro.run.cfa
rf632bd50 rb195498 50 50 51 51 52 while( req & cur = reqs`elems; cur`moveNext)52 while( req & cur = iter( reqs ); advance( cur ) ) 53 53 printf("{%d %d} ", cur.pri, cur.rqr); 54 54 printf("\n"); -
doc/theses/mike_brooks_MMath/programs/lst-features-multidir.run.cfa
rf632bd50 rb195498 79 79 80 80 with(DLINK_VIA(req, req.by_pri)) { 81 while( req & cur = reqs_pri_global`elems; cur`moveNext)81 while( req & cur = iter( reqs_pri_global ); advance( cur ) ) 82 82 printf("{%d %d} ", cur.pri, cur.rqr); 83 83 printf("| "); … … 85 85 86 86 with(DLINK_VIA(req, req.by_rqr)) { 87 while( req & cur = reqs_rqr_42`elems; cur`moveNext)87 while( req & cur = iter( reqs_rqr_42 ); advance( cur ) ) 88 88 printf("{%d %d} ", cur.pri, cur.rqr); 89 89 printf("| "); 90 while( req & cur = reqs_rqr_17`elems; cur`moveNext)90 while( req & cur = iter( reqs_rqr_17 ); advance( cur ) ) 91 91 printf("{%d %d} ", cur.pri, cur.rqr); 92 92 printf("| "); 93 while( req & cur = reqs_rqr_99`elems; cur`moveNext)93 while( req & cur = iter( reqs_rqr_99 ); advance( cur ) ) 94 94 printf("{%d %d} ", cur.pri, cur.rqr); 95 95 printf("\n");
Note:
See TracChangeset
for help on using the changeset viewer.