TODO: Should have a flag to tell the garbage collector to automatically determine how many iterations are needed It should then gather statistics such as how many objects has been created since last run, and how many objects are destroyed per iteration, and how many objects are detected as cyclic garbage per iteration. It should try to reach a stable number of objects, i.e. so that on average the
| 167 | // of iterations of detections that must be executed per cycle while still identifying the cyclic garbage |
| 168 | // These variables should also be available for inspection through the gcstatistics. |
| 169 | int asCGarbageCollector::GarbageCollect(asDWORD flags, asUINT iterations) |
| 170 | { |
| 171 | // If the GC is already processing in another thread, then don't enter here again |
| 172 | if( TRYENTERCRITICALSECTION(gcCollecting) ) |
| 173 | { |
| 174 | // If the GC is already processing in this thread, then don't enter here again |
| 175 | if( isProcessing ) |
| 176 | { |
| 177 | LEAVECRITICALSECTION(gcCollecting); |
| 178 | return 1; |
| 179 | } |
| 180 | |
| 181 | isProcessing = true; |
| 182 | |
| 183 | bool doDetect = (flags & asGC_DETECT_GARBAGE) || !(flags & asGC_DESTROY_GARBAGE); |
| 184 | bool doDestroy = (flags & asGC_DESTROY_GARBAGE) || !(flags & asGC_DETECT_GARBAGE); |
| 185 | |
| 186 | if( flags & asGC_FULL_CYCLE ) |
| 187 | { |
| 188 | // Reset the state |
| 189 | if( doDetect ) |
| 190 | { |
| 191 | // Move all new objects to the old list, so we guarantee that all is detected |
| 192 | MoveAllObjectsToOldList(); |
| 193 | detectState = clearCounters_init; |
| 194 | } |
| 195 | if( doDestroy ) |
| 196 | { |
| 197 | destroyNewState = destroyGarbage_init; |
| 198 | destroyOldState = destroyGarbage_init; |
| 199 | } |
| 200 | |
| 201 | // The full cycle only works with the objects in the old list so that the |
| 202 | // set of objects scanned for garbage is fixed even if new objects are added |
| 203 | // by other threads in parallel. |
| 204 | unsigned int count = (unsigned int)(gcOldObjects.GetLength()); |
| 205 | for(;;) |
| 206 | { |
| 207 | // Detect all garbage with cyclic references |
| 208 | if( doDetect ) |
| 209 | while( IdentifyGarbageWithCyclicRefs() == 1 ) {} |
| 210 | |
| 211 | // Now destroy all known garbage |
| 212 | if( doDestroy ) |
| 213 | { |
| 214 | if( !doDetect ) |
| 215 | while( DestroyNewGarbage() == 1 ) {} |
| 216 | while( DestroyOldGarbage() == 1 ) {} |
| 217 | } |
| 218 | |
| 219 | // Run another iteration if any garbage was destroyed |
| 220 | if( count != (unsigned int)(gcOldObjects.GetLength()) ) |
| 221 | count = (unsigned int)(gcOldObjects.GetLength()); |
| 222 | else |
| 223 | break; |
| 224 | } |
| 225 | |
| 226 | isProcessing = false; |
no test coverage detected