Singleton 1 1.

Slides:



Advertisements
Podobné prezentace
A1PRG - Programování – Seminář Ing. Michal Typová konverze, oblast platnosti, paměťové třídy 9 Verze
Advertisements

(instance konkrétní třídy)
ÚVOD DO C++ 3 TŘÍDY a objekty - POKRAČOVÁNÍ
Seminář C++ 5. cvičení Dědičnost Ing. Jan Mikulka.
Programovací jazyk C++
Pole, ukazatele a odkazy
ÚVOD DO CPP 7 Dědičnost - pokračování
BLIŽŠÍ POHLED NA TŘÍDY, DĚDIČNOST - úvod
PJV151 Vnořené a vnitřní členy mohou být členy tříd a interfejsů. Je-li X obalem Y a Y je obalem Z, pak Z získá jméno X$Y$Z - kompilací vzniknou classy.
C++ Přednáška 3 Konstantní a statické členy tříd, ukazatel this, konstantní instance třídy Ing. Jiří Kulhánek , kat. 352, VŠB TU Ostrava 2004.
Programování v C++ Cvičení.
Principy překladačů Běhová podpora Jakub Yaghob. Běhová podpora Statická podpora jazyka Překladač Interface na knihovny Hlavičkové soubory Dynamická podpora.
Čtvrté cvičení Objektové programování Objektový model v Javě
J a v a Začínáme programovat Lucie Žoltá metody, objekty, konstruktor.
Chain of responsibility Martin Malý prezentace na předmět Návrhové vzory (PRG024) na MFF UK
C# - struktury, výčtové typy, pole
State. State – kontext a problém Kontext  chování objektu má záviset na jeho stavu, který se typicky mění za běhu Neflexibilní řešení  metody obsahují.
Páté cvičení Dědičnost Interface Abstarktní třídy a metody
Seminář C cvičení STL, Trolltech Ing. Jan Mikulka.
Adapter. Adapter – pojem Součástka navržená k propojení dvou „nekompatibilních“ zařízení Definice slova podle Cambridge Advanced Learner's Dictionary:
C# - Exceptions (výjimky)
Objektové programování
C# - funkce a procedury Centrum pro virtuální a moderní metody a formy vzdělávání na Obchodní akademii T.G. Masaryka, Kostelec nad Orlicí.
Jedenácté cvičení Vlákna. Java cv112 Vlákna Operační systém Mutitasking – více úloh se v operačním programu vykonává „současně“ Java Multithreading -
Seminář C cvičení Obsluha výjimek Ing. Jan Mikulka.
08/04/20151 Delegáty (1) Delegát (delegate) je datový typ, který definuje signaturu metody Delegáty bývají rovněž označovány jako typo- vě bezpečné ukazatele.
PRÁCE S VLÁKNY A APLIKAČNÍ DOMÉNY V.NET FRAMEWORK APLIKACÍCH Architektura technologie.NET Jan Martinovič, FEI - Katedra Informatiky.
Strategy. Strategy – „All-in-1“ na začátek class AStrategy { public: virtual void Algorithm()=0; protected: AStrategy(); }; class SpecificStrategy: public.
Seminář C++ 4. cvičení Objekty Ing. Jan Mikulka. Co je objekt ► obraz třídy i instance ► třída – definovaná za pomocí klíčového slova class ► instance.
6. cvičení Polymorfismus
A1PRG - Programování – Seminář Ing. Michal Ukazatele a pole 10 Verze
Počítače a programování 1
PB161 Právo friend, přetěžování operátorů, přetypování PB161 | Friend, operátory PB161 – Programování v jazyce C++ Objektově Orientované Programování.
Memento. Obnovení operačního systému ( Windows | Linux...) Všichni víme, co jsou transekce v databázi Memento – zálohování databáze.
KIV/PPA1 cvičení 8 Cvičící: Pavel Bžoch. Osnova cvičení Objekty v Javě Třída Konstruktor Metody Metody a proměnné třídy x instance Program sestávající.
OSNOVA: a) Úvod do OOPb) Třídy bez metod c) Třídy s metodamid) Konstruktory a destruktory e) Metody constf) Knihovní třídy g) Třídy ve tříděh) Přetížení.
PB161 Principy OOP - rozhraní, dědičnost PB161 | Principy OOP - Dědičnost, rozhraní
C# - předávání parametrů Centrum pro virtuální a moderní metody a formy vzdělávání na Obchodní akademii T.G. Masaryka, Kostelec nad Orlicí.
IB111 Programování a algoritmizace
Návrh a tvorba WWW Přednáška 5 Úvod do jazyka PHP.
OSNOVA: a) Přetížení členských funkcí b) Dědičnost tříd Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače a programování 2 pro obor EST BPC2E.
Dědičnost - inheritance dědičnost je jednou z forem znovupoužitelnosti dědičnost je jednou z forem znovupoužitelnosti B A Třída A je předkem třídy B Třída.
13/04/20151 Datový typ třída – class (1) Datový typ definovaný uživatelem Poskytuje mechanismus pro modelování entit, s nimiž manipulují aplikace Charakterizuje.
Metodika objektového přístupu při tvorbě překladačů. Marek Běhálek Informatika a aplikovaná matematika FEI VŠB-TU Ostrava.
Principy OOP Objektově orientované programování vychá-zí ze třech základních principů (rysů): zapouzdření (encapsulation) dědičnost (inheritance) polymorfismus.
Netrvaloppa21 Vytvořte třídu Student pro reprezentaci struktury student na ZČU. Atributy třídy budou fakulta a osobniCislo. Název třídy: Student proměnné.
Počítače a programování 1 7.přednáška. Základy Pole ve třídách a metodách Pole Arrays.
FEL Komunikátor. Memory Leak program konsumuje operační paměť, kterou neumožňuje uvolnit o uvolnění paměti stará Garbage Collector ▫plně v režii Java.
Pokročilé programování v C++ (část B)
Jazyk C A0B36PRI - PROGRAMOVÁNÍ Část II.
Strategy. Motivace Různé algoritmy pro stejnou akci Hromada kódu v mnoha podmínkách Důsledky  Komplexnost  Špatná čitelnost  Těžká správa kódu  Těžka.
Iterator Iterator – Problém struct Item { int _value; Item * _next; Item( int value, Item * next ) : _value( value ), _next( next ) { } }; void Print(
Template Method. Motivační příklad – reálný svět Čaj 1) Uvař vodu 2) Dej do hrnku sáček čaje 3) Zalij hrnek 4) Přisyp cukr a vymačkej citrón Káva 1) Uvař.
NÁZEV ŠKOLY: S0Š Net Office, spol. s r.o., Orlová-Lutyně AUTOR: Ing. Adéla Tomalová NÁZEV: Podpora výuky v technických oborech TEMA: Objektově orientované.
Programování v jazyce C++ Speciality jazyka C++, úvod do OOP.
Y36PJC Programování v jazyce C/C++
Úvod do C# - OOP Jaroslav BURDYS 4IT.
Programovací jazyk C++
Y36PJC Programování v jazyce C/C++
ZAL – 3. cvičení 2016.
Singleton
Návrhový vzor Flyweight
Počítače a programování 2 pro obor EST BPC2E PŘEDNÁŠKA 3
Lazy load Použity informace z knihy Patterns of Enterprise Application Architecture od M. Fowlera Jan Sládek.
Bridge.
C# přehled vlastností.
NÁZEV ŠKOLY: S0Š Net Office, spol. s r.o., Orlová-Lutyně
Monitor Object 1.
Singleton
Composite “Spojuj a panuj”.
Transkript prezentace:

Singleton 1 1

Jasná i temnější zákoutí jazyka C++ Všichni patrně znají…. ….klíčové slovo static a jeho význam pro členy třídy. ….rozdíl mezi statickou a dynamickou alokací (operátor new). Někdo už možná pozapomněl, ale každý by asi domyslel, že…. ....není definováno pořadí inicializace statických objektů v různých .cpp souborech. ….pořadí odstraňování těchto objektů je obrácené než pořadí inicializace. Avšak toto pořadí není možné za běhu programu nijak rozumně a hezky zjistit. Málokdo ví…. ….jak přesně funguje funkce atexit(). 2 2

Singleton – obsah Motivace Základní myšlenka Implementace Problémy Vícevláknovost dědičnost destrukce Shrnutí 3 3

Singleton – motivace Co mají následující příklady společného? Odpověď: DatabaseConnectionPool – přiděluje spojení do DB jednotlivým částem aplikace WindowManager – v okenním systému existuje jeden objekt spravující okna Keyboard, display, log – (KDL) PrinterSpooler – více tiskáren, jeden manažer FileSystem System clock Herní prostředí – např. mapa ve hře Odpověď: Třídy řešící tyto problémy vyžadují jedinou instanci. Mít více instancí může být zbytečné, nežádoucí, nebezpečné nebo nemožné. Měly by být lehce přístupné z libovolného místa. 4 4

Singleton – naivní implementace → základní myšlenka Globální proměnná + zaručuje globální přístupový bod - znepřehledňuje namespace a kód - nedokáže zaručit jedinou instanci objektu Statická data + statické metody + zaručuje jedinou instanci - problém rozšiřitelnosti – statické metody nemohou být virtuální - problém inicializace (závislosti) - problém úklidu (kdo to má dělat) Lepší řešení třída se o jedinečnost své instance stará sama inicializace: konstruktor úklid: destruktor problem inicializace – staticke promenne sa inicializuju pri zavadeni probramu. Norma nedefinuje poradi inicializace, nelze se tedy vytvarat zavislosti 5 5

Singleton – požadavky Zaručení jediné instance Globální přístupový bod zakázat vytvoření více instancí zakázat kopírování existující instance zakázat zrušení instance zakázat deserializaci Globální přístupový bod použití na libovolném místě kódu přístup poskytován samotnou třídou Navíc bychom rádi zachovali možnost rozšiřitelnosti bez nutnosti zásahu do kódu předka všechny nástroje objektového programování virtuální metody, abstraktní metody, přetěžování metod možnost rozšiřitelnosti pomocí šablon 6 6

Singleton – návrh řešení třída si řídí vytváření instance a přístup k ní sama je schopná zajistit jedinečnost instance Veřejná statická přístupová metoda. Statická reference na jedinou instanci. Metody nad instancí singletonu. 7 7

Singleton – Lazy instantiation V C++ nelze použít statickou inicializaci nelze definovat pořadí konstruktorů statických tříd navíc objekt může být vytvořen zbytečně class Singleton { private: static Singleton instance; public: static Singleton * instance() { return &instance; } Na první pohled správné, ale kvůli nedefinovanému pořadí inicializace špatné! Řešení - objekt bude vytvořen, až když o něj bude skutečně požádáno lze snadno ovlivnit pořadí konstrukce nikdy nebude vytvořen zbytečně lze dosáhnout malou úpravou statické funkce vracející instanci objektu analogická implementace funkční ve všech rozumných jazycích static Singleton instance() { if (instance == 0) { instance = new Singleton; } return instance; Instance se vytvoří při prvním volání instance() – až když je to potřeba. 8 8

Singleton – implementace C++ Statická metoda pro přístup k jediné instanci. class Singleton { public: static Singleton &instance() { if (pInstance == 0) { pInstance = new Singleton; } return pInstance; void doSomethingUseful() {...} private: Singleton() {...} Singleton(const Singleton&); Singleton& operator=(const Singleton&); ~Singleton() {...} static Singleton* pInstance; }; Singleton* Singleton::pInstance = 0; int main(int argc, char** argv) { Singleton::instance().doSomethingUseful(); ... Instance se vytvoří při prvním volání instance() – až když je to potřeba. Konstruktor nesmí být public. Inicializuje třídu. Volán jenom zevnitř třídy. Kopírovací konstruktor a operátor přiřazení se snaží kompilátor generovat sám. Je nutné mu v tom zabránit. Destruktor nesmí být public, někdo by mohl smazat instanci. Ukazatel na instanci si spravuje třída sama. Statická inicializace. Jednoduchý příklad použití. 9 9

Singleton – implementace C# (a Java) Statická metoda pro globální přístup k jediné instanci. class Singleton { public static Singleton Instance() { return instance; } void doSomethingUseful() {...} private Singleton() {...} private static Singleton instance = new Singleton(); Konstruktor nesmí být public. Inicializuje třídu. Volán jenom zevnitř třídy. Referenci na instanci si spravuje třída sama. Statická inicializace. C# a Java v tomto případě zajistí vždy korektní konstrukci a téměř nikdy nevytvoří Singleton zbytečně 10 10

Singleton – implementace C# (a obdobně Java) Detailnější pohled – ještě línější implementace C# a Java inicializují statické položky třídy před prvním přístupem Navíc tím získáme thread-safe řešení public class Singleton { private Singleton () {} class SingletonCreator { private static SingletonCreator () {} internal static readonly Singleton instance = new Singleton(); } public static Singleton Instance() { return SingletonCreator.instancee; Vnitřní třída pro línou inicializaci. Viditelnost internal, aby vnější třída mohla k této položce přistoupit. Pro vnější svět je stále privátní. Privátní objekt inicializovaný privátním konstruktorem. 11

Singleton – Java problémy a enum implementace Problém serializace, pokud ji požadujeme – vrací novou instanci => je nutné mít všechny položky transient a přetížit readResolve Problém s reflection – lze přistoupit k privátnímu konstruktoru => měl by házet výjimku, pokud už instance existuje Jiné řešení – enum Singleton public enum Singleton { INSTANCE; public void doSomethingUseful() { ... } } ... Singleton.INSTANCE.doSomethingUseful() Řeší problém s reflection, serializací 12

Singleton – problémy GoF '95 Problém vícevláknových aplikací Dědičnost relativně jednoduchý vzor od té doby rozsáhlé diskuse Vlissides '98: “I used to think it was one of the more trivial of our patterns ... Boy, I was wrong!” Problém vícevláknových aplikací Dědičnost Problém destrukce (lifetime) 13 13

Singleton – více vláken a procesorů V prostředí více vláken nesplňuje definici může vytvořit více instancí public static Singleton Instance() { if (instance == null) { instance = new Singleton(); } return instance; sem se může dostat více vláken Řešení - zámky 14 14

uzamknutí zajistí přístup jen Singleton – více vláken a procesorů, zamykání (C#) Řešení - zámky zaručují jednu instanci na multiprocesorech nezbytná kombinace s volatile – cache coherency problem funguje ve všech jazycích režie může být nepřijatelně vysoká private static volatile Singleton instance; private static object lockObj = new Object(); public static Singleton Instance() { lock (lockObj) { if (instance == null) { instance = new Singleton(); } return instance; uzamknutí zajistí přístup jen jednomu vláknu Jde to lépe? referenci (či pointer) si můžeme ukládat – nevolat opakovaně Instance() double-checked locking pattern 15 15

Singleton – double-checked locking Pozorování referenci získáváme často konstrukci provádíme (doufejme) jen jednou stačí zamykat jen při konstrukci Double-Checked Locking Pattern private static volatile Singleton instance; private static object lockObj = new Object(); public static Singleton Instance() { if (instance == null) { lock (lockObj) { instance = new Singleton(); } return instance; Za první podmínku se může dostat více vláken. Za zámek už jen jedno vlákno, znovu ověření podmínky, jinak by později prolezlo případné další čekající vlákno. Zde mi to už nikdo nezmění. Není to příliš jednoduché řešení pro tak složitý vzor? 16 16

Singleton – double-checked locking C++ problémy norma pro vícevláknové aplikace mnoho nezaručuje dovoluje prohazovat instrukce. Instance nemusí být null, ale přesto nemusí být inicializována Java, C# problémy dovolují při optimalizaci prohazovat instrukce. Instance nemusí být null, ale přesto nemusí být inicializována až do Javy 1.2 chyba v garbage collectoru až do Javy 1.4 nepříliš jasné a správné chování volatile nyní už double-checked locking s volatile funguje správně Java, C# – volatile vlákna přistupují k proměnné „jako by byla celá v zamčené sekci“ vlákno čte vždy aktuální necachovanou hodnotu 17 17

Singleton – dědičnost Singleton vydává za svou instanci instanci některého z potomků existuje maximálně jedna instance přes všechny potomky v C++ musí potomek být spřátelený s bázovou třídou nebo být vnořenou třídou v Javě nebo C# musí být potomek vnořenou třídou Několik singletonů implementuje společné rozhraní existuje maximálně jedna instance pro každého z potomků 18 18

Singleton – dědičnost (1. případ) class Singleton { public: static Singleton &instance() { if (pInstance == 0) { if (getEnv(“NAZEV”) == “PRVNI”) pInstance = new Prvni; else pInstance = new Druhy; } return pInstance; virtual void doSomethingUseful() = 0; private: /* konstruktory, destruktory, atd. */ }; class Prvni : public Singleton { virtual void doSomethingUseful() {...} friend class Singleton; class Druhy : public Singleton { /* podobně jako třída Prvni */ Vytvoří se taková instance, která je požadována. Společné rozhraní, které musí všechny odděděné třídy implementovat. Implementace rozhraní. Aby mohla bázová třída vytvářet instance. 19 19

Singleton – dědičnost (1. případ) Registruje instanci singletonu pod zadaným jménem. class Singleton { public: static void Register(const char * name, Singleton *); static Singleton * Instance() { if (_instance == 0) { const char * singletonName = getenv("SINGLETON"); _instance = Lookup(singletonName); } return _instance; protected: static Singleton * Lookup(const char * name); private: static Singleton * _instance; static list<NameSingletonPair> * registry; }; class MySingleton : public Singleton { static MySingleton theSingleton; MySingleton() { ... Singleton::Register("MySingleton", this); Nalezne se a vrátí taková instance, která je požadovaná. Najde instanci podle jména. Udržuje dvojici název odvozeného singletonu a jeho instanci. Singleton se při vytvoření registruje rodiči. Instance musí před jejím hledáním existovat! Problém: Je jedna „pravá“ instance přes všechny potomky, ale ostatní stejně existují 20

Singleton – dědičnost (2. případ) #include <iostream> template<typename T> class Base { public: static T &instance() { static T inst; return inst; } virtual void echo () = 0; protected: Base() {} virtual ~Base() {} private: Base(const Base &); Base& operator=(const Base &); }; class Derived: public Base<Derived> { friend class Base<Derived>; void echo () { std::cout << “I’m Derived" << std::endl; } Derived() {} virtual ~Derived() {} int main(int argc, char **argv) { Derived &derived = Derived::instance(); derived.echo(); Dědičnost implementována pomocí šablon. Možnost šablonování metody instance(), místo třídy. Možnost vytváření abstrakních metod. Třída Base<Derived> musí být náš friend (volání konstruktoru ze statické metody instance()). Jednoduché použití. 21 21

Singleton – destrukce Zodpovědnost za zrušení Kdy je objekt zrušen je nutné uvolnit paměť? je nutné uvolnit používané prostředky Kdy je objekt zrušen nutné dodržet určité pořadí rušení Některé objekty je potřeba mít přístupné vždy log 22 22

Singleton – destrukce Ostrich 'Ostrichovo' řešení (leaking singleton) problém destrukce ignorovat statická paměť se uvolní automaticky při ukončení procesu jako každá kulturní třída by měl mít destruktor zápis do logu, uzavření spojení, odhlášení, ... lze vést diskuze o tom co je a co není leak (memory leak, resource leak) V čem je problém? destruktor se nezavolá ukládáme statický ukazatel, ne statický objekt 23 23

Singleton – destrukce killer Idea ukazatel zabalit do třídy starajíci se o destrukci kompilátor se stará o zrušení statického objektu singletonKiller, který ve svém destruktoru instanci Singleton zabíjí class SingletonKiller { public: void setSingleton(Singleton* _instance) { instance = _instance; } Singleton* getSingleton() { return instance; ~SingletonKiller() { delete instance; private: static Singleton* instance; }; class Singleton { static Singleton* instance(); Singleton(); ~Singleton(); Singleton(const Singleton&); Singleton& operator=(const Singleton&); static SingletonKiller singletonKiller; Singleton* SingletonKiller::instance = 0; SingletonKiller Singleton::singletonKiller; 2. destruktor killera killer obsahuje ukazatel na náš singleton 3. destruktor singletonu 1. destrukce statické proměnné Singleton* Singleton::instance() { if (!singletonKiller.getSingleton()) { singletonKiller.setSingleton( new Singleton); } return singletonKiller.getSingleton(); 24 24

Singleton – Meyers Scott Meyers místo operátoru new, statická lokální proměnná instanci nedržíme ve statickém ukazateli funkce vracející referenci na statický objekt ve funkci 2. inicializace statického objektu pouze při prvním průchodu registrace atexit class Singleton { public: static Singleton& instance() { static Singleton inst; return inst; } private: Singleton() {...} Singleton(const Singleton&); Singleton& operator=(const Singleton&); ~Singleton() {...} }; int main(int argc, char** argv) { Singleton& s = Singleton::instance(); ... 4. návrat zkonstruovaného objektu 3. konstruktor objektu 6. destruktor objektu 1. zavolá se metoda 5. konec programu, destrukce statických proměnných 25 25

Singleton – funkce atexit Odstraňování statických proměnných LIFO – nejdříve se odstraní naposledy inicializované int atexit(void*(pFunction)()); při vytváření objektu se zaregistruje funkce pro zrušení při ukončení programu se postupně zavolají registrované funkce Singleton& Singleton::instance() { extern void __constructSingleton(void* memory); extern void __destroySingleton(); static bool __initialized = false; static char __buffer[sizeof(Singleton)]; if (!__initialized) { __constructSingleton(__buffer); atexit(__DestroySingleton); __initialized = true; } return *reinterpret_cast<Singleton*>(__buffer); funkce generované kompilátorem proměnné generované kompilátorem __buffer obsahuje Singleton volání funkce __constructSingleton() zavolá konstruktor na paměti __buffer zaregistruje destrukci 26 26

Singleton – pořadí destrukce Dead reference problem při nevhodném pořadí mohou vzniknout reference na neexistující objekty příklad: singletony Keyboard, Display, Log vytvoření instance Log pouze při chybě destrukce Logu by měla následovat až po destrukcích ostatních singletonů nebo aspoň poznat problém a slušně umřít inicializace Keyboard inicializace Display s chybou inicializace Log a zapsání chyby konec programu destrukce Log destrukce Display destrukce Keyboard s chybou reference neexistujícího objektu Log 27 27

inicializace přesunuta do privátní metody Singleton – detekce mrtvé reference Detekce destruovaného objektu přidání statické proměnné, její nastavení v destruktoru class Singleton { public: static Singleton& instance() { if (!pInstance) { if (destroyed) throw ...; else create(); } return *pInstance; private: static void create() { static Singleton inst; pInstance = &inst; Singleton() {...} Singleton(const Singleton&); Singleton& operator=(const Singleton&); ~Singleton() { destroyed = true; pInstance = NULL; static bool destroyed; static Singleton* pInstance; }; Singleton* Singleton::pInstance = 0; bool Singleton::destroyed = false; detekce problému inicializace přesunuta do privátní metody nastavení zrušení příznak zrušení 28 28

Singleton – Fénix Detekce někdy nestačí - nutnost přístupu k singletonu kdykoliv idea: bájný pták Fénix vstane ze svého popela znovuvytvoření při detekci zrušeného objektu příklad KDL - Keyboard a Display obyčejné singletony, Log Fénix C++: paměť statických objektů zůstane alokována až do konce běhu programu problém: stav starého mrtvého Singletonu je navždy ztracen class Singleton { ... void KillPhoenix(); }; void Singleton::OnDeadRef() { Create(); new(pInstance) Singleton; atexit(KillPhoenix); destroyed = false; } void Singleton::KillPhoenix() { pInstance->~Singleton(); zbytek třídy nezměněn při detekci zrušení se uloží reference na paměť zrušeného objektu placement new zavolání konstruktoru na daném místě registrace destruktoru fénixu explicitní zavolání destruktoru nelze delete! 29 29

Singleton – dlouhověkost Problémy Fénixe ztráta stavu, uložení, uzavření, ... Nejasnost C++ standardů ohledně funkce atexit() Singleton s dlouhověkostí při vytváření singletonu priorita destrukce KDL – Log bude mít větší dlouhověkost explicitní mechanismus destrukce objektů nelze použít destrukci řízenou kompilátorem - pouze dynamické objekty mechanismus by měl fungovat na jakékoliv (dynamické) objekty class SomeSingleton { ... }; class SomeClass { ... }; SomeClass* pGlobalObject(new SomeClass); template <typename T> void SetLongevity(T* pDynObj, int longevity); int main() { SetLongevity(&SomeSingle().Inst(), 5); SetLongevity(pGlobalObject, 6); ... } šablona pro nastavování dlouhověkosti prioritní fronta na zabití po ukončení programu se objekty destruují v tomto pořadí 30 30

Singleton – implementace dlouhověkosti Prioritní fronta při stejných prioritách se chová jako zásobník C++ pravidlo: dříve inicializované objekty se destruují později čeho to bude fronta? neexistuje společný předek, registrační funkce je šablona ukazatel na abstraktního předka šablon obsahujících ukazatel na objekt virtuální držák virtuální destruktor LifeTimeTracker virtual ~LifeTimeTracker() longevity šablona instanciována a objekt vytvořen šablonou SetLongevity ConcreteLTT<T> ~ConcreteLTT() T ~T() delete obj; 31 31

vlastní fronta na zabití Singleton – implementace dlouhověkosti class LifetimeTracker { public: LifetimeTracker(unsigned int x): longevity(x) {} virtual ~LifetimeTracker() = 0; friend inline bool Compare( unsigned int longevity, const LifetimeTracker* p) { return p->longevity_ > longevity; } private: unsigned int longevity; }; inline LifetimeTracker::~LifetimeTracker() {} typedef LifetimeTracker** TrackerArray; extern TrackerArray pTA; extern unsigned int elements; template <typename T> struct Deleter { static void Delete(T* pObj) { delete pObj; virtuální držák umí zabíjet... ... a porovnávat stáří vlastní fronta na zabití způsob zabití defaultně delete lze i free, ... Bylo dříve vejce nebo slepice? TrackerArray se musí chovat jako Singleton čímžpádem ale trpí všemi jeho problémy 32 32

Singleton – kategorizace Dělení z hlediska vytvoření dynamické (operátor new, malloc) destruktor se nezavolá statické (Meyers singleton) funkce vracející referenci na statický objekt Threading model jednovláknové bez synchronizace double-checked locking problémy se synchronizací – platformě závislé Životnost (lifetime) Ostrichovo řešení (Leaking singleton) resource, memory leaks killer obalení ukazatele třídou starající se o destrukci životnost určená kompilátorem (Meyers singleton) destrukce v pořadí podle LIFO detekce mrtvé reference při detekci zrušeného objektu výjimka Fénix singleton po zrušení objektu jeho znovuvytvoření dlouhověkost (singleton with longevity) specifikace pořadí destrukcí 33 33

Singleton – shrnutí, související vzory Možné použití zjednodušení stavu aplikace - zajištění pouze jedné instance nějakého objektu řízení přístupu do DB, tiskových zdrojů… omezení plýtvaní zdrojů (lze přidělit existující spojení) možnost regulovat počty, frekvence… přístupů přidělení spojení s vhodnými právy Související NV Abstract Factory, Builder, Prototype častá implementace pomocí singletonu Facade v případě potřeby pouze jednoho vstup do systému State stavové objekty jsou často Singletony 34 34