summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/statechart/example/PingPong/PingPong.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
commite6918187568dbd01842d8d1d2c808ce16a894239 (patch)
tree64f88b554b444a49f656b6c656111a145cbbaa28 /src/boost/libs/statechart/example/PingPong/PingPong.cpp
parentInitial commit. (diff)
downloadceph-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.cpp181
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;
+}