- Timestamp:
- Apr 18, 2025, 8:43:09 AM (5 months ago)
- Branches:
- master
- Children:
- e86735ba
- Parents:
- 4740281
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/collections/list.hfa
r4740281 r9dd1dd6 10 10 // Created On : Wed Apr 22 18:00:00 2020 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 2 11:32:26 202313 // Update Count : 212 // Last Modified On : Thu Apr 17 07:28:47 2025 13 // Update Count : 3 14 14 // 15 15 … … 20 20 forall( Decorator &, T & ) 21 21 struct tytagref { 22 22 inline T &; 23 23 }; 24 24 25 25 forall( tOuter &, tMid &, tInner & ) 26 26 trait embedded { 27 27 tytagref( tMid, tInner ) ?`inner( tOuter & ); 28 28 }; 29 29 … … 37 37 // 38 38 // struct foo { 39 // 40 // 39 // int a, b, c; 40 // inline (bar); 41 41 // }; 42 42 // P9_EMBEDDED( foo, bar ) … … 44 44 45 45 // usual version, for structs that are top-level declarations 46 #define P9_EMBEDDED( 46 #define P9_EMBEDDED( derived, immedBase ) P9_EMBEDDED_DECL_( derived, immedBase, static ) P9_EMBEDDED_BDY_( immedBase ) 47 47 48 48 // special version, for structs that are declared in functions 49 #define P9_EMBEDDED_INFUNC( derived, immedBase ) P9_EMBEDDED_DECL_( derived, immedBase, 49 #define P9_EMBEDDED_INFUNC( derived, immedBase ) P9_EMBEDDED_DECL_( derived, immedBase, ) P9_EMBEDDED_BDY_( immedBase ) 50 50 51 51 // forward declarations of both the above; generally not needed 52 52 // may help you control where the P9_EMBEEDED cruft goes, in case "right after the stuct" isn't where you want it 53 #define P9_EMBEDDED_FWD( derived, immedBase )P9_EMBEDDED_DECL_( derived, immedBase, static ) ;54 #define P9_EMBEDDED_FWD_INFUNC( derived, immedBase ) auto P9_EMBEDDED_DECL_( derived, immedBase, 53 #define P9_EMBEDDED_FWD( derived, immedBase ) P9_EMBEDDED_DECL_( derived, immedBase, static ) ; 54 #define P9_EMBEDDED_FWD_INFUNC( derived, immedBase ) auto P9_EMBEDDED_DECL_( derived, immedBase, ) ; 55 55 56 56 // private helpers 57 57 #define P9_EMBEDDED_DECL_( derived, immedBase, STORAGE ) \ 58 59 60 58 forall( Tbase &, TdiscardPath & | { tytagref( TdiscardPath, Tbase ) ?`inner( immedBase & ); } ) \ 59 STORAGE inline tytagref(immedBase, Tbase) ?`inner( derived & this ) 60 61 61 #define P9_EMBEDDED_BDY_( immedBase ) { \ 62 63 64 65 66 62 immedBase & ib = this; \ 63 Tbase & b = ib`inner; \ 64 tytagref(immedBase, Tbase) result = { b }; \ 65 return result; \ 66 } 67 67 68 68 #define EMBEDDED_VIA( OUTER, MID, INNER ) \ … … 88 88 89 89 #if defined( __x86_64 ) 90 91 92 93 94 90 // Preferred case: tag in the most-significant bit. Dereference 91 // has been shown to segfault consistently. Maintenance should 92 // list more architectures as "ok" here, to let them use the 93 // preferred case, when valid. 94 #define ORIGIN_TAG_BITNO ( 8 * sizeof( size_t ) - 1 ) 95 95 #else 96 97 98 99 100 96 // Fallback case: tag in the least-significant bit. Dereference 97 // will often give an alignment error, but may not, e.g. if 98 // accessing a char-typed member. 32-bit x86 uses the most- 99 // significant bit for real room on the heap. 100 #define ORIGIN_TAG_BITNO 0 101 101 #endif 102 102 #define ORIGIN_TAG_MASK (((size_t)1) << ORIGIN_TAG_BITNO) … … 109 109 forall( tE & ) { 110 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 111 struct dlink{ 112 tE *next; 113 tE *prev; 114 }; 115 116 static inline void ?{}( dlink(tE) & this ) { 117 this.next = 0p; 118 this.prev = 0p; 119 } 120 121 forall( tLinks & = dlink(tE) ) 122 struct dlist { 123 inline dlink(tE); 124 }; 125 126 forall( tLinks & | embedded( tE, tLinks, dlink(tE) ) ) { 127 static inline tE * $get_list_origin_addr( dlist(tE, tLinks) & lst ) { 128 dlink(tE) & link_from_null = ( * (tE *) 0p )`inner; 129 ptrdiff_t link_offset = (ptrdiff_t) & link_from_null; 130 size_t origin_addr = ((size_t) & lst) - link_offset; 131 size_t preResult = ORIGIN_TAG_SET( origin_addr ); 132 return (tE *)preResult; 133 } 134 135 static inline void ?{}( dlist(tE, tLinks) & this ) { 136 tE * listOrigin = $get_list_origin_addr( this ); 137 ( ( dlink(tE) & ) this ){ listOrigin, listOrigin } ; 138 } 139 } 140 140 141 141 } … … 147 147 verify (&list_pos != 0p); 148 148 verify (&to_insert != 0p); 149 149 dlink(tE) & linkToInsert = to_insert`inner; 150 150 verify(linkToInsert.prev == 0p); 151 151 verify(linkToInsert.next == 0p); 152 153 154 155 156 152 tE & list_pos_elem = * (tE *) ORIGIN_TAG_CLEAR( (size_t) & list_pos ); 153 dlink(tE) & list_pos_links = list_pos_elem`inner; 154 asm( "" : : : "memory" ); 155 tE & after_raw = * list_pos_links.next; 156 tE & after_elem = * (tE *) ORIGIN_TAG_CLEAR( (size_t) & after_raw ); 157 157 linkToInsert.prev = & list_pos; 158 158 linkToInsert.next = & after_raw; 159 160 159 dlink(tE) & afterLinks = after_elem`inner; 160 afterLinks.prev = &to_insert; 161 161 list_pos_links.next = &to_insert; 162 162 asm( "" : : : "memory" ); 163 163 } 164 164 … … 166 166 verify (&list_pos != 0p); 167 167 verify (&to_insert != 0p); 168 168 dlink(tE) & linkToInsert = to_insert`inner; 169 169 verify(linkToInsert.next == 0p); 170 170 verify(linkToInsert.prev == 0p); 171 172 173 174 175 171 tE & list_pos_elem = * (tE *) ORIGIN_TAG_CLEAR( (size_t) & list_pos ); 172 dlink(tE) & list_pos_links = list_pos_elem`inner; 173 asm( "" : : : "memory" ); 174 tE & before_raw = * (list_pos_links).prev; 175 tE & before_elem = * (tE *) ORIGIN_TAG_CLEAR( (size_t) & before_raw ); 176 176 linkToInsert.next = & list_pos; 177 177 linkToInsert.prev = & before_raw; 178 179 178 dlink(tE) & beforeLinks = before_elem`inner; 179 beforeLinks.next = &to_insert; 180 180 (list_pos_links).prev = &to_insert; 181 181 asm( "" : : : "memory" ); 182 182 } 183 183 184 184 static inline tE & remove(tE & list_pos) { 185 185 verify (&list_pos != 0p); 186 187 188 189 190 191 192 193 194 195 196 186 verify( ! ORIGIN_TAG_QUERY((size_t) & list_pos) ); 187 dlink(tE) & list_pos_links = list_pos`inner; 188 tE & before_raw = * list_pos_links.prev; 189 tE & before_elem = * (tE *) ORIGIN_TAG_CLEAR( (size_t) & before_raw ); 190 dlink(tE) & before_links = before_elem`inner; 191 tE & after_raw = * list_pos_links.next; 192 tE & after_elem = * (tE *) ORIGIN_TAG_CLEAR( (size_t) & after_raw ); 193 dlink(tE) & after_links = after_elem`inner; 194 before_links.next = &after_raw; 195 after_links.prev = &before_raw; 196 asm( "" : : : "memory" ); 197 197 list_pos_links.prev = 0p; 198 198 list_pos_links.next = 0p; 199 200 201 } 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 199 asm( "" : : : "memory" ); 200 return list_pos; 201 } 202 203 static inline tE & ?`first( dlist(tE, tLinks) &lst ) { 204 tE * firstPtr = lst.next; 205 if (ORIGIN_TAG_QUERY((size_t)firstPtr)) firstPtr = 0p; 206 return *firstPtr; 207 } 208 static inline tE & ?`last ( dlist(tE, tLinks) &lst ) { 209 tE * lastPtr = lst.prev; 210 if (ORIGIN_TAG_QUERY((size_t)lastPtr)) lastPtr = 0p; 211 return *lastPtr; 212 } 213 214 static inline bool ?`isEmpty( dlist(tE, tLinks) & lst ) { 215 tE * firstPtr = lst.next; 216 if (ORIGIN_TAG_QUERY((size_t)firstPtr)) firstPtr = 0p; 217 return firstPtr == 0p; 218 } 219 220 static inline bool ?`isListed( tE & e ) { 221 221 verify (&e != 0p); 222 222 dlink(tE) & e_links = e`inner; 223 223 return (e_links.prev != 0p) || (e_links.next != 0p); 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 224 } 225 226 static inline tE & ?`elems( dlist(tE, tLinks) & lst ) { 227 tE * origin = $get_list_origin_addr( lst ); 228 return *origin; 229 } 230 231 static inline bool ?`moveNext( tE && refx ) { 232 tE && ref_inner = refx; 233 tE & oldReferent = * (tE*) ORIGIN_TAG_CLEAR( (size_t) & ref_inner ); 234 &ref_inner = oldReferent`inner.next; 235 return &ref_inner != 0p && 236 ! ORIGIN_TAG_QUERY( (size_t) & ref_inner ); 237 } 238 239 static inline bool ?`movePrev( tE && refx ) { 240 tE && ref_inner = refx; 241 tE & oldReferent = * (tE*) ORIGIN_TAG_CLEAR( (size_t) & ref_inner ); 242 &ref_inner = oldReferent`inner.prev; 243 return &ref_inner != 0p && 244 ! ORIGIN_TAG_QUERY( (size_t) & ref_inner ); 245 } 246 247 static inline bool ?`hasNext( tE & e ) { 248 return e`moveNext; 249 } 250 251 static inline bool ?`hasPrev( tE & e ) { 252 return e`movePrev; 253 } 254 255 static inline tE & ?`next( tE & e ) { 256 if( e`moveNext ) return e; 257 return * 0p; 258 } 259 260 static inline tE & ?`prev( tE & e ) { 261 if( e`movePrev ) return e; 262 return * 0p; 263 } 264 265 static inline void insert_first( dlist(tE, tLinks) &lst, tE & e ) { 266 insert_after(lst`elems, e); 267 } 268 269 static inline void insert_last( dlist(tE, tLinks) &lst, tE & e ) { 270 insert_before(lst`elems, e); 271 } 272 273 static inline tE & try_pop_front( dlist(tE, tLinks) &lst ) { 274 tE & first_inlist = lst`first; 275 tE & first_item = first_inlist; 276 if (&first_item) remove(first_inlist); 277 return first_item; 278 } 279 280 static inline tE & try_pop_back( dlist(tE, tLinks) &lst ) { 281 tE & last_inlist = lst`last; 282 tE & last_item = last_inlist; 283 if (&last_item) remove(last_inlist); 284 return last_item; 285 } 286 286 287 287 288 288 #if !defined(NDEBUG) && (defined(__CFA_DEBUG__) || defined(__CFA_VERIFY__)) 289 289 static bool $validate_fwd( dlist(tE, tLinks) & this ) { 290 291 292 293 294 295 296 297 298 299 300 301 302 290 if ( ! & this`first ) return ( (& this`last) == 0p); 291 292 tE & lagElem = *0p; 293 294 while ( tE & it = this`elems; it`moveNext ) { 295 if (& lagElem == 0p && &it != & this`first ) return false; 296 & lagElem = & it; 297 } 298 299 if (& lagElem != & this`last) return false; 300 301 // TODO: verify that it is back at this`elems; 302 return true; 303 303 } 304 304 static bool $validate_rev( dlist(tE, tLinks) & this ) { 305 306 307 308 309 310 311 312 313 314 315 316 317 305 if ( ! & this`last ) return ( (& this`first) == 0p); 306 307 tE & lagElem = *0p; 308 309 while ( tE & it = this`elems; it`movePrev ) { 310 if (& lagElem == 0p && &it != & this`last ) return false; 311 & lagElem = & it; 312 } 313 314 if (& lagElem != & this`first) return false; 315 316 // TODO: verify that it is back at this`elems; 317 return true; 318 318 } 319 319 static inline bool validate( dlist(tE, tLinks) & this ) {
Note:
See TracChangeset
for help on using the changeset viewer.