//
// Copyright (c) 2002
// Ronald Kevin Burton
//
// Z poniższym kodem nie jest związana żadna gwarancja poprawności działania.
// Program został dołączony do książki ".NET CLR. Księga eksperta" w celu
// ilustracji koncepcji i zasad przedstawionych w tej książce. Program może być 
// używany na własne ryzyko.
//
// Przyznaje się prawo do użycia lub kopiowania tego oprogramowania do dowolnego celu
// bez konieczności ponoszenia żadnych opłat pod warunkiem, że powyższe uwagi zostaną 
// zachowane we wszystkich kopiach. Przyznaje się także prawo do modyfikacji kodu
// i dystrybucji zmodyfikowanego kodu pod warunkiem zachowania powyższych uwag
// oraz dołączenia informacji mówiącej o modyfikacji kodu.
//
// 
using System;
using System.Threading;

namespace ProfilingSamples
{
	public class GCGenerationMain 
	{
		public class BaseObj 
		{
			private string name;
			public BaseObj(string name)
			{
				this.name = name;
			}
		}
		public class TestObj : BaseObj 
		{
			public TestObj(String s) : base(s) 
			{
			}
			public int Generation 
			{
				get
				{
					return GC.GetGeneration(this);
				}
			}
		}
		void TestThread()
		{
			try
			{
				// Sprawdźmy, ile generacji może obsłużyć zarządzana sterta (wiemy, że są to 2 generacje)
				Console.WriteLine("Maksymalna liczba generacji GC: {0}", GC.MaxGeneration);
				TestObj [] toa = new TestObj[10];
				while(true)
				{ 
					for(int i = 0; i < toa.Length; i++)
						toa[i] = new TestObj("TestObj" + i.ToString());

					// Wykonanie GC zmienia generację obiektu
					GC.Collect();

					GC.Collect();

					GC.Collect();

					// Zniszczenie silnego odwołania do tego obiektu
					for(int i = 0; i < toa.Length; i++)
						toa[i] = null;

					GC.Collect(0);
					GC.WaitForPendingFinalizers();

					GC.Collect(1);
					GC.WaitForPendingFinalizers();

					GC.Collect(2);
					GC.WaitForPendingFinalizers();

					Thread.Sleep(500);
				}
			}
			catch(Exception e)
			{
				Console.WriteLine("TestThread przerywa pracę: {0}", e.Message);
			}
		}
		static void Main(string [] args)
		{
			GCGenerationMain m = new GCGenerationMain();
			Thread testThread = new Thread(new ThreadStart(m.TestThread));
			testThread.Start();
			string input = Console.ReadLine();
			testThread.Abort();
			testThread.Join();
		}
	}
}