Changeset 4b3b352
- Timestamp:
- Oct 7, 2021, 2:13:46 PM (4 years ago)
- Branches:
- ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum
- Children:
- 804bf677
- Parents:
- 0f781fb8
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified libcfa/src/containers/string.cfa ¶
r0f781fb8 r4b3b352 92 92 } 93 93 94 string ?=?(string & this, string other) {94 string & ?=?(string & this, string & other) { //// <---- straw man change 95 95 (*this.inner) = (*other.inner); 96 96 return this; -
TabularUnified libcfa/src/containers/string.hfa ¶
r0f781fb8 r4b3b352 41 41 void ?=?(string &s, const string &other); 42 42 void ?=?(string &s, char other); 43 string ?=?(string &s, string other); // string tolerates memcpys; still saw calls to autogen44 43 string & ?=?(string &s, string &other); // surprising ret seems to help avoid calls to autogen 44 //string ?=?( string &, string ) = void; 45 45 void ^?{}(string &s); 46 46 -
TabularUnified libcfa/src/containers/string_res.cfa ¶
r0f781fb8 r4b3b352 223 223 } 224 224 225 // Constructor from a raw buffer and size 226 void ?{}(string_res &s, const char* rhs, size_t rhslnth) with(s) { 225 static inline void eagerCopyCtorHelper(string_res &s, const char* rhs, size_t rhslnth) with(s) { 227 226 assert( ambient_string_sharectx->activeHeap && "Need to implement private contexts" ); 228 227 (Handle){ * ambient_string_sharectx->activeHeap }; … … 236 235 } 237 236 237 // Constructor from a raw buffer and size 238 void ?{}(string_res &s, const char* rhs, size_t rhslnth) with(s) { 239 eagerCopyCtorHelper(s, rhs, rhslnth); 240 } 241 238 242 // String literal constructor 239 243 void ?{}(string_res &s, const char* rhs) { … … 245 249 246 250 assert( ambient_string_sharectx->activeHeap && "Need to implement private contexts" ); 247 assert( s2.Handle.ulink == ambient_string_sharectx->activeHeap && "need to implement context crossing");248 251 249 252 verify( start <= end && end <= s2.Handle.lnth ); 250 253 251 (s.Handle){}; 252 s.Handle.s = s2.Handle.s + start; 253 s.Handle.lnth = end - start; 254 s.Handle.ulink = ambient_string_sharectx->activeHeap; 255 AddThisAfter(s.Handle, s2.Handle ); // insert this handle after rhs handle 256 // ^ bug? skip others at early point in string 254 if (s2.Handle.ulink == ambient_string_sharectx->activeHeap) { 255 // same heap: allow overlap 256 (s.Handle){}; 257 s.Handle.s = s2.Handle.s + start; 258 s.Handle.lnth = end - start; 259 s.Handle.ulink = ambient_string_sharectx->activeHeap; 260 AddThisAfter(s.Handle, s2.Handle ); // insert this handle after rhs handle 261 // ^ bug? skip others at early point in string 257 262 258 if (mode == COPY_VALUE) { 259 // make s alone in its shareEditSet 260 s.shareEditSet_prev = &s; 261 s.shareEditSet_next = &s; 263 if (mode == COPY_VALUE) { 264 // make s alone in its shareEditSet 265 s.shareEditSet_prev = &s; 266 s.shareEditSet_next = &s; 267 } else { 268 verify( mode == SHARE_EDITS ); 269 270 // s2 is logically const but not implementation const 271 string_res & s2mod = (string_res &) s2; 272 273 // insert s after s2 on shareEditSet 274 s.shareEditSet_next = s2mod.shareEditSet_next; 275 s.shareEditSet_prev = &s2mod; 276 s.shareEditSet_next->shareEditSet_prev = &s; 277 s.shareEditSet_prev->shareEditSet_next = &s; 278 } 262 279 } else { 263 verify( mode == SHARE_EDITS ); 264 265 // s2 is logically const but not implementation const 266 string_res & s2mod = (string_res &) s2; 267 268 // insert s after s2 on shareEditSet 269 s.shareEditSet_next = s2mod.shareEditSet_next; 270 s.shareEditSet_prev = &s2mod; 271 s.shareEditSet_next->shareEditSet_prev = &s; 272 s.shareEditSet_prev->shareEditSet_next = &s; 273 } 274 } 275 276 void assign(string_res &this, const char* buffer, size_t bsize) { 277 278 // traverse the incumbent share-edit set (SES) to recover the range of a base string to which `this` belongs 279 string_res * shareEditSetStartPeer = & this; 280 string_res * shareEditSetEndPeer = & this; 281 for (string_res * editPeer = this.shareEditSet_next; editPeer != &this; editPeer = editPeer->shareEditSet_next) { 282 if ( editPeer->Handle.s < shareEditSetStartPeer->Handle.s ) { 283 shareEditSetStartPeer = editPeer; 284 } 285 if ( shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth < editPeer->Handle.s + editPeer->Handle.lnth) { 286 shareEditSetEndPeer = editPeer; 287 } 288 } 289 290 // full string is from start of shareEditSetStartPeer thru end of shareEditSetEndPeer 291 // `this` occurs in the middle of it, to be replaced 292 // build up the new text in `pasting` 293 294 string_res pasting = { 295 shareEditSetStartPeer->Handle.s, // start of SES 296 this.Handle.s - shareEditSetStartPeer->Handle.s }; // length of SES, before this 297 append( pasting, 298 buffer, // start of replacement for this 299 bsize ); // length of replacement for this 300 append( pasting, 301 this.Handle.s + this.Handle.lnth, // start of SES after this 302 shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - 303 (this.Handle.s + this.Handle.lnth) ); // length of SES, after this 304 305 // The above string building can trigger compaction. 306 // The reference points (that are arguments of the string building) may move during that building. 307 // From this point on, they are stable. 308 // So now, capture their values for use in the overlap cases, below. 309 // Do not factor these definitions with the arguments used above. 280 // crossing heaps: eager copy 281 assert( mode == COPY_VALUE && "need to solidify context-crossing rules for requesting shared edits"); 282 eagerCopyCtorHelper(s, s2.Handle.s + start, end - start); 283 verify(s.shareEditSet_prev == &s); 284 verify(s.shareEditSet_next == &s); 285 } 286 } 287 288 static void assignEditSet(string_res & this, string_res * shareEditSetStartPeer, string_res * shareEditSetEndPeer, 289 char * resultSesStart, 290 size_t resultSesLnth, 291 HandleNode * resultPadPosition, size_t bsize ) { 310 292 311 293 char * beforeBegin = shareEditSetStartPeer->Handle.s; … … 317 299 size_t oldLnth = this.Handle.lnth; 318 300 319 this.Handle.s = pasting.Handle.s+ beforeLen;301 this.Handle.s = resultSesStart + beforeLen; 320 302 this.Handle.lnth = bsize; 321 MoveThisAfter( this.Handle, pasting.Handle);303 MoveThisAfter( this.Handle, *resultPadPosition ); 322 304 323 305 // adjust all substring string and handle locations, and check if any substring strings are outside the new base string 324 char *limit = pasting.Handle.s + pasting.Handle.lnth;306 char *limit = resultSesStart + resultSesLnth; 325 307 for (string_res * p = this.shareEditSet_next; p != &this; p = p->shareEditSet_next) { 326 308 verify (p->Handle.s >= beforeBegin); … … 353 335 // take start as start-anchored 354 336 size_t startOffsetFromStart = p->Handle.s - beforeBegin; 355 p->Handle.s = pasting.Handle.s+ startOffsetFromStart;337 p->Handle.s = resultSesStart + startOffsetFromStart; 356 338 } else { 357 339 verify ( p->Handle.s < afterBegin ); … … 371 353 } 372 354 } 373 MoveThisAfter( p->Handle, pasting.Handle ); // move substring handle to maintain sorted order by string position 374 } 355 MoveThisAfter( p->Handle, *resultPadPosition ); // move substring handle to maintain sorted order by string position 356 } 357 } 358 359 static void assign_(string_res &this, const char* buffer, size_t bsize, const string_res & valSrc) { 360 361 // traverse the incumbent share-edit set (SES) to recover the range of a base string to which `this` belongs 362 string_res * shareEditSetStartPeer = & this; 363 string_res * shareEditSetEndPeer = & this; 364 for (string_res * editPeer = this.shareEditSet_next; editPeer != &this; editPeer = editPeer->shareEditSet_next) { 365 if ( editPeer->Handle.s < shareEditSetStartPeer->Handle.s ) { 366 shareEditSetStartPeer = editPeer; 367 } 368 if ( shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth < editPeer->Handle.s + editPeer->Handle.lnth) { 369 shareEditSetEndPeer = editPeer; 370 } 371 } 372 373 verify( shareEditSetEndPeer->Handle.s >= shareEditSetStartPeer->Handle.s ); 374 size_t editSetLength = shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - shareEditSetStartPeer->Handle.s; 375 verify( editSetLength >= this.Handle.lnth ); 376 377 378 if ( this.Handle.lnth == editSetLength // the entire run of the share-edit set is being overwritten: SES's result will only use characters from the source string 379 && & valSrc // sourcing from a managed string 380 && valSrc.Handle.ulink == this.Handle.ulink ) { // sourcing from same heap 381 382 assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer, 383 valSrc.Handle.s, 384 valSrc.Handle.lnth, 385 &((string_res&)valSrc).Handle, bsize); 386 387 } else { 388 389 // full string is from start of shareEditSetStartPeer thru end of shareEditSetEndPeer 390 // `this` occurs in the middle of it, to be replaced 391 // build up the new text in `pasting` 392 393 // super private string ctor: ignore ambient context 394 void ?{}( string_res &s, VbyteHeap & heap, const char* rhs, size_t rhslnth ) with(s) { 395 (Handle){ heap }; 396 Handle.s = VbyteAlloc(*Handle.ulink, rhslnth); 397 Handle.lnth = rhslnth; 398 for ( int i = 0; i < rhslnth; i += 1 ) { // copy characters 399 Handle.s[i] = rhs[i]; 400 } // for 401 s.shareEditSet_prev = &s; 402 s.shareEditSet_next = &s; 403 } 404 405 // we are only overwriting a proper substring of some string: need to mash characters from old and new together 406 // OR we are importing characters: need to copy eagerly 407 string_res pasting = { 408 * this.Handle.ulink, // maintain same heap, regardless of context 409 shareEditSetStartPeer->Handle.s, // start of SES 410 this.Handle.s - shareEditSetStartPeer->Handle.s }; // length of SES, before this 411 append( pasting, 412 buffer, // start of replacement for this 413 bsize ); // length of replacement for this 414 append( pasting, 415 this.Handle.s + this.Handle.lnth, // start of SES after this 416 shareEditSetEndPeer->Handle.s + shareEditSetEndPeer->Handle.lnth - 417 (this.Handle.s + this.Handle.lnth) ); // length of SES, after this 418 419 // The above string building can trigger compaction. 420 // The reference points (that are arguments of the string building) may move during that building. 421 // From this point on, they are stable. 422 423 assignEditSet(this, shareEditSetStartPeer, shareEditSetEndPeer, 424 pasting.Handle.s, 425 pasting.Handle.lnth, 426 &pasting.Handle, bsize); 427 } 428 429 // So now, capture their values for use in the overlap cases, below. 430 // Do not factor these definitions with the arguments used in string building above. 431 432 } 433 434 void assign(string_res &this, const char* buffer, size_t bsize) { 435 assign_(this, buffer, bsize, *0p); 375 436 } 376 437 … … 385 446 // Copy assignment operator 386 447 void ?=?(string_res & this, const string_res & rhs) with( this ) { 387 assign (this, rhs.Handle.s, rhs.Handle.lnth);448 assign_(this, rhs.Handle.s, rhs.Handle.lnth, rhs); 388 449 } 389 450 -
TabularUnified tests/collections/.expect/string-ctx-manage.txt ¶
r0f781fb8 r4b3b352 1 hi 2 bye 3 hi 4 bye 1 5 done -
TabularUnified tests/collections/string-ctx-manage.cfa ¶
r0f781fb8 r4b3b352 1 1 #include <string.hfa> 2 2 #include <string_sharectx.hfa> 3 #include <string_res.hfa> 3 4 4 // The functionality for these tests isn't written yet. 5 // But its interface compiles and the cases it drives are detected. 5 void baseline() { 6 string x = "hi"; 6 7 7 void failEagerCopy() { 8 string y = x; // construct y in same context, no write yet => no copy yet 9 assert( y.inner->Handle.s == x.inner->Handle.s); 10 sout | y; // hi 11 12 x = "bye"; 13 y = x; // y in same context, no write yet => no copy yet 14 assert( y.inner->Handle.s == x.inner->Handle.s); 15 sout | y; // bye 16 } 17 18 void eagerCopy() { 8 19 string x = "hi"; 9 string_sharectx c = { N O_SHARING };20 string_sharectx c = { NEW_SHARING }; 10 21 11 // want: implied forced eager copy 12 // got: assertion failure, "need to implement context crossing" 13 string y = x; 22 string y = x; // construct y in different context => eager copy 23 assert( y.inner->Handle.s != x.inner->Handle.s); 24 sout | y; // hi 25 26 x = "bye"; //.... Bookmark 9/30 shallow: surprisingly this step failed 27 y = x; // y was already in different context => eager copy 28 assert( y.inner->Handle.s != x.inner->Handle.s); 29 sout | y; // bye 14 30 } 15 31 … … 26 42 27 43 int main() { 44 baseline(); 45 eagerCopy(); 28 46 if (showFail) { 29 failEagerCopy();30 47 failSoloAlloc(); 31 48 }
Note: See TracChangeset
for help on using the changeset viewer.