Fixed task start race condition
When the start_at
method is called, the statechart climbs into its initial state, then the active object starts a thread.
But, prior to this release, if the start_at
method caused calls to other methods which needed a task to run, the task would be started to honor the request of the call. This meant that the task would be started too soon, and the active object could send events to the HSM dispatcher, while it was still trying to climb into its initial state. Statecharts only run one event at a time, and starting a chart while having it react to events breaks the RTC protocol meaning that the statechart could behave non-deterministically .
Specifically, the bug fixed in this release would happen when a call to subscribe
, or publish
, or post_fifo
, or post_lifo
where made during the start-up process. The start_thread_if_not_running
decorator wrapped these calls so that they could work because they needed a thread to work. However it was a mistake to allow the thread to be started in more than one location in the code base. This bug has been fixed in this release and the start_thread_if_not_running
decorator has been removed so that the same mistake won't be made again.
There are situations when the subscribe
, or publish
, or post_fifo
, or post_lifo
calls will be made before the thread is started. These requests must be honored but they can be deferred till after the thread is started. To grant the client access to these features without a running thread, the post_fifo
and post_lifo
calls put their requests directly into the Active Object's queues so that they will be acted upon when the thread is started. To do the same for the publish
and subscribe
calls, two new meta signals (a signal which carries another signal) were invented. If a publish
method is called before a thread was started, an event with the signal named PUBLISH_META_SIGNAL
is posted using the post_lifo
technique into the Active Object's lifo queue. Inside of this event is enough information to publish an event with the required priority once the Active Object's thread started at a later time. A similar technique was followed to honor calls to subscribe
, it's signal name is SUBSCRIBE_META_SIGNAL
.
The ActiveObject's self.top
state was overloaded to catch the PUBLISH_META_SIGNAL
and SUBSCRIBE_META_SIGNAL
and dispatch them to private functions which work once the thread is running. To improve performance the publish
and subscribe
methods only publish events if no thread is running. If the thread is running they call thread related private functions directly, as they did before.
In addition to this change, a subscribed
method was added to the ActiveObject and ActiveFabric class. This method could be used to determine if a signal_name
or event
had been subscribed to for a given queue type (lifo/fifo).
Also, the stop_fabric
and stop_active_object
internal signals were renamed to STOP_FABRIC_SIGNAL
and STOP_ACTIVE_OBJECT_SIGNAL
to make their names consistent with other internal signal names.