diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
commit | e6918187568dbd01842d8d1d2c808ce16a894239 (patch) | |
tree | 64f88b554b444a49f656b6c656111a145cbbaa28 /src/boost/libs/statechart/example/PingPong/PingPong.cpp | |
parent | Initial commit. (diff) | |
download | ceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip |
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/statechart/example/PingPong/PingPong.cpp')
-rw-r--r-- | src/boost/libs/statechart/example/PingPong/PingPong.cpp | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/boost/libs/statechart/example/PingPong/PingPong.cpp b/src/boost/libs/statechart/example/PingPong/PingPong.cpp new file mode 100644 index 000000000..715ebf98b --- /dev/null +++ b/src/boost/libs/statechart/example/PingPong/PingPong.cpp @@ -0,0 +1,181 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright 2002-2008 Andreas Huber Doenni +// Distributed under the Boost Software License, Version 1.0. (See accompany- +// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +////////////////////////////////////////////////////////////////////////////// + + + +////////////////////////////////////////////////////////////////////////////// +// #define USE_TWO_THREADS // ignored for single-threaded builds +// #define CUSTOMIZE_MEMORY_MANAGEMENT +////////////////////////////////////////////////////////////////////////////// +// The following example program demonstrates the use of asynchronous state +// machines. First, it creates two objects of the same simple state machine +// mimicking a table tennis player. It then sends an event (the ball) to the +// first state machine. Upon reception, the first machine sends a similar +// event to the second state machine, which then sends the event back to the +// first machine. The two machines continue to bounce the event back and forth +// until one machine "has enough" and aborts the game. The two players don't +// "know" each other, they can only pass the ball back and forth because the +// event representing the ball also carries two boost::function objects. +// Both reference the fifo_scheduler<>::queue_event() function, binding the +// scheduler and the handle of the opponent. One can be used to return the +// ball to the opponent and the other can be used to abort the game. +// Depending on whether the program is compiled single-threaded or +// multi-threaded and the USE_TWO_THREADS define above, the two +// machines either run in the same thread without/with mutex locking or in two +// different threads with mutex locking. +////////////////////////////////////////////////////////////////////////////// + + +#include "Player.hpp" + +#include <boost/statechart/asynchronous_state_machine.hpp> +#include <boost/statechart/fifo_worker.hpp> + +#include <boost/mpl/list.hpp> +#include <boost/config.hpp> +#include <boost/intrusive_ptr.hpp> +#include <boost/function.hpp> +#include <boost/bind.hpp> + +#ifdef BOOST_HAS_THREADS +# include <boost/thread/thread.hpp> +#endif + +#include <iostream> +#include <ctime> + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std +{ + using ::clock_t; + using ::clock; +} +#endif + +#ifdef BOOST_INTEL +# pragma warning( disable: 304 ) // access control not specified +# pragma warning( disable: 383 ) // reference to temporary used +# pragma warning( disable: 981 ) // operands are evaluated in unspecified order +#endif + + + +namespace sc = boost::statechart; + + + +////////////////////////////////////////////////////////////////////////////// +const unsigned int noOfEvents = 1000000; + + +////////////////////////////////////////////////////////////////////////////// +char GetKey() +{ + char key; + std::cin >> key; + return key; +} + + +////////////////////////////////////////////////////////////////////////////// +int main() +{ + std::cout << "Boost.Statechart PingPong example\n\n"; + std::cout << "Threading configuration:\n"; + #ifdef BOOST_HAS_THREADS + std::cout << "Multi-threaded build with "; + #ifdef USE_TWO_THREADS + std::cout << 2; + #else + std::cout << 1; + #endif + std::cout << " thread(s).\n"; + #else + std::cout << "Single-threaded build\n"; + #endif + + std::cout << "\np<CR>: Performance test\n"; + std::cout << "e<CR>: Exits the program\n\n"; + + char key = GetKey(); + + while ( key != 'e' ) + { + switch( key ) + { + case 'p': + { + #ifdef BOOST_HAS_THREADS + MyScheduler scheduler1( true ); + #else + MyScheduler scheduler1; + #endif + + #ifdef USE_TWO_THREADS + #ifdef BOOST_HAS_THREADS + MyScheduler scheduler2( true ); + #else + MyScheduler & scheduler2 = scheduler1; + #endif + #else + MyScheduler & scheduler2 = scheduler1; + #endif + + MyScheduler::processor_handle player1 = + scheduler1.create_processor< Player >( noOfEvents / 2 ); + scheduler1.initiate_processor( player1 ); + MyScheduler::processor_handle player2 = + scheduler2.create_processor< Player >( noOfEvents / 2 ); + scheduler2.initiate_processor( player2 ); + + boost::intrusive_ptr< BallReturned > pInitialBall = new BallReturned(); + pInitialBall->returnToOpponent = boost::bind( + &MyScheduler::queue_event, &scheduler1, player1, _1 ); + pInitialBall->abortGame = boost::bind( + &MyScheduler::queue_event, + &scheduler1, player1, MakeIntrusive( new GameAborted() ) ); + + scheduler2.queue_event( player2, pInitialBall ); + + std::cout << "\nHaving players return the ball " << + noOfEvents << " times. Please wait...\n"; + + const unsigned int prevCount = Player::TotalNoOfProcessedEvents(); + const std::clock_t startTime = std::clock(); + + #ifdef USE_TWO_THREADS + #ifdef BOOST_HAS_THREADS + boost::thread otherThread( + boost::bind( &MyScheduler::operator(), &scheduler2, 0 ) ); + scheduler1(); + otherThread.join(); + #else + scheduler1(); + #endif + #else + scheduler1(); + #endif + + const std::clock_t elapsedTime = std::clock() - startTime; + std::cout << "Time to send and dispatch one event and\n" << + "perform the resulting transition: "; + std::cout << elapsedTime / static_cast< double >( CLOCKS_PER_SEC ) * + 1000000.0 / ( Player::TotalNoOfProcessedEvents() - prevCount ) + << " microseconds\n\n"; + } + break; + + default: + { + std::cout << "Invalid key!\n"; + } + } + + key = GetKey(); + } + + return 0; +} |