• GarbageCollection.cpp
  • #define CATCH_CONFIG_MAIN
    #include <catch.h>
    
    #include <Gorgon/Containers/GarbageCollection.h>
    #include <stdint.h>
    #include <vector>
    #include <algorithm>
    
    using namespace Gorgon::Containers;
    
    std::vector<intptr_t> deleted;
    
    class A {
    public:
    	A() : life(7) { As.Add(this); }
    
    	~A() { 
    		deleted.push_back(reinterpret_cast<intptr_t>(this));
    		As.Remove(this); 
    	}
    
    	void Kill() {
    		life--;
    	}
    
    	static void KillAll(unsigned times=1) {
    		for(auto &a : As) {
    			a.life-=times;
    		}
    	}
    
    	static int ACnt() { return As.GetCount(); }
    
    	int LifeLeft() const { return life;  }
    
    private:
    	int life;
    	static Collection<A> As;
    };
    
    bool ShouldBeCollected(const A &a) {
    	return a.LifeLeft()<=0;
    }
    
    Collection<A> A::As;
    
    TEST_CASE("Garbage collection", "[GarbageCollector]") {
    
    	GarbageCollection<A> gc;
    	gc.AddNew();
    	gc.AddNew();
    
    	REQUIRE(A::ACnt() == 2);
    
    	A::KillAll(7);
    
    	REQUIRE(A::ACnt() == 2);
    
    	gc.Collect();
    
    	REQUIRE(A::ACnt() == 0);
        
        deleted.clear();
    
    	auto first=reinterpret_cast<intptr_t>(&gc.AddNew());
    
    	A::KillAll();
    
    	auto second=reinterpret_cast<intptr_t>(&gc.AddNew());
    
    	A::KillAll(6);
    
    	gc.Collect();
    
    	REQUIRE( std::find(deleted.begin(), deleted.end(), first)!=deleted.end() );
    	REQUIRE(std::find(deleted.begin(), deleted.end(), second)==deleted.end());
    
    	A::KillAll(1);
    	gc.Collect();
    
    	REQUIRE(A::ACnt() == 0);
    }