void ObservableTest::testAsyncGarbagCollector() { BOOST_TEST_MESSAGE("Testing observer pattern with an asynchronous " "garbage collector (JVM/.NET use case)..."); // This test core dumps if used with the ordinary implementation // of the observer pattern (comparable situation // in JVM or .NET eco systems). const ext::shared_ptr<SimpleQuote> quote(new SimpleQuote(-1.0)); GarbageCollector gc; boost::thread workerThread(&GarbageCollector::run, &gc); for (Size i=0; i < 10000; ++i) { const ext::shared_ptr<MTUpdateCounter> observer(new MTUpdateCounter); observer->registerWith(quote); gc.addObj(observer); for (Size j=0; j < 10; ++j) quote->setValue(Real(j)); } gc.terminate(); workerThread.join(); if (MTUpdateCounter::instanceCounter() != 0) { BOOST_FAIL("garbage collection does not work."); } }
TEST_F(GarbageCollectorTest, Schedule) { GarbageCollector gc; // Make some temporary files to gc. const string& file1 = "file1"; const string& file2 = "file2"; const string& file3 = "file3"; ASSERT_SOME(os::touch(file1)); ASSERT_SOME(os::touch(file2)); ASSERT_SOME(os::touch(file3)); ASSERT_TRUE(os::exists(file1)); ASSERT_TRUE(os::exists(file2)); ASSERT_TRUE(os::exists(file3)); Clock::pause(); Future<Nothing> scheduleDispatch1 = FUTURE_DISPATCH(_, &GarbageCollectorProcess::schedule); Future<Nothing> scheduleDispatch2 = FUTURE_DISPATCH(_, &GarbageCollectorProcess::schedule); Future<Nothing> scheduleDispatch3 = FUTURE_DISPATCH(_, &GarbageCollectorProcess::schedule); // Schedule the gc operations. Future<Nothing> schedule1 = gc.schedule(Seconds(10), file1); Future<Nothing> schedule2 = gc.schedule(Seconds(10), file2); Future<Nothing> schedule3 = gc.schedule(Seconds(15), file3); // Ensure the dispatches are completed before advancing the clock. AWAIT_READY(scheduleDispatch1); AWAIT_READY(scheduleDispatch2); AWAIT_READY(scheduleDispatch3); Clock::settle(); // Advance the clock to trigger the GC of file1 and file2. Clock::advance(Seconds(10)); Clock::settle(); AWAIT_READY(schedule1); AWAIT_READY(schedule2); ASSERT_TRUE(schedule3.isPending()); EXPECT_FALSE(os::exists(file1)); EXPECT_FALSE(os::exists(file2)); EXPECT_TRUE(os::exists(file3)); // Trigger the GC of file3. Clock::advance(Seconds(5)); Clock::settle(); AWAIT_READY(schedule3); EXPECT_FALSE(os::exists(file3)); Clock::resume(); }
void ObservableTest::testMultiThreadingGlobalSettings() { BOOST_TEST_MESSAGE("Testing observer global settings in a " "multithreading environment..."); const ext::shared_ptr<SimpleQuote> quote(new SimpleQuote(-1.0)); ObservableSettings::instance().disableUpdates(true); GarbageCollector gc; boost::thread workerThread(&GarbageCollector::run, &gc); typedef std::list<ext::shared_ptr<MTUpdateCounter> > local_list_type; local_list_type localList; for (Size i=0; i < 4000; ++i) { const ext::shared_ptr<MTUpdateCounter> observer(new MTUpdateCounter); observer->registerWith(quote); if ((i%4) == 0) { localList.push_back(observer); for (Size j=0; j < 5; ++j) quote->setValue(Real(j)); } gc.addObj(observer); } gc.terminate(); workerThread.join(); if (localList.size() != Size(MTUpdateCounter::instanceCounter())) { BOOST_FAIL("garbage collection does not work."); } for (local_list_type::iterator iter = localList.begin(); iter != localList.end(); ++iter) { if ((*iter)->counter() != 0) { BOOST_FAIL("notification should have been blocked"); } } ObservableSettings::instance().enableUpdates(); for (local_list_type::iterator iter = localList.begin(); iter != localList.end(); ++iter) { if ((*iter)->counter() != 1) { BOOST_FAIL("only one notification should have been sent"); } } }
int main() { GarbageCollector gc; ValueCreator valueCreator(&gc); ArrayCreator arrayCreator(&gc); Array* array = arrayCreator.create(); int size = 100000; while(size != 0) { array->push(valueCreator.create(size)); size--; } gc.collect(true); return 0; }
Signal::Signal(int contextWindowPosition,double signalScore, SignalSensor &sensor,GarbageCollector &garbageCollector) : contextWindowPosition(contextWindowPosition), sensor(sensor), signalScore(signalScore) { predecessors[0]=predecessors[1]=predecessors[2]=NULL; initializePropagators(signalScore); #ifdef EXPLICIT_GRAPHS garbageCollector.addSignal(this); #endif }
TEST_F(GarbageCollectorTest, Prune) { GarbageCollector gc; // Make some temporary files to prune. const string& file1 = "file1"; const string& file2 = "file2"; const string& file3 = "file3"; const string& file4 = "file4"; ASSERT_SOME(os::touch(file1)); ASSERT_SOME(os::touch(file2)); ASSERT_SOME(os::touch(file3)); ASSERT_SOME(os::touch(file4)); ASSERT_TRUE(os::exists(file1)); ASSERT_TRUE(os::exists(file2)); ASSERT_TRUE(os::exists(file3)); ASSERT_TRUE(os::exists(file4)); Clock::pause(); Future<Nothing> schedule1 = gc.schedule(Seconds(10), file1); Future<Nothing> schedule2 = gc.schedule(Seconds(10), file2); Future<Nothing> schedule3 = gc.schedule(Seconds(15), file3); Future<Nothing> schedule4 = gc.schedule(Seconds(15), file4); AWAIT_ASSERT_EQ(true, gc.unschedule(file3)); AWAIT_DISCARDED(schedule3); // Prune file1 and file2. gc.prune(Seconds(10)); AWAIT_READY(schedule1); AWAIT_READY(schedule2); ASSERT_TRUE(schedule4.isPending()); // Both file1 and file2 will have been removed. EXPECT_FALSE(os::exists(file1)); EXPECT_FALSE(os::exists(file2)); EXPECT_TRUE(os::exists(file3)); EXPECT_TRUE(os::exists(file4)); // Prune file4. gc.prune(Seconds(15)); AWAIT_READY(schedule4); EXPECT_FALSE(os::exists(file4)); Clock::resume(); }
Signal::Signal(int contextWindowPosition,double signalScore, SignalSensor &sensor,GarbageCollector &garbageCollector, SignalType signalType) : contextWindowPosition(contextWindowPosition), sensor(sensor), signalScore(signalScore), signalType(signalType), annotated(false) { predecessors[0]=predecessors[1]=predecessors[2]=NULL; const int n=SignalTypeProperties::global.belongsInWhichQueues(signalType).size(); propagators.resize(n); propagators.setAllTo(NULL); initializePropagators(signalScore); #ifdef EXPLICIT_GRAPHS garbageCollector.addSignal(this); #endif }
TEST_F(GarbageCollectorTest, Unschedule) { GarbageCollector gc; // Attempt to unschedule a file that is not scheduled. AWAIT_ASSERT_EQ(false, gc.unschedule("bogus")); // Make some temporary files to gc. const string& file1 = "file1"; const string& file2 = "file2"; const string& file3 = "file3"; ASSERT_SOME(os::touch(file1)); ASSERT_SOME(os::touch(file2)); ASSERT_SOME(os::touch(file3)); ASSERT_TRUE(os::exists(file1)); ASSERT_TRUE(os::exists(file2)); ASSERT_TRUE(os::exists(file3)); Clock::pause(); // Schedule the gc operations. Future<Nothing> schedule1 = gc.schedule(Seconds(10), file1); Future<Nothing> schedule2 = gc.schedule(Seconds(10), file2); Future<Nothing> schedule3 = gc.schedule(Seconds(10), file3); // Unschedule each operation. AWAIT_ASSERT_EQ(true, gc.unschedule(file2)); AWAIT_ASSERT_EQ(true, gc.unschedule(file3)); AWAIT_ASSERT_EQ(true, gc.unschedule(file1)); // Advance the clock to ensure nothing was GCed. Clock::advance(Seconds(10)); Clock::settle(); // The unscheduling will have discarded the GC futures. AWAIT_DISCARDED(schedule1); AWAIT_DISCARDED(schedule2); AWAIT_DISCARDED(schedule3); EXPECT_TRUE(os::exists(file1)); EXPECT_TRUE(os::exists(file2)); EXPECT_TRUE(os::exists(file3)); Clock::resume(); }
inline AllocatorOperation free_op(Reference ref, GarbageCollector &gc) { void *ptr = reinterpret_cast<void *>(reinterpret_cast<char *>(ref.ptr()) - gc.header_size()); return AllocatorOperation(FREE, ptr); }
inline void operator delete(void*, GarbageCollector<T>& gc) { gc.free_last(); }