Signals + Threads: Qt vs. Boost

Podobne dokumenty
Qt sygnały i sloty. Bogdan Kreczmer. Katedra Cybernetyki i Robotyki Wydział Elektroniki Politechnika Wrocławska

Qt sygnały i designer

Wprowadzenie do szablonów szablony funkcji

Szablony funkcji i szablony klas

Programowanie w środowiskach RAD QtCreator, Qt i C++

Wprowadzenie do szablonów szablony funkcji

Wprowadzenie do szablonów klas

The Graphics View Framework. Oprogramowanie i wykorzystanie stacji roboczych. Wykład 5. he Graphics View Framework - architektura

Kurs programowania. Wykład 9. Wojciech Macyna. 28 kwiecień 2016

Oprogramowanie i wykorzystanie stacji roboczych. Wykład 4

obiekty funkcyjne - funktory

Standard C++0x (C++1x?) Marcin Świderski

Qt - podstawowe cechy

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Programowanie w środowiskach RAD Qt i C++

Kurs programowania. Wykład 9. Wojciech Macyna

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Jzyk C++ cz 3. Jarosław Gramacki Instytut Informatyki i Elektroniki ( $)*)+' *, - ( ' )*'.' '',*/ *, ','*0) 1 / ) %*+ 2'' 2" ( $%%) )'20 )*0) 1 / )

Język C++ wykład VI. uzupełnienie notatek: dr Jerzy Białkowski. Programowanie C/C++ Język C++ wykład VI. dr Jarosław Mederski.

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Podstawy programowania w Qt4

Programowanie 2. Język C++. Wykład 3.

Zaawansowane programowanie w C++ (PCP)

Projektowanie klas c.d. Projektowanie klas przykład

Kurs programowania. Wykład 13. Wojciech Macyna. 14 czerwiec 2017

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

STL: implementowanie algorytmów C++: STL. STL: implementowanie algorytmów. STL: implementowanie algorytmów. STL: implementowanie algorytmów

Obsługa wyjątków. Język C++ WW12

Mechanizm sygnałów i slotów. Oprogramowanie i wykorzystanie stacji roboczych. Wykład 4. Sygnały i sloty - definicja klasy

Składnia C++ Programowanie Obiektowe, część 3 Mateusz Cicheński

STL: kontenery. STL: kontenery. STL: kontenery. Typy kontenerów STL. STL: kontenery. STL: kontenery. multimap. Kontener map: przykład zadanie:

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

Wątki. Definiowanie wątków jako klas potomnych Thread. Nadpisanie metody run().

Technologie programowania Wykład 4. Szablony funkcji Notes. Szablony funkcji Notes. Szablony funkcji Notes. Notes. Przemek Błaśkiewicz.

I - Microsoft Visual Studio C++

Wykład I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Wstęp do wiadomości teoretycznych (nie, nie jest to masło maślane ani wstęp, wstępów proszę cierpliwie czytać)

Operacje wejścia/wyjścia odsłona pierwsza

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

Zdalne wywołania procedur. Jarosław Kuchta Programowanie Współbieżne

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 28 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27

public: // interfejs private: // implementacja // składowe klasy protected: // póki nie będziemy dziedziczyć, // to pole nas nie interesuje

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Algorytmy i Struktury Danych. Anna Paszyńska

C++11. C++ 11 wybrane elementy. C++11: referencje do rvalue C++ 11: C++11: referencje do rvalue. C++11: referencje do rvalue. Referencje do rvalue

Wykład II. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Systemy wbudowane. Architektura środowiska SystemC. Wykład 8: SystemC zasady modelowania systemów wbudowanych

Technologie cyfrowe semestr letni 2018/2019

Programowanie w C++ Wykład 11. Katarzyna Grzelak. 13 maja K.Grzelak (Wykład 11) Programowanie w C++ 1 / 30

Język C++ wykład VIII

Modelowanie numeryczne w fizyce atmosfery Ćwiczenia 3

Technologie cyfrowe semestr letni 2018/2019

Laboratorium 1 Temat: Przygotowanie środowiska programistycznego. Poznanie edytora. Kompilacja i uruchomienie prostych programów przykładowych.

Szablony. Szablony funkcji

Języki programowania - podstawy

Kurs programowania. Wykład 3. Wojciech Macyna. 22 marca 2019

Wartości domyślne, szablony funkcji i klas

Curiously recurring template pattern

Wykład 1. Program przedmiotu. Programowanie (język C++) Literatura. Program przedmiotu c.d.:

Wykład 1. Program przedmiotu. Programowanie Obiektowe (język C++) Literatura. Program przedmiotu c.d.:

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Współbieżność i równoległość w środowiskach obiektowych. Krzysztof Banaś Obliczenia równoległe 1

Przeciążenie (przeładowanie nazw) funkcji

Programowanie i struktury danych

Qt - edycja, obsługa zdarzeń, rozmieszczenie kontrolek

Paradygmaty programowania. Paradygmaty programowania

TEMAT : KLASY POLIMORFIZM

Dzisiejszy wykład. Klasa string. wersja prosta wersja ze zliczaniem odwołań. Wyjątki Specyfikator volatile Semafory

1 Atrybuty i metody klasowe

Qt - dialogi. Bogdan Kreczmer. ZPCiR ICT PWR pokój 307 budynek C3

Zaawansowane programowanie w języku C++ Funkcje uogólnione - wzorce

Współbieżność w środowisku Java

Tablice i struktury. czyli złożone typy danych. Programowanie Proceduralne 1

Część 4 życie programu

Wstęp do programowania obiektowego. STL - Standard Template Library

Dzisiejszy wykład. Wzorce projektowe. Visitor Client-Server Factory Singleton

Java. Programowanie Obiektowe Mateusz Cicheński

Java. Wykład. Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ

Wprowadzenie do tworzenia zaawansowanych interfejsów graficznych: QGraphics View Framework vs. QML. Jakub Bogacz. Patryk Górniak

Na ekranie monitora zostaną wyświetlone w dwu liniach teksty Pierwsza linia Druga linia

Operacje wejścia/wyjścia (odsłona druga) - pliki

Programowanie w C++ Wykład 6. Katarzyna Grzelak. kwiecień K.Grzelak (Wykład 6) Programowanie w C++ 1 / 40

Programowanie obiektowe i C++ dla matematyków

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Wprowadzenie. Programowanie Obiektowe Mateusz Cicheński

Programowanie w języku C++

Wstęp do Programowania 2

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 7 maja K.Grzelak (Wykład 8) Programowanie w C++ 1 / 31

Środowisko programistyczne GEANT4

1. Pierwszy program. Kompilator ignoruje komentarze; zadaniem komentarza jest bowiem wyjaśnienie programu człowiekowi.

Programowanie Obiektowo Zorientowane w języku c++ Przestrzenie nazw

Programowanie Proceduralne

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Wstęp do programowania

FUNKCJE WZORCOWE. Wykład 10. Programowanie Obiektowe (język C++) Funkcje wzorcowe wprowadzenie (2) Funkcje wzorcowe wprowadzenie (1)

ECLIPSE wnioski z dwóch pierwszych laboratoriów

X Window System (I) Oprogramowanie i wykorzystanie stacji roboczych. Wykład 1. X Window System (III) X Window System (II)

W2 Wprowadzenie do klas C++ Klasa najważniejsze pojęcie C++. To jest mechanizm do tworzenia obiektów. Deklaracje klasy :

Transkrypt:

Signals + Threads: Qt vs. Boost Adam Bujalski 2014-04-01 Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 1 / 22

Spis Treści 1 2 Wątki 3 Qt::QueuedConnection w boost Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 2 / 22

Problem w ogólności Problem w ogólnośći Obie biblioteki stanowią implementację wzorca obserwator Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 3 / 22

Problem w ogólności Problem w ogólnośći Obie biblioteki stanowią implementację wzorca obserwator Obserwator Slot Obserwowany Sygnał Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 3 / 22

Problem w ogólności Problem w ogólnośći Obie biblioteki stanowią implementację wzorca obserwator Obserwator Slot Obserwowany Sygnał Obie biblioteki umożliwiają połączenia wiele do wiele Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 3 / 22

w Qt Łączenie sygnałów - Qt Qt4 QObject :: connect (&a, SIGNAL ( asignal ( int )), &d, SLOT ( bslot ( int ))); d. connect (&a, SIGNAL ( asignal ( int )), SLOT ( dslot ( int ))); Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 4 / 22

w Qt Łączenie sygnałów - Qt Qt4 QObject :: connect (&a, SIGNAL ( asignal ( int )), &d, SLOT ( bslot ( int ))); d. connect (&a, SIGNAL ( asignal ( int )), SLOT ( dslot ( int ))); // Koniecznie w pliku naglowkowym class A : public QObject { signals : asignal ( int ); // bez ciala metody }; class D : public QObject { public slots : dslot ( int ); }; Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 4 / 22

w Qt Łączenie sygnałów - Qt Qt5 QObject :: connect (&a, &A:: asignal ( int ), &d, &D:: dslot ( int )); void somefunction (); QObject :: connect ( button, & QPushButton :: clicked, this, somefunction, Qt :: QueuedConnection ); Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 5 / 22

w Qt Łączenie sygnałów - Qt Qt5 QObject :: connect (&a, &A:: asignal ( int ), &d, &D:: dslot ( int )); void somefunction (); QObject :: connect ( button, & QPushButton :: clicked, this, somefunction, Qt :: QueuedConnection ); Dodatkowo w Qt5 zmienił się typ zwracny przez metody QObject::connect Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 5 / 22

w Qt Łączenie sygnałów - Qt Qt5 QObject :: connect (&a, &A:: asignal ( int ), &d, &D:: dslot ( int )); void somefunction (); QObject :: connect ( button, & QPushButton :: clicked, this, somefunction, Qt :: QueuedConnection ); Dodatkowo w Qt5 zmienił się typ zwracny przez metody QObject::connect W Qt4 był to bool Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 5 / 22

w Qt Łączenie sygnałów - Qt Qt5 QObject :: connect (&a, &A:: asignal ( int ), &d, &D:: dslot ( int )); void somefunction (); QObject :: connect ( button, & QPushButton :: clicked, this, somefunction, Qt :: QueuedConnection ); Dodatkowo w Qt5 zmienił się typ zwracny przez metody QObject::connect W Qt4 był to bool W Qt5 jest to QMetaObject::Connection Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 5 / 22

w Qt Typy połączeń Enum Qt::ConnectionType określa sposób w jaki zostanie wywołany slot obsługujący dany sygnał. Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 6 / 22

w Qt Typy połączeń Enum Qt::ConnectionType określa sposób w jaki zostanie wywołany slot obsługujący dany sygnał. Możliwe są następujące wartości: Stała Wartość Qt::AutoConnection 0 Qt::DirectConnection 1 Qt::QueuedConnection 2 Qt::BlockingQueuedConnection 3 Qt::UniqueConnection 0x80 Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 6 / 22

w boost Sygnały w boost void slotfun ( int ); struct CSlot { void operator () ( int ); void aslot ( int ); } aslot ; Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 7 / 22

w boost Sygnały w boost void slotfun ( int ); struct CSlot { void operator () ( int ); void aslot ( int ); } aslot ; boost :: signals2 :: signal < void ( int )> asig ; boost :: signals2 :: connection c = asig. connect ( slotfun ); Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 7 / 22

w boost Sygnały w boost void slotfun ( int ); struct CSlot { void operator () ( int ); void aslot ( int ); } aslot ; boost :: signals2 :: signal < void ( int )> asig ; boost :: signals2 :: connection c = asig. connect ( slotfun ); asig. connect ( aslot ); // aslot jest kopiowany asig. connect ( boost :: bind (& CSlot :: aslot, & aslot, _1)); Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 7 / 22

w boost Emisja sygnału Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 8 / 22

w boost Emisja sygnału Qt emit voidsignal (); emit asignal (25) ; Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 8 / 22

w boost Emisja sygnału Qt emit voidsignal (); emit asignal (25) ; boost voidsignal (); asig (25) ; Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 8 / 22

w boost combiner w boost Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 9 / 22

w boost combiner w boost W Qt wartości zwracane przez sloty wywołane podczas obsługi sygnału są ignorowane. Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 9 / 22

w boost combiner w boost W Qt wartości zwracane przez sloty wywołane podczas obsługi sygnału są ignorowane. W boost można podać jako argument sygnału combiner, który umożliwia dowolne połączenie wartości zwracanych przez sloty. Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 9 / 22

w boost combiner w boost W Qt wartości zwracane przez sloty wywołane podczas obsługi sygnału są ignorowane. W boost można podać jako argument sygnału combiner, który umożliwia dowolne połączenie wartości zwracanych przez sloty. Domyślnie boost::optional z wartością zwróconą przez ostatni wywoływany slot. Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 9 / 22

w boost Przykładowy combiner // aggregate_ values is a combiner which places all // the values returned from slots into a container template < typename Container > struct aggregate_ values { template < typename InputIterator > Container operator ()( InputIterator first, InputIterator last ) const { Container values ; for (; first!= last ; ++ first ) values. push_ back (* first ); // * first wywola slot return values ; } }; Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 10 / 22

w boost Przykładowy combiner // aggregate_ values is a combiner which places all // the values returned from slots into a container template < typename Container > struct aggregate_ values { template < typename InputIterator > Container operator ()( InputIterator first, InputIterator last ) const { Container values ; for (; first!= last ; ++ first ) values. push_ back (* first ); // * first wywola slot return values ; } }; boost :: signals2 :: signal < float ( float, float ), aggregate_ values < std :: vector < float > > > sig ; Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 10 / 22

w boost Przykładowy combiner // aggregate_ values is a combiner which places all // the values returned from slots into a container template < typename Container > struct aggregate_ values { template < typename InputIterator > Container operator ()( InputIterator first, InputIterator last ) const { Container values ; for (; first!= last ; ++ first ) values. push_ back (* first ); // * first wywola slot return values ; } }; boost :: signals2 :: signal < float ( float, float ), aggregate_ values < std :: vector < float > > > sig ; std :: vector < float > results = sig (5, 3); Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 10 / 22

Wątki Spis Treści 1 2 Wątki 3 Qt::QueuedConnection w boost Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 11 / 22

Wątki Wątki w boost Wątki w boost - wynik programu [7f251f24e700] Hello from thread() [7f251f250780] Hello from run_thread1() [7f251f250780] Hello from run_thread2() [7f251f24e700] Hello from thread() Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 12 / 22

Wątki Wątki w boost Wątki w boost - program # define LOG std :: cout << "[" \ << boost :: this_ thread :: get_id () \ << "] " void thread () { LOG << " Hello from thread ()" << std :: endl ; } void run_ thread1 () { boost :: thread t( thread ); t. join (); LOG << " Hello from run_ thread1 ()" << std :: endl ; } Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 13 / 22

Wątki Wątki w boost Wątki w boost - program c.d. void run_ thread2 () { boost :: thread t( thread ); // wg. dokumentacji jest thread_ joiner // ale w 1.54 nie ma takiej klasy... boost :: thread_guard <> g( t); LOG << " Hello from run_ thread2 ()" << std :: endl ; } int main () { run_thread1 (); run_thread2 (); return 0; } Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 14 / 22

Wątki Wątki w Qt Wątki w Qt - hello_thread.h # include < QThread > # include < QDebug > # include < iostream > # define LOG qdebug () << "[" \ << QThread :: currentthread () << "]" class HelloThread : public QThread { Q_ OBJECT protected : virtual void run () { LOG << " HelloThread "; } }; Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 15 / 22

Wątki Wątki w Qt Wątki w Qt - program główny # include < QCoreApplication > # include < hello_thread.h> int main ( int argc, char * argv []) { QCoreApplication a( argc, argv ); HelloThread t; t. start (); LOG << " GUI / Main Thread "; t. wait (); } return 0; Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 16 / 22

Wątki Wątki w Qt Wątki w Qt - wyjście programu [ QThread(0x9fe1a0) ] GUI/Main Thread [ HelloThread(0x7fff646c9ed0) ] HelloThread Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 17 / 22

Wątki Synchronizacja Synchronizacja - prymitywy Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 18 / 22

Wątki Synchronizacja Synchronizacja - prymitywy Obie biblioteki udostępniają podobny zestaw prymitywów do synchronizacji Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 18 / 22

Wątki Synchronizacja Synchronizacja - prymitywy Obie biblioteki udostępniają podobny zestaw prymitywów do synchronizacji boost Qt mutex QMutex timed_mutex recursive_mutex QMutex(QMutex::Recursive) recursive_timex_mutex shared_mutex QReadWriteLock upgradable_mutex QSemaphore condition_variable[_any] QWaitCondition Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 18 / 22

Wątki Synchronizacja Synchronizacja - prymitywy Obie biblioteki udostępniają podobny zestaw prymitywów do synchronizacji boost Qt mutex QMutex timed_mutex recursive_mutex QMutex(QMutex::Recursive) recursive_timex_mutex shared_mutex QReadWriteLock upgradable_mutex QSemaphore condition_variable[_any] QWaitCondition Dodatkowo w obu bibliotekach dostępne są mechanizmy RAII do odpowiedniego zajmownaia zasobów. Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 18 / 22

Wątki QtRunable/QThreadPool i QtConcurent Wątki w Qt - inne opcje Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 19 / 22

Wątki QtRunable/QThreadPool i QtConcurent Wątki w Qt - inne opcje W Qt można korzystać z wielowątkowości wykorzystując dodatkowe mechanizmy, które w bardziej automatyczny sposób zarządają wątkami, Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 19 / 22

Wątki QtRunable/QThreadPool i QtConcurent Wątki w Qt - inne opcje W Qt można korzystać z wielowątkowości wykorzystując dodatkowe mechanizmy, które w bardziej automatyczny sposób zarządają wątkami, Mechanizm QThreadPool w połączeniu z QRunnable Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 19 / 22

Wątki QtRunable/QThreadPool i QtConcurent Wątki w Qt - inne opcje W Qt można korzystać z wielowątkowości wykorzystując dodatkowe mechanizmy, które w bardziej automatyczny sposób zarządają wątkami, Mechanizm QThreadPool w połączeniu z QRunnable Ale ciągle wymaga on ręcznego ustalania ilości wątków do uruchomienia, Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 19 / 22

Wątki QtRunable/QThreadPool i QtConcurent Wątki w Qt - inne opcje W Qt można korzystać z wielowątkowości wykorzystując dodatkowe mechanizmy, które w bardziej automatyczny sposób zarządają wątkami, Mechanizm QThreadPool w połączeniu z QRunnable Ale ciągle wymaga on ręcznego ustalania ilości wątków do uruchomienia, Wysokopoziomowy QtConcurent, który samodzielnie dostosowuje ilość wątków do ilości procesorów w systemie i udostępnia funkcyjne API MapReduce i FilterReduce. Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 19 / 22

Wątki QtRunable/QThreadPool i QtConcurent MapReduce w Qt - map typedef QMap < QString, int > WordCount ; // countwords counts the words in a single file. // This function is called in parallel by several // threads and must be thread safe. WordCount countwords ( const QString & file ) { QFile f( file ); f. open ( QIODevice :: ReadOnly ); QTextStream textstream (& f); WordCount wordcount ; while ( textstream. atend () == false ) foreach ( QString word, textstream. readline (). split (" ")) wordcount [ word ] += 1; } return wordcount ; Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 20 / 22

Wątki QtRunable/QThreadPool i QtConcurent MapReduce w Qt - reduce // reduce adds the results from map to the final result. // This functor will only be called by one thread // at a time. void reduce ( WordCount & result, const WordCount & w) { QMapIterator < QString, int > i(w); while (i. hasnext ()) { i. next (); result [i. key ()] += i. value (); } } QStringList files = findfiles (/*... */); WordCount total = mappedreduced ( files, countwords, reduce ); Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 21 / 22

Qt::QueuedConnection w boost Na koniec Qt::QueuedConnection w boost Adam Bujalski Signals + Threads: Qt vs. Boost 2014-04-01 22 / 22