Changeset b195498 for doc/theses/mike_brooks_MMath/list.tex
- Timestamp:
- Apr 24, 2025, 6:35:41 PM (5 months ago)
- Branches:
- master
- Children:
- 6b33e89, f85de47
- Parents:
- f632bd50
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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
Note:
See TracChangeset
for help on using the changeset viewer.