Narzędzia użytkownika

Narzędzia witryny


aktywny_obiekt

Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Next revision
Previous revision
aktywny_obiekt [2008/04/15 20:23]
krogala utworzono
aktywny_obiekt [2008/04/15 20:43]
krogala
Linia 1: Linia 1:
-===Wzorzec Projektowy Aktywny Obiekt===+====== Wzorzec Projektowy Aktywny Obiekt ​======
 autor: Krzysztof Rogala autor: Krzysztof Rogala
  
 +===== Problem =====
 Wyobraźmy sobie bazę danych (już istniejącą). Jedni użytkownicy mogą czytać z niej dane, a innni je zmieniać. Ci pierwsi (dalej: czytelnicy) są niezadowoleni,​ ponieważ czasem z bazy odczytują nieaktualne lub bezsensowne dane. Ci drudzy (dalej: pisarze) także są niezadowoleni,​ ponieważ podczas oczekiwania na wprowadzenie poprawek do bazy, nic nie mogą robić. Rozwiązaniem tego problemu jest synchronizacja dostępu. Nie może być tak, że jednocześnie ktoś pisze do bazy i z niej czyta. Preferowani w takiej sytuacji będą pisarze. Ponadto założyłem Wyobraźmy sobie bazę danych (już istniejącą). Jedni użytkownicy mogą czytać z niej dane, a innni je zmieniać. Ci pierwsi (dalej: czytelnicy) są niezadowoleni,​ ponieważ czasem z bazy odczytują nieaktualne lub bezsensowne dane. Ci drudzy (dalej: pisarze) także są niezadowoleni,​ ponieważ podczas oczekiwania na wprowadzenie poprawek do bazy, nic nie mogą robić. Rozwiązaniem tego problemu jest synchronizacja dostępu. Nie może być tak, że jednocześnie ktoś pisze do bazy i z niej czyta. Preferowani w takiej sytuacji będą pisarze. Ponadto założyłem
 także, że na raz tylko jeden czytelnik korzysta z bazy. Co więcej, wprowadzamy rozdzielenie wywołania metody i jej wykonania, co pozwala pisarzom natychmiast przejść do innych zadań. także, że na raz tylko jeden czytelnik korzysta z bazy. Co więcej, wprowadzamy rozdzielenie wywołania metody i jej wykonania, co pozwala pisarzom natychmiast przejść do innych zadań.
 +
 +==== include'​y i stałe globalne ====
 <code cpp> <code cpp>
 #include <​queue>​ #include <​queue>​
Linia 19: Linia 22:
 boost::​mutex io_mutex; boost::​mutex io_mutex;
 </​code>​ </​code>​
 +---- 
 +===== Budowa "​aktywnego obiektu"​ =====
 Wzorzec "​aktywny obiekt"​ wykorzystuje następujące klasy: Wzorzec "​aktywny obiekt"​ wykorzystuje następujące klasy:
 **Proxy** - klasa widoczna dla programisty,​ która zawiera interfejs obiektu **Proxy** - klasa widoczna dla programisty,​ która zawiera interfejs obiektu
Linia 46: Linia 50:
 class Reader; class Reader;
 </​code>​ </​code>​
-Najpierw implementujemy ​bazę danych ​i metodyktóre będą na niej wywoływane.+===== Implementacja klas ===== 
 +==== Baza danych ==== 
 +Klasa reprezentująca faktyczną ​bazę danych, ​oraz implementująca metody ​na niej wywoływane
 <code cpp> <code cpp>
 class Database { class Database {
Linia 66: Linia 72:
 }; };
 </​code>​ </​code>​
-Teraz implementujemy klasę opakowującą wartości ​zwracane+==== Wartości zwracane ==== 
 +Klasa ta opakowuje wartość //int//, zwracaną przez funkcję //read//. Umożliwia ona automatyczną lecz blkującą konwersję na //int//, lub na pobranie ​wartości ​za pomocą funkcji, jeżeli ta jest już gotowa.
 <code cpp> <code cpp>
 class RetVal { class RetVal {
Linia 107: Linia 114:
 }; };
 </​code>​ </​code>​
-Następnie implementujemy ​żądanie wywołania metody. Zawiera ono funkcję ​**guard** służącą do zapewnienia spełnienia dodatkowych warunków synchronizacji,​ oraz **call**, wywołującą właściwą metodę+==== Żądanie ==== 
 +Implementujemy ​żądanie wywołania metody. Zawiera ono funkcję ​//guard// służącą do zapewnienia spełnienia dodatkowych warunków synchronizacji,​ oraz //call//, wywołującą właściwą metodę
 <code cpp> <code cpp>
 class Request { class Request {
Linia 153: Linia 161:
 }; };
 </​code>​ </​code>​
-Implementujemy planistę.+==== Planista ==== 
 +Planista odpowiadający za uszeregowanie metod, korzysta z wewnętrznej kolejki std::queue
 <code cpp> <code cpp>
 class Scheduler { class Scheduler {
Linia 217: Linia 226:
 }; };
 </​code>​ </​code>​
-I na koniec implementujemy proxy+==== Proxy ==== 
 +Klasa będąca interfejsem dla programisty. Tworzy ona żądania wywołania do metod, a do wątku wywołującego metodę natychmiast zwraca wartość.
 <code cpp> <code cpp>
 class DBProxy { class DBProxy {
Linia 244: Linia 254:
 DBProxy base; DBProxy base;
 </​code>​ </​code>​
-Implementuję ​pisarza i czytelnika+===== Przykład użycia ===== 
 + 
 +==== Pisarz i czytelnik ==== 
 +To prosta implementacja ​pisarza i czytelnika. Jedyne co robią to wpisują/​czytają dane z bazy i spią. Można jednak wyobrazić sobie jak np pisarz wymyśla dane (np wyszukuje), a czytelnik jakoś odczytane dane przetwarza. Każdy będzie wywoływał się w osobnym wątku. Do podziału na wątki wykorzystałem boost::​thread. Warto też zwrócić uwagę na utworzenie z wypisywania sekcji krytycznej i synchronizacji przy pomocy mutexa.
 <code cpp> <code cpp>
 class Writer { class Writer {
aktywny_obiekt.txt · ostatnio zmienione: 2008/04/15 20:43 przez krogala