| 1 | #include <string.hfa>
 | 
|---|
| 2 | #include <string_sharectx.hfa>
 | 
|---|
| 3 | #include <string_res.hfa>
 | 
|---|
| 4 | 
 | 
|---|
| 5 | // In these tests, shared heaps are never remotely full and string sizes are tiny.
 | 
|---|
| 6 | // So here, the SUT should put a yes-sharing string in a heap with lots of spare room.
 | 
|---|
| 7 | // The SUT should always keep a no-sharing string's buffer 1x--2x the string's size.
 | 
|---|
| 8 | // This check uses 3x as a heuristic split between those cases.
 | 
|---|
| 9 | void assertSpareRoomInHeap( string & s, bool expectOversized ) {
 | 
|---|
| 10 |     double bytesInHeap = DEBUG_string_bytes_in_heap(s.inner->Handle.ulink);
 | 
|---|
| 11 |     double bytesUsed =  s.inner->Handle.lnth;
 | 
|---|
| 12 |     double overhead = bytesInHeap / bytesUsed;
 | 
|---|
| 13 |     assert (overhead >= 1);
 | 
|---|
| 14 |     if ( expectOversized )
 | 
|---|
| 15 |         assert( overhead >= 3.0 );
 | 
|---|
| 16 |     else 
 | 
|---|
| 17 |         assert( overhead < 3.0 );
 | 
|---|
| 18 | }
 | 
|---|
| 19 | 
 | 
|---|
| 20 | void baseline() {
 | 
|---|
| 21 |     string x = "hi";
 | 
|---|
| 22 |     assertSpareRoomInHeap( x, true );
 | 
|---|
| 23 | 
 | 
|---|
| 24 |     string y = x; // construct y in same context, no write yet => no copy yet
 | 
|---|
| 25 |     assertSpareRoomInHeap( y, true );
 | 
|---|
| 26 |     assert( y.inner->Handle.s == x.inner->Handle.s);
 | 
|---|
| 27 |     sout | y; // hi
 | 
|---|
| 28 | 
 | 
|---|
| 29 |     x = "bye";
 | 
|---|
| 30 |     assertSpareRoomInHeap( x, true );
 | 
|---|
| 31 |     y = x; // y in same context, no write yet => no copy yet
 | 
|---|
| 32 |     assertSpareRoomInHeap( y, true );
 | 
|---|
| 33 |     assert( y.inner->Handle.s == x.inner->Handle.s);
 | 
|---|
| 34 |     sout | y; // bye
 | 
|---|
| 35 | }
 | 
|---|
| 36 | 
 | 
|---|
| 37 | void eagerCopy() {
 | 
|---|
| 38 |     string x = "hi";
 | 
|---|
| 39 |     assertSpareRoomInHeap( x, true );
 | 
|---|
| 40 |     string_sharectx c = { NEW_SHARING };
 | 
|---|
| 41 | 
 | 
|---|
| 42 |     string y = x; // construct y in different context => eager copy
 | 
|---|
| 43 |     assertSpareRoomInHeap( y, true );
 | 
|---|
| 44 |     assert( y.inner->Handle.s != x.inner->Handle.s);
 | 
|---|
| 45 |     sout | y; // hi
 | 
|---|
| 46 | 
 | 
|---|
| 47 |     x = "bye";
 | 
|---|
| 48 |     assertSpareRoomInHeap( x, true );
 | 
|---|
| 49 |     y = x; // y was already in different context => eager copy
 | 
|---|
| 50 |     assertSpareRoomInHeap( y, true );
 | 
|---|
| 51 |     assert( y.inner->Handle.s != x.inner->Handle.s);
 | 
|---|
| 52 |     sout | y; // bye
 | 
|---|
| 53 | }
 | 
|---|
| 54 | 
 | 
|---|
| 55 | void soloAlloc() {
 | 
|---|
| 56 |     string x = "hi";
 | 
|---|
| 57 |     assertSpareRoomInHeap( x, true );
 | 
|---|
| 58 |     string_sharectx c = { NO_SHARING };
 | 
|---|
| 59 |     
 | 
|---|
| 60 |     string y = x; // y allocates into private pad, implying eager copy
 | 
|---|
| 61 |     assertSpareRoomInHeap( y, false );
 | 
|---|
| 62 |     assert( y.inner->Handle.s != x.inner->Handle.s);
 | 
|---|
| 63 |     sout | y; // hi
 | 
|---|
| 64 | 
 | 
|---|
| 65 |     x = "bye";
 | 
|---|
| 66 |     assertSpareRoomInHeap( x, true );
 | 
|---|
| 67 |     y = x; // into private y => eager copy
 | 
|---|
| 68 |     assertSpareRoomInHeap( y, false );
 | 
|---|
| 69 |     assert( y.inner->Handle.s != x.inner->Handle.s);
 | 
|---|
| 70 |     sout | y; // bye
 | 
|---|
| 71 | }
 | 
|---|
| 72 | 
 | 
|---|
| 73 | 
 | 
|---|
| 74 | int main() {
 | 
|---|
| 75 |     baseline();
 | 
|---|
| 76 |     eagerCopy();
 | 
|---|
| 77 |     soloAlloc();
 | 
|---|
| 78 |     printf("done\n");
 | 
|---|
| 79 | }
 | 
|---|