boost::statechart - two async machines in one process?
I've been using asynchronous boost::statechart for 5+ years but that doesn't seem to count for much in this instance. I've wrapped myself around the axel and have no idea how to proceed. Any help would be greatly appreciated. I am attempting to create a program that contains two separate classes, each built on a boost::statechart state machine. The classes are similar but there is one-and-only-one class a and it creates instances of class b. At least, that was the plan. (Apologies if this diagram doesn't format correctly. Outlook is NOT being cooperative.) _______________________ ________________________ | boost::statechart | | boost::statechart | |______________________| |________________________| ^ ^ _________|______________ _________|______________ | struct a_statechart | | struct b_statechart | |_______________________| |_______________________| | | _________O____________ __________O___________ | struct a_impl | | struct b_impl | |----------------------------------| |-----------------------------------| | fifo_scheduler sched_ | | fifo_scheduler sched_ | | processor_handle asm_ | | processor_handle bsm_ | | boost::thread thread_ | | boost::thread thread_ | |_____________________| |______________________| | | _________o____________ _________o____________ | struct a | | struct b | |_____________________| |______________________| However, if the class b processor_handle (bsm_) is initialized, the class a state machine doesn't react to *any* events. If I comment out the bsm_ initialization, the class a state machine handles events as expected. If bsm_ is initialized (with our without creating the thread), the class a state machine doesn't respond to any event. The results are exactly the same if bsm_ is assigned in the ctor. Both asm_ and bsm_ are initialized in the ?_impl ctor: [usual stuff]: sched_(true), ?sm_( sched_.create_processor< ?_statechart >() ), thread_() { FWIW, The state machines in both classes are assigned a thread in the ?_impl ctor: boost::thread tmp( bind( &fifo_scheduler<>::operator(), &sched_, 0 ) ); thread_.swap( tmp ); Any assistance will be greatly appreciated. Regards, Dick Bridges The opinions and data in this missive are my own and do not necessarily represent the positions, strategies, or opinions of Western Digital Corporation. IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses. Glenda: http://glenda.cat-v.org/gallery/
Hi Dick
Any assistance will be greatly appreciated.
I don't see why the machines should behave as you describe. Can you please post a repro? Thanks & Regards, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.
-----Original Message----- From: Boost-users [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Andreas Huber Sent: Monday, February 25, 2013 11:43 AM To: boost-users@lists.boost.org Subject: Re: [Boost-users] boost::statechart - two async machines in one process?
[snip] I don't see why the machines should behave as you describe. Can you please post a repro?
Thanks & Regards, Andreas Huber
Happy Thursday Andreas,
Apologies in advance for all the code. Simply not sure where the hints may be found.
When the offending line (the_many_impl.cpp, [.create_processor]) is
removed, react(the_one_init) occurs. When line 14 is restored, the
react() does not occur (i.e., program appears to be hung).
./exemplar
the_many_impl ctor.
the_many_impl queued the the_many_init event.
the_one_impl ctor.
the_one_impl queued the the_one_init event.
waiting for a keystroke.
the_one_state_machine ctor.
the_one_state_machine::initiate_impl()
the_one installed_state ctor.
the_one installed_state::react(the_one_init) <-- with [.create_processor] disabled
k ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
returning from main.
~the_one_impl dtor.
exemplar: /xtools/boost/i686-pc-linux-gnu/boost_1_51_0/
include/boost/thread/pthread/condition_variable.hpp:133:
boost::condition_variable_any::~condition_variable_any():
Assertion `!pthread_mutex_destroy(&internal_mutex)' failed.
Aborted
file: the_one.hpp
//^^^^^^^^^^^^^^^
#if !defined(THE_ONE_HPP_26D4F573_E462_4863_A730_79E1A8B28639)
#define THE_ONE_HPP_26D4F573_E462_4863_A730_79E1A8B28639
#include <memory>
namespace western_digital {
class the_one_impl;
class the_one {
public:
the_one();
virtual
~the_one();
private:
std::unique_ptr< the_one_impl > impl_;
}; // class the_one
} // namespace western_digital
#endif // THE_ONE_HPP_26D4F573_E462_4863_A730_79E1A8B28639
file: the_one.cpp
//^^^^^^^^^^^^^^^
#include <string>
#include "the_one/the_one.hpp"
#include "the_one/the_one_impl.hpp"
namespace fw = western_digital;
fw::the_one::the_one() : impl_( new fw::the_one_impl() ) {}
fw::the_one::~the_one() {}
file: the_one_impl.hpp
//^^^^^^^^^^^^^^^^^^^^
#if !defined(THE_ONE_IMPL_HPP_EA676320_C9EC_4A09_BCA4_DF5E40FDC262)
#define THE_ONE_HPP_EA676320_C9EC_4A09_BCA4_DF5E40FDC262
#include <memory>
#include <string>
#include <iostream>
#include "the_one/the_one_state_machine.hpp"
namespace sc = boost::statechart;
namespace mpl = boost::mpl;
namespace western_digital {
class the_one_impl {
public:
the_one_impl();
virtual
~the_one_impl() {
std::cout << "~the_one_impl dtor." << std::endl;
}
the_one_scheduler_t the_one_scheduler_;
sc::fifo_scheduler<>::processor_handle sm_;
boost::thread the_one_thread_;
}; // class the_one_impl
} // western_digital
#endif // #if !defined(THE_ONE_IMPL_HPP_EA676320_C9EC_4A09_BCA4_DF5E40FDC262)
file: the_one_impl.cpp
//^^^^^^^^^^^^^^^^^^^^
#include "the_one/the_one_impl.hpp"
namespace fw = western_digital;
fw::the_one_impl::the_one_impl() :
the_one_scheduler_(true), sm_( the_one_scheduler_.create_processor< fw::the_one_state_machine_t >() ),
the_one_thread_()
{
std::cout << "the_one_impl ctor." << std::endl;
the_one_scheduler_.initiate_processor( sm_ );
the_one_scheduler_.queue_event( sm_, MakeIntrusive( new fw::the_one_init() ) );
std::cout << "the_one_impl queued the the_one_init event." << std::endl;
boost::thread temp_thread( boost::bind( &sc::fifo_scheduler<>::operator(), &the_one_scheduler_, 0 ) );
the_one_thread_.swap( temp_thread );
}
file: the_one_state_machine.hpp
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#if !defined(THE_ONE_STATE_MACHINE_HPP_CE0C147D_8C95_4EAB_B7BD_6C527E9332F5)
#define THE_ONE_STATE_MACHINE_HPP_CE0C147D_8C95_4EAB_B7BD_6C527E9332F5
#include <stdexcept>
#include
Hi Dick I've tried to reproduce the problem with the code you have sent me by private email. For starters, I get exactly the same output whether or not line 14 in the_many_impl.cpp is commented out or not. I can't say I've fully understood your code, but it seems as though the state classes for both state machines have the same names and are declared in the same namespace, which would result in an ODR violation. It seems the linker should complain, so it might well be that I'm missing something. For now, may I ask you to give the state classes for the two machines different names and see whether that resolves the problem? If not, please let me know. Regards, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.
participants (2)
-
Andreas Huber
-
Dick Bridges