Changeset 4740281


Ignore:
Timestamp:
Apr 17, 2025, 10:25:00 PM (13 hours ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
master
Parents:
15eebd4
Message:

proofread list chapter

Location:
doc/theses/mike_brooks_MMath
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified doc/theses/mike_brooks_MMath/list.tex

    r15eebd4 r4740281  
    11\chapter{Linked List}
    22
    3 I wrote a linked-list library for \CFA.  This chapter describes it.
    4 
    5 The library provides a doubly-linked list that
    6 attaches links intrusively,
    7 supports multiple link directions,
    8 integrates with user code via the type system,
    9 treats its ends uniformly, and
    10 identifies a list using an explicit head.
    11 
    12 TODO: more summary
    13 
     3This chapter presents my work on designing and building a linked-list library for \CFA.
     4Due to time limitations and the needs expressed by the \CFA runtime developers, I focussed on providing a doubly-linked list, and its bidirectionally iterators for traversal.
     5Simpler data-structures, like stack and queue, can be built from the doubly-linked mechanism with only a slight storage/performance cost because of the unused link field.
     6Reducing to data-structures with a single link follows directly from the more complex doubly-links and its iterators.
    147
    158
    169\section{Features}
    1710
     11The following features directed this project, where the goal is high-performance list operations required by \CFA runtime components, like the threading library.
     12
     13
    1814\subsection{Core Design Issues}
    1915
    20 This section reviews how a user experiences my \CFA list library's position on the issues of Section~\ref{toc:lst:issue}.
    21 The library provides a doubly-linked list that
    22 attaches links intrusively,
    23 supports multiple link directions,
    24 integrates with user code via the type system,
    25 treats its ends uniformly, and
    26 identifies a list using an explicit head.
    27 
    28 The \CFA list library's version of the running @req@ example is in Figure~\ref{fig:lst-features-intro}.
    29 Its link attachment is intrusive and the resulting memory layout is pure-stack, just as for the LQ version of Figure~\ref{f:Intrusive}.
    30 The framework-provided type @dlink(...)@ provides the links.
    31 The user inserts the links into the @req@ structure by using \CFA inline-inheritance (TODO: reference introduction).
    32 Inline inheritance means the type of the field is @dlink(req)@, the field is unnamed, a reference to a @req@ is implicitly convertible to @dlink@.\footnote{
    33     The \CFA list examples elide the \lstinline{P9_EMBEDDED} annotations that (TODO: xref P9E future work) proposes to obviate.
    34     Thus, these examples illustrate a to-be state, free of what is to be historic clutter.
    35     The elided portions are immaterial to the discussion and the examples work with the annotations provided.
    36     The \CFA test suite (TODO:cite?) includes equivalent demonstrations, with the annotations included.}
    37 These links have a nontrivial, user-specified location within the @req@ structure;
    38 this convention encapsulates the implied pointer arithmetic safely.
     16The 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.
     17This design covers system and data management issues stated in Section~\ref{toc:lst:issue}.
     18
     19Figure~\ref{fig:lst-features-intro} continues the running @req@ example from Figure~\ref{fig:lst-issues-attach} using the \CFA list.
     20The \CFA link attachment is intrusive so the resulting memory layout is per user node, as for the LQ version of Figure~\ref{f:Intrusive}.
     21The \CFA framework provides generic type @dlink( T, T )@ for the two link fields (front and back).
     22A user inserts the links into the @req@ structure via \CFA inline-inheritance from the Plan-9 C dialect~\cite[\S~3.3]{Thompson90new}.
     23Inline inheritance is containment, where the inlined field is unnamed but the type's internal fields are hoisted into the containing structure.
     24Hence, the field names must be unique, unlike \CC nested types, but the type names are at a nested scope level, unlike aggregate nesting in C.
     25Note, the position of the containment is normally unimportant, unless there is some form of memory or @union@ overlay.
     26The key feature of inlined inheritance is that a pointer to the containing structure is automatically converted to a pointer to any anonymous inline field for assignments and function calls, providing containment inheritance with implicit subtyping.
     27Therefore, a reference to a @req@ is implicitly convertible to @dlink@ in assignments and function calls.
     28% These links have a nontrivial, user-specified location within the @req@ structure;
     29% this convention encapsulates the implied pointer arithmetic safely.
     30The links in @dlist@ point at (links) in the containing node, know the offsets of all links (data is abstract), and any field-offset arithmetic or link-value changes are safe and abstract.
    3931
    4032\begin{figure}
    41     \lstinput{20-32}{lst-features-intro.run.cfa}
     33    \lstinput{20-30}{lst-features-intro.run.cfa}
    4234    \caption[Multiple link directions in \CFA list library]{
    4335        Demonstration of the running \lstinline{req} example, done using the \CFA list library.
    44         This example does the same job that Figure~\ref{fig:lst-issues-attach} shows three ways.
     36        This example is equivalent to the three approaches in Figure~\ref{fig:lst-issues-attach}.
    4537    }
    4638    \label{fig:lst-features-intro}
    4739\end{figure}
     40
     41Figure~\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.
     42The declaration of @req@ has two inline-inheriting @dlink@ occurrences.
     43The first of these gives a type named @req.by_pri@, @req@ inherits from it, and it inherits from @dlink@.
     44The second line @req.by_rqr@ is similar to @req.by_pri@.
     45Thus, there is a diamond, non-virtual, inheritance from @req@ to @dlink@, with @by_pri@ and @by_rqr@ being the mid-level types.
     46
     47Disambiguation occurs in the declarations of the list-head objects: @reqs_pri_global@, @reqs_rqr_42@, @reqs_rqr_17@, and @reqs_rqr_99@.
     48The type of the variable @reqs_pri_global@ is @dlist(req, req.by_pri)@, meaning operations called on @reqs_pri_global@ are implicitly disambiguated.
     49In the example, the calls @insert_first(reqs_pri_global, ...)@ imply, ``here, we are working by priority.''
     50As 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.
    4851
    4952\begin{figure}
     
    5154\begin{tabular}{@{}ll@{}}
    5255\begin{tabular}{@{}l@{}}
    53     \lstinput{20-25}{lst-features-multidir.run.cfa} \\
    54     \lstinput{40-67}{lst-features-multidir.run.cfa}
     56    \lstinput{20-31}{lst-features-multidir.run.cfa} \\
     57    \lstinput{43-71}{lst-features-multidir.run.cfa}
    5558    \end{tabular}
    5659        &
     
    6063\caption{
    6164        Demonstration of multiple static link directions done in the \CFA list library.
    62         This example does the same job as Figure~\ref{fig:lst-issues-multi-static}.
     65        The right example is from Figure~\ref{fig:lst-issues-multi-static}.
     66                The left \CFA example does the same job.
    6367    }
    6468    \label{fig:lst-features-multidir}
    6569\end{figure}
    6670
    67 Figure~\ref{fig:lst-features-multidir} shows how the \CFA library supports multi-static link directionality.
    68 The declaration of @req@ now has two inline-inheriting @dlink@ occurrences.
    69 The first of these lines gives a type named @req.by_pri@, @req@ inherits from it, and it inherits from @dlink@.
    70 The second line @req.by_rqr@ is similar to @req.by_pri@.
    71 Thus, there is a diamond, non-virtual, inheritance from @req@ to @dlink@, with @by_pri@ and @by_rqr@ being the mid-level types.
    72 Disambiguation occurs in the declarations of the list-head objects.
    73 The type of the variable @reqs_pri_global@ is @dlist(req, req.by_pri)@,
    74 meaning operations called on @reqs_pri_global@ are implicitly disambiguated.
    75 In the example, the calls @insert_first(reqs_pri_global, ...)@ imply, ``here, we are working by priority.''
    76 
    7771The \CFA library also supports the common case, of single directionality, more naturally than LQ. 
    7872Figure~\ref{fig:lst-features-intro} shows a single-direction list done with no contrived name for the link direction,
    79 where Figure~\ref{f:Intrusive} adds the unnecessary name, @x@.
    80 In \CFA, a user doing a single direction (Figure~\ref{fig:lst-features-intro})
    81 sets up a simple inheritance with @dlink@, and declares a list head to have the simpler type @dlist(...)@.
    82 While a user doing multiple link directions (Figure~\ref{fig:lst-features-multidir})
    83 sets up a diamond inheritance with @dlink@, and declares a list head to have the more-informed type @dlist(..., DIR)@.
     73where Figure~\ref{f:Intrusive} adds the unnecessary field name, @d@.
     74In \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 )@.
     75In 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 )@.
    8476
    8577The directionality issue also has an advanced corner-case that needs treatment.
    86 When working with multiple directions, while calls like @insert_first@ benefit from implicit direction disambiguation, other calls like @insert_after@ still require explicit disambiguation.
    87 It happens because the call
     78When working with multiple directions, calls like @insert_first@ benefit from implicit direction disambiguation;
     79however, other calls like @insert_after@ still require explicit disambiguation, \eg the call
    8880\begin{cfa}
    8981insert_after(r1, r2);
    9082\end{cfa}
    9183does not have enough information to clarify which of a request's simultaneous list directions is intended.
    92 Is @r2@ supposed to be the next-priority request after @r1@, or is @r2@ supposed to join the same-requestor list of @r1@?
     84Is @r2@ supposed to be the next-priority request after @r1@, or is @r2@ supposed to join the same-requester list of @r1@?
    9385As such, the \CFA compiler gives an ambiguity error for this call.
    94 To let the programmer resolve the ambiguity, the list library provides a hook for applying the \CFA language's scoping and priority rules.
     86To resolve the ambiguity, the list library provides a hook for applying the \CFA language's scoping and priority rules.
    9587It applies as:
    9688\begin{cfa}
    9789with ( DLINK_VIA(req, req.pri) ) insert_after(r1, r2);
    9890\end{cfa}
    99 Here, importing (using the @with@ syntax on) the @DLINK_VIA@ result causes one of the list directions to become a more attrictive candidate to \CFA's overload resolution.
    100 This boost applies within the scope of the the import, which is a single line in the example just given, but could also be a custom block or an entire function body.
    101 
    102 \noindent
    103 \begin{tabular}{ll}
    104 \begin{cfa}
    105 void f() with ( DLINK_VIA(req, req.pri) ) {
    106     ...
    107 
    108     insert_after(r1, r2);
    109 
    110     ...
     91Here, the @with@ statement opens the scope of the object type for the expression;
     92hence, the @DLINK_VIA@ result causes one of the list directions to become a more attractive candidate to \CFA's overload resolution.
     93This boost applies within the scope of the following statement, but could also be a custom block or an entire function body.
     94\begin{cquote}
     95\setlength{\tabcolsep}{15pt}
     96\begin{tabular}{@{}ll@{}}
     97\begin{cfa}
     98void f() @with( DLINK_VIA(req, req.pri) )@ {
     99        ...
     100
     101        insert_after(r1, r2);
     102
     103        ...
    111104}
    112105\end{cfa}
     
    114107\begin{cfa}
    115108void f() {
    116     ...
    117     with ( DLINK_VIA(req, req.pri) ) {
    118         ...
    119     }
    120     ...
     109        ...
     110        @with( DLINK_VIA(req, req.pri) )@ {
     111                ...  insert_after(r1, r2);  ...
     112        }
     113        ...
    121114}
    122115\end{cfa}
    123116\end{tabular}
    124 
    125 \noindent
    126 By doing in on a larger scope, a user can put code within that acts as if there is only one list direction.
    127 This boost is needed only when operating on a list with several directions, using operations that do not take list heads.
     117\end{cquote}
     118By using a larger scope, a user can put code within that acts as if there is only one list direction.
     119This boost is needed only when operating on a list with several directions, using operations that do not take the list head.
    128120Otherwise, the sole applicable list direction ``just works.''
    129121
    130 The \CFA library offers a type-system mediated integration with user code.
    131 The examples presented do not use preprocessor macros.
    132 The touchpoints @dlink@ and @dlist@ are ordinary types.
    133 Even though they are delivered as header-included static-inline implementations,
    134 the \CFA compiler typechecks the list library code separately from user code.
     122Unlike \CC templates container-types, the \CFA library works completely within the type system;
     123both @dlink@ and @dlist@ are ordinary types.
     124There is no textual expansion other than header-included static-inline function for performance.
    135125Errors in user code are reported only with mention of the library's declarations.
     126Finally, the library is separately compiled from the usage code.
    136127
    137128The \CFA library works in headed and headless modes.  TODO: elaborate.
     
    141132\subsection{Iteration}
    142133
    143 Many languages offer an iterator interface for collections to implement, and a corresponding for-each loop syntax for consuming the items through implicit interface calls.
     134Many languages offer an iterator interface for collections, and a corresponding for-each loop syntax for consuming the items through implicit interface calls.
    144135\CFA does not yet have a general-purpose form of such a feature, though it has a form that addresses some use cases.
    145 This section shows why the incumbemt \CFA pattern does not work for linked lists and gives the alternative now offered by the linked-list libary.
     136This section shows why the incumbent \CFA pattern does not work for linked lists and gives the alternative now offered by the linked-list library.
    146137Chapter 5 [TODO: deal with optimism here] presents a design that satisfies both uses and accommodates even more complex collections.
    147138
    148 The incumbent \CFA extensible loop syntax is:
    149 \begin{cfa}
     139The current \CFA extensible loop syntax is:
     140\begin{cfa}
     141for( elem; end )
    150142for( elem; begin ~ end )
    151 for( elem; end )
    152 \end{cfa}
    153 Many derived forms of @begin ~ end@ exist, but they of primaty interest to defining numeric ranges, so they are excluded from the linked-list discussion.
    154 This ``two-place for'' syntax abbreviates, respectively:
    155 \begin{cfa}
    156 for( typeof(end) elem = begin; elem < end; elem += 1 )
    157 for( typeof(end) elem = 0; elem < end; elem += 1 )
    158 \end{cfa}
    159 From these calls, letting @E@ be @typeof(end)@, the implied interface is:
    160 \begin{itemize}
    161 \item
    162     case-appropriate construction: one of @void ?{}( E &, typeof(begin) )@, or @void ?{}( E &, zero_t )@, depending on the specific loop form
    163 \item
    164     comparison, for termination testing: @int ?<?( const E &, const E & )@
    165 \item
    166     increment, for ``next item'': @E & ?+=?( E &, one_t )@
    167 \end{itemize}
    168 The shortened loop works well for using a numeric range to step through an array:
    169 \begin{cfa}
    170 for ( i; n ) total += a[i];
    171 \end{cfa}
    172 
    173 When used for array-stepping, the loop is acting like JavaScript's @for...in@ construct,
     143for( elem; begin ~ end ~ step )
     144\end{cfa}
     145Many derived forms of @begin ~ end@ exist, but are used for defining numeric ranges, so they are excluded from the linked-list discussion.
     146These three forms are rely on the iterative trait:
     147\begin{cfa}
     148forall( T ) trait Iterate {
     149        void ?{}( T & t, zero_t );
     150        int ?<?( T t1, T t2 );
     151        int ?<=?( T t1, T t2 );
     152        int ?>?( T t1, T t2 );
     153        int ?>=?( T t1, T t2 );
     154        T ?+=?( T & t1, T t2 );
     155        T ?+=?( T & t, one_t );
     156        T ?-=?( T & t1, T t2 );
     157        T ?-=?( T & t, one_t );
     158}
     159\end{cfa}
     160where @zero_t@ and @one_t@ are constructors for the constants 0 and 1.
     161The simple loops above are abbreviates for:
     162\begin{cfa}
     163for( typeof(end) elem = @0@; elem @<@ end; elem @+=@ @1@ )
     164for( typeof(begin) elem = begin; elem @<@ end; elem @+=@ @1@ )
     165for( typeof(begin) elem = @0@; elem @<@ end; elem @+=@ @step@ )
     166\end{cfa}
     167which use a subset of the trait operations.
     168The shortened loop works well for iterating a number of times or through an array.
     169\begin{cfa}
     170for ( 20 ) // 20 iterations
     171for ( i: 1 ~= 21 ~ 2 ) // odd numbers
     172for ( i; n ) total += a[i]; // subscripts
     173\end{cfa}
     174which is similar to other languages, like JavaScript.
    174175\begin{cfa}
    175176for ( i in a ) total += a[i];
    176177\end{cfa}
    177 albeit with different mechanisms for expressing the array's length.
    178 But the similarity is that the loop binds the declared identifier (@i@) to the array's \emph{indeces}, not its contained values.
    179 A linked list has only values, no keys.
    180 So, to seek iteration of a linked list via the existing loop syntax is to ask whether this syntax can also do double-duty for iterating values.
     178Albeit with different mechanisms for expressing the array's length.
     179It might be possible to take the \CC iterator:
     180\begin{c++}
     181for ( list<int>::iterator it=mylist.begin(); it != mylist.end(); ++it )
     182\end{c++}
     183and convert it to the \CFA form
     184\begin{cfa}
     185for ( it; begin() ~= end() )
     186\end{cfa}
     187by having a list operator @<=@ that just looks for equality, and @+=@ that moves to the next node, \etc.
     188
     189However, the list usage is contrived, because a list does use its data values for relational comparison, only links for equality comprison.
     190Hence, the focus of a list iterator's stopping condition is fundamentally different.
     191So, iteration of a linked list via the existing loop syntax is to ask whether this syntax can also do double-duty for iterating values.
    181192That is, to be an analog of JavaScript's @for..of@ syntax:
    182193\begin{cfa}
     
    193204Advantages of this change include being able to pass ranges to functions, for example, projecting a numerically regular subsequence of array entries, and being able to use the loop syntax to cover more collection types, such as looping over the keys of a hashtable.
    194205
    195 
    196 
    197 
    198 When iteratig an empty list, the question, ``Is there a further element?'' needs to be posed once, receiving the answer, ``no.''
     206When iterating an empty list, the question, ``Is there a further element?'' needs to be posed once, receiving the answer, ``no.''
    199207When iterating an $n$-item list, the same question gets $n$ ``yes'' answers (one for each element), plus one ``no'' answer, once there are no more elements; the question is posed $n+1$ times.
    200208
    201 When iteratig an empty list, the question, ``What is the value of the current element?'' is never posed, nor is the command, ``Move to the next element,'' issued.  When iterating an $n$-item list, each happens $n$ times.
     209When iterating an empty list, the question, ``What is the value of the current element?'' is never posed, nor is the command, ``Move to the next element,'' issued.  When iterating an $n$-item list, each happens $n$ times.
    202210
    203211So, asking about the existence of an element happens once more than retrieving an element's value and advancing the position.
     
    209217TODO: deal with spontaneous simultaneity, like a single-axis req, put into an array: which ``axis'' is @&req++@ navigating: array-adjacency vs link dereference.  It should sick according to how you got it in the first place: navigating dlist(req, req.pri) vs navigating array(req, 42).  (prob. future work)
    210218
     219
    211220\section{Implementation}
    212221
     
    214223
    215224\VRef[Figure]{fig:lst-impl-links} continues the running @req@ example, now showing the \CFA list library's internal representation.
     225The @dlink@ structure contains exactly two pointers: @next@ and @prev@, which are opaque to a user.
     226Even though the user-facing list model is ordered (linear), the CFA library implements all listing as circular.
     227This choice helps achieve uniform end treatment and TODO finish summarizing benefit.
     228A link pointer targets a neighbouring @dlink@ structure, rather than a neighbouring @req@.
     229(Recall, the running example has the user putting a @dlink@ within a @req@.)
    216230
    217231\begin{figure}
     
    224238\end{figure}
    225239
    226 The @dlink@ structure contains exactly two pointers: @next@ and @prev@.  This @dlink@ content is opaque to the user.
    227 
    228 Even though the user-facing list model is ordered (linear), the CFA library implements all listing as circular.
    229 This choice helps achieve uniform end treatment and TODO finish summarizing benefit.
    230 
    231 A link pointer targets a neighbouring @dlink@ structure, rather than a neighbouring @req@.
    232 (Recall, the running example has the user putting a @dlink@ within a @req@.)
    233 
    234 Link pointers are tagged according to whether the link is user-visible.
     240Link pointers are internally tagged according to whether the link is user-visible.
    235241Links among user-requested neighbours are left natural, with the tag bit not set.
    236242System-added links, which produce the circular implementation, have the tag bit set.
     
    239245In a headed list, the list head (@dlist(req)@) acts as an extra element in the implementation-level circularly-linked list.
    240246The content of a @dlist@ is a (private) @dlink@, with the @next@ pointer purposed for the first element, and the @prev@ pointer purposed for the last element.
    241 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@ strucures, situated inside of other things.
     247Since 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.
    242248The 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.
    243249
    244 In a headless list, the cicular backing list is only among @dlink@s within @req@s.  The tags are set on the links that a user cannot navigate.
     250In 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.
    245251
    246252No 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.
     
    251257\label{toc:lst:futwork}
    252258
     259The \CFA list examples elide the \lstinline{P9_EMBEDDED} annotations that (TODO: xref P9E future work) proposes to obviate.
     260Thus, these examples illustrate a to-be state, free of what is to be historic clutter.
     261The elided portions are immaterial to the discussion and the examples work with the annotations provided.
     262The \CFA test suite (TODO:cite?) includes equivalent demonstrations, with the annotations included.
     263\begin{cfa}
     264struct mary {
     265        float anotherdatum;
     266        inline dlink(mary);
     267};
     268struct fred {
     269        float adatum;
     270        inline struct mine { inline dlink(fred); };
     271        inline struct yours { inline dlink(fred); };
     272};
     273\end{cfa}
     274like in the thesis examples.  You have to say
     275\begin{cfa}
     276struct mary {
     277        float anotherdatum;
     278        inline dlink(mary);
     279};
     280P9_EMBEDDED(mary, dlink(mary))
     281struct fred {
     282        float adatum;
     283        inline struct mine { inline dlink(fred); };
     284        inline struct yours { inline dlink(fred); };
     285};
     286P9_EMBEDDED(fred, fred.mine)
     287P9_EMBEDDED(fred, fred.yours)
     288P9_EMBEDDED(fred.mine, dlink(fred))
     289P9_EMBEDDED(fred.yours, dlink(fred))
     290\end{cfa}
     291like in tests/list/dlist-insert-remove.
     292Future work should autogen those @P9_EMBEDDED@ declarations whenever it sees a plan-9 declaration.
     293The exact scheme chosen should harmonize with general user-defined conversions.
     294
     295Today's P9 scheme is:  mary gets a function `inner returning this as dlink(mary).
     296Fred gets four of them in a diamond.
     297They're defined so that `inner is transitive; i.e. fred has two further ambiguous overloads mapping fred to dlink(fred).
     298The scheme allows the dlist functions to give the assertion, "we work on any T that gives a `inner to dlink(T)."
     299
    253300
    254301TODO: deal with: A doubly linked list is being designed.
  • TabularUnified doc/theses/mike_brooks_MMath/programs/lst-features-intro.run.cfa

    r15eebd4 r4740281  
    2020struct req {
    2121        int pri, rqr;
    22         inline dlink(req);
     22        inline dlink(req);              // containment inheritance, fields hoisted into structure
    2323};
    2424
    2525dlist(req) reqs;
    2626
    27 req
    28         r1 = {1, 42},
    29         r2 = {2, 42};
     27req r1 = {1, 42}, r2 = {2, 42};
    3028
    3129insert_first(reqs, r2);
    3230insert_first(reqs, r1);
     31
     32
    3333
    3434
  • TabularUnified doc/theses/mike_brooks_MMath/programs/lst-features-multidir.run.cfa

    r15eebd4 r4740281  
    2828
    2929
     30
     31
    3032// need to spice this case; can't forward declare nested struct
    3133P9_EMBEDDED_INFUNC(req, req.by_pri)
     
    3335P9_EMBEDDED_INFUNC(req.by_pri, dlink(req))
    3436P9_EMBEDDED_INFUNC(req.by_rqr, dlink(req))
     37
     38
    3539
    3640
Note: See TracChangeset for help on using the changeset viewer.