//
// 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.Diagnostics;

namespace LinkedList
{
	/// <summary>
	/// Podsumowanie dla LinkedObject.
	/// </summary>
	public class LinkedObject
	{
		private LinkedObject link;
		public LinkedObject()
		{
		}
		public LinkedObject(LinkedObject node)
		{
			link = node;
		}
		public LinkedObject Link
		{
			get
			{
				return link;
			}
			set
			{
				link = value;
			}
		}
	}
	public class FinalizedLinkedObject
	{
		private FinalizedLinkedObject link;
		public FinalizedLinkedObject()
		{
		}
		public FinalizedLinkedObject(FinalizedLinkedObject node)
		{
			link = node;
		}
		public FinalizedLinkedObject Link
		{
			get
			{
				return link;
			}
			set
			{
				link = value;
			}
		}
		~FinalizedLinkedObject()
		{
		}
	}
	// Kod wywodzi się z IDisposable, ci zapewnia implementację
	// właściwych metod oraz umożliwia sprawdzenie, czy ten obiekt
	// obiekt obsługuje deterministyczny model finalizacji. Odbywa się
	// fto poprzez zapytanie obiektu o interfejs IDisposable.
	public class DisposeLinkedObject : IDisposable
	{
		// Stan tego obiektu powinien być umieszczony w buforze,
		// co daje pewność jednorazowej finalizacji obiektu. Należy upewnić
		// się, czy ta zmienna została poprawnie zainicjalizowana
		// we wszystkich konstruktorach tego obiektu lub czy zapewnia
		// domyślną wartość.
		private bool disposed = false;
		private DisposeLinkedObject link = null;
		// W tym kodzie został zaimplementowany tylko domyślny konstruktor.
		// W przypadku prawdziwej aplikacji zasób kapsułkowany przez ten
		// obiekt jest tutaj tworzony, istnieje inny konstruktor pozwalający
		// na właściwe utworzenie tego obiektu i/lub istnieje jawna metoda
		// open pozwalająca na utworzenie zasobu.
		public DisposeLinkedObject()
		{
		}
		public DisposeLinkedObject(DisposeLinkedObject node)
		{
			link = node;
		}
		public DisposeLinkedObject Link
		{
			get
			{
				return link;
			}
			set
			{
				link = value;
			}
		}
		// Będzie to główna metoda ujawniana przez obiekt w celu
		// deterministycznej finalizacji. Obiekt powinien być
		// otwierany poprzez dyrektywę new i konstruktora (lub przez 
		// jawne wywołanie open), a następnie jawnie zamknięty
		// przez tę metodę.
		public void Close()
		{
			Dispose();
		}
		// Implementacja IDisposable. Istnieje tylko jedna metoda
		// implementacji w interfejsie IDisposable. Nie należy tworzyć
		// metody wirtualnej, a klasa pochodna nie powinna mieć
		// możliwości zastąpienia tej metody.
		public void Dispose()
		{
			// Usunięcie zarządzanych i niezarządzanych zasobów.
			Dispose(true);
			// Usunięcie tego obiektu z kolejki finalizacji, dzięki
			// czemu kod finalizacji dla tego obiektu nie zostanie
			// wykonany po raz drugi.
			GC.SuppressFinalize(this);
		}
		// Funkcja Dispose(bool disposing) może być użyta w dwóch sytuacjach.
		// Jeśli wartość disposing jest prawdą, to ta metoda została wywołana
		// pośrednio lub bezpośrednio przez kod użytkownika. Usunięcie
		// zarządzanych i niezarządzanych zasobów jest możliwe.
		// Jeśli wartość disposing jest fałszem, to ta metoda została wywołana
		// przez moduł wykonawczy z wewnątrz finalizera, przez co nie należy
		// odwoływać się do innych obiektów. Możliwe jest usunięcie tylko
		// niezarządzanych zasobów.
		protected virtual void Dispose(bool disposing)
		{
			// Sprawdzenie, czy wywołano już Dispose.
			if(!this.disposed)
			{
				// Jeśli wartość disposing jest prawdą, to usunięcie wszystkich
				// zarządzanych i niezarządzanych zasobów.
				if(disposing)
				{
					// Usunięcie zarządzanych zasobów.
				}
				// Zwolnienie niezarządzanych zasobów. Jeśli wartość disposing jest
				// fałszem, to tylko ta część kodu jest wykonywana.
				//
				// Uwaga: Ten kod nie zapewnia bezpieczeństwa wątek.
				// Inny wątek może rozpocząć usuwanie obiektu po usunięciu
				// zarządzanych zasobów, ale przed ustawieniem odpowiedniego
				// znacznika. Jeśli zostanie użyty tu kod synchronizacji,
				// to nie można pozwolić na blokowanie przez zbyt długi czas 
				// ze względu na możliwość wywołania tego kodu z poziomu
				// destruktora.
			}
			// Należy upewnić się, czy zasoby nie zostaną zwolnione
			// więcej niż jeden raz.
			disposed = true;         
		}

		// Ten destruktor zostanie uruchomiony tylko jeśli metoda Dispose 
		// nie zostanie wywołana, gdyż w przeciwnym wypadku następuje użycie
		// GC.SupressFinalize(), który sprawdza fakt wywołania destruktora
		// dla tego obiektu. Daje to szansę finalizacji klasy bazowej.
		// Nie należy używać destruktorów dla typów wywodzących się z tej klasy.
		~DisposeLinkedObject()      
		{
			// Nie należy tworzyć tu ponownie kodu czyszczącego Dispose.
			// Wywołanie Dispose(false) jest optymalne w zakresie czytelności
			// i łatwości obsługi.
			// Wywołanie Dispose(false) powoduje usunięcie tylko niezarządzanych
			// zasobów.
			Dispose(false);
		}

	}
}
