Najwyraźniej boost zawiera dwie oddzielne biblioteki dla maszyn stanowych: Statechart i Meta State Machine (MSM). Slogany podają bardzo podobne opisy:
- Boost.Statechart - Dowolnie złożone maszyny o skończonych stanach można zaimplementować w czytelnym i łatwym w utrzymaniu kodzie C ++.
- Meta State Machine - bardzo wydajna biblioteka dla ekspresyjnych maszyn skończonych UML2.
Czy wiesz, jakie są kluczowe różnice i jakie należy wziąć pod uwagę przy wyborze między nimi?
c++
boost
state-machine
boost-statechart
boost-msm
FireAphis
źródło
źródło
Odpowiedzi:
Ponieważ wydaje się, że zainteresowanie jest duże, pozwolę sobie na wyrażenie mojej (oczywiście stronniczej) opinii, którą należy zatem przyjąć z przymrużeniem oka:
Możesz wyrobić sobie lepszą opinię, szukając komentarzy zamieszczonych podczas recenzji MSM. Ten temat był szeroko omawiany na liście deweloperów.
źródło
Jak już wspomniał Christophe, jedną z kluczowych różnic między tymi dwiema bibliotekami jest wydajność w czasie wykonywania. Chociaż MSM prawdopodobnie oferuje najlepsze, co możesz tutaj uzyskać, Statechart świadomie zamienia cykle pamięci i procesora na lepszą skalowalność.
Dzięki Boost.Statechart możesz rozłożyć układ (tj. Stany, przejścia) swojego automatu stanów na wiele jednostek tłumaczeniowych (pliki cpp) w sposób, w jaki nie jest to możliwe w przypadku MSM. Pozwala to na łatwiejsze w utrzymaniu implementację dużych FSM i uzyskanie znacznie szybszej kompilacji niż w przypadku MSM.
Często łatwo odpowiedzieć na pytanie, czy narzut wydajności Statechart w porównaniu z MSM będzie istotny dla Twojej aplikacji, gdy zadasz sobie pytanie, ile zdarzeń będzie musiała przetworzyć Twoja aplikacja na sekundę.
Zakładając umiarkowanie złożony FSM zaimplementowany z Boost.Statechart, oto kilka liczb:
Jeśli chodzi o obciążenie procesora, jeśli liczba zdarzeń do przetworzenia jest znacznie niższa niż te liczby, obciążenie Boost.Statechart w porównaniu z MSM prawie na pewno nie będzie zauważalne. Jeśli liczba jest znacznie wyższa, zdecydowanie lepiej jest z MSM.
Więcej szczegółowych informacji na temat kompromisów między wydajnością a skalowalnością można znaleźć tutaj: http://www.boost.org/doc/libs/1_45_0/libs/statechart/doc/performance.html
źródło
Podczas kodowania własnej implementacji PPP użyłem Statechart z trzech powodów: 1) Statechart jest prostszy i ma bardziej przejrzystą dokumentację; 2) Naprawdę nie lubię UML :)
Dokumentacja Boost mówi, że MSM jest co najmniej 20 razy szybszy, ale kompiluje się dość wolno dla dużych FSM.
źródło
Jakiś czas temu zacząłem od Statechart i przeniosłem się na MSM, ponieważ łatwiej było go używać w połączeniu z asio z jednego wątku. Nie udało mi się połączyć Statechart i jego możliwości wielowątkowych przy użyciu asio - było to prawdopodobnie jakieś niezrozumienie Statechart przez początkujących. Odkryłem, że MSM jest łatwiejszy w użyciu, ponieważ nie dotyczy wielowątkowości.
źródło
W odpowiedzi na późne wejście Tima do dyskusji (która dotyczy również jednego z bardzo wczesnych komentarzy Lwa).
Jako jeden z tych, którzy argumentowali za separacją wyjścia od destruktorów w statechart (argument oparty na prawdziwym przypadku użycia, o interakcji z rzeczywistym światem, tj. I / O) dawno temu, kiedy został przesłany do Boost, zgadzam się, że mogą wystąpić problemy z umieszczeniem wyjścia logika w destruktorach. Nie jest zaskakujące, że David Abrahams przedstawił przekonujące argumenty dotyczące również bezpieczeństwa wyjątków. Z tych powodów Statechart nie wymaga umieszczania logiki w destruktorach - ale pozwala - zgodnie ze zwykłymi radami.
Logika, która powinna zawsze działać tylko jako część przejścia ze stanu (a nie zniszczenia obiektu stanu stanu jako całości), może (i powinna, jeśli trzeba wykonać również czyszczenie zasobów), zostać rozdzielona na osobną akcję exit ().
W przypadku „cienkiego” stanu bez aktywnego stanu (zasobów), wystarczy wykonać akcje wejścia / wyjścia, możesz wykonać te akcje w ctor i d'tor i upewnić się, że konstruktor i destruktor nie rzucają. Nie ma powodu, aby - nie ma stanu, na którym mógłby wykonać RAII - nie ma nic złego w tym, że obsługa błędów w tych miejscach wywołuje odpowiednie zdarzenia. Nadal może być konieczne rozważenie, czy chcesz, aby akcje wyjścia, które zmieniają stan zewnętrzny, były uruchamiane po zniszczeniu automatu stanowego ... i umieść je w akcji wyjścia, jeśli nie chcesz, aby występowały w tym przypadku ...
Statechart modeluje aktywację jako instancję obiektu, więc jeśli twój konstruktor ma do wykonania rzeczywistą pracę / aktywację / instancję i jest w stanie zawieść, tak że stan nie może zostać wprowadzony, Statechart obsługuje to, dając ci możliwość zmapowania wyjątku do zdarzenie. Jest to obsługiwane w sposób, który działa w górę hierarchii stanów w poszukiwaniu stanu zewnętrznego, który obsługuje zdarzenie wyjątku, analogicznie do sposobu, w jaki stos zostałby rozwinięty w modelu wywołania opartym na stosie wywołań.
To wszystko jest dobrze udokumentowane - sugeruję przeczytanie dokumentacji i wypróbowanie tego. Sugeruję, abyś używał destruktorów do czyszczenia „zasobów oprogramowania” i akcji wyjścia w celu wykonania „akcji wyjścia w świecie rzeczywistym”.
Warto zauważyć, że propagacja wyjątków jest pewnym problemem we wszystkich środowiskach sterowanych zdarzeniami, a nie tylko w wykresach stanu. Najlepiej jest rozważać i uwzględniać błędy / błędy w projekcie swojego wykresu stanu i wtedy i tylko wtedy, gdy nie możesz sobie z nimi poradzić w inny sposób, skorzystaj z mapowania wyjątków. Przynajmniej to działa dla mnie - ymmmv ....
źródło