Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
EventIdentifyGlobal.hxx
Go to the documentation of this file.
1
35#ifndef _OPENLCB_EVENTIDENTIFYGLOBAL_HXX_
36#define _OPENLCB_EVENTIDENTIFYGLOBAL_HXX_
37
38#include "openlcb/If.hxx"
39#include "utils/Atomic.hxx"
40
41namespace openlcb
42{
43
53{
54public:
70
78
82 void arm(bool delete_self = false)
83 {
84 AtomicHolder h(this);
85 if (is_terminated())
86 {
87 aborted_ = false;
88 deleteSelf_ = delete_self;
90 }
91 }
92
93private:
97 {
98 msg->unref();
99 AtomicHolder h(this);
100 aborted_ = true;
101 }
102
105 {
106 // get a pseudo random number between 1.500 and 2.011 seconds
107 uint64_t h = node_->node_id() * 0x1c19a66d;
108 uint32_t hh = h ^ (h >> 32);
109 hh = hh ^ (hh >> 12) ^ (hh >> 24);
110 long long timeout_msec = 1500 + (hh & 0x1FF);
111
112 return sleep_and_call(
113 &timer_, MSEC_TO_NSEC(timeout_msec), STATE(timeout));
114 }
115
118 {
119 {
120 // Making the state flow termination atomic cleans up a potential
121 // race condition with an arm() call coming in after the if
122 // statement but before the StateFlowBase::exit() call.
123 AtomicHolder h(this);
124 if (aborted_)
125 {
126 // no need to send Event Identify Global, already detected one
127 return deleteSelf_ ? delete_this() : exit();
128 }
129 }
130
131 if (!node_->is_initialized())
132 {
133 // node not initialized yet, try again later
135 }
136
137 // allocate a buffer for the Event Identify Global message
138 return allocate_and_call(
140 }
141
144 {
145 auto *b = get_allocation_result(
146 node_->iface()->global_message_write_flow());
147 b->data()->reset(
149 node_->iface()->global_message_write_flow()->send(b);
150
151 return deleteSelf_ ? delete_this() : exit();
152 }
153
155 MessageHandler::GenericHandler eventIdentifyGlobalHandler_;
158 uint8_t aborted_ : 1;
159 uint8_t deleteSelf_ : 1;
160};
161
162} // namespace openlcb
163
164#endif // _OPENLCB_EVENTIDENTIFYGLOBAL_HXX_
#define STATE(_fn)
Turns a function name into an argument to be supplied to functions expecting a state.
Definition StateFlow.hxx:61
See OSMutexLock in os/OS.hxx.
Definition Atomic.hxx:153
Lightweight locking class for protecting small critical sections.
Definition Atomic.hxx:130
Base class for all QMember types that hold data in an expandable format.
Definition Buffer.hxx:195
void unref()
Decrement count.
Definition Buffer.hxx:675
void register_handler(HandlerType *handler, ID id, ID mask)
Adds a new handler to this dispatcher.
void unregister_handler(HandlerType *handler, ID id, ID mask)
Removes a specific instance of a handler from this dispatcher.
virtual void send(MessageType *message, unsigned priority=UINT_MAX)=0
Entry point to the flow.
Return type for a state flow callback.
Use this timer class to deliver the timeout notification to a stateflow.
Base class for state machines.
bool is_terminated()
Action allocate_and_call(FlowInterface< Buffer< T > > *target_flow, Callback c, Pool *pool=nullptr)
Allocates a buffer from a pool and proceed to the next state when allocation is successful.
Action delete_this()
Terminates the flow and deletes *this.
Action exit()
Terminate current StateFlow activity.
void start_flow(Callback c)
Resets the flow to the specified state and starts it.
Buffer< T > * get_allocation_result(FlowInterface< Buffer< T > > *target_flow)
Takes the result of the asynchronous allocation.
Action call_immediately(Callback c)
Imediately call the next state upon return.
Action sleep_and_call(::Timer *timer, long long timeout_nsec, Callback c)
Suspends execution of this control flow for a specified time.
Helper object for producing an Event Identify Global message.
StateFlowTimer timer_
timer object for handling the timeout
uint8_t deleteSelf_
delete object upon state flow exit (one-shot)
EventIdentifyGlobal(Node *node)
Constructor.
Node * node_
node to send message from
void handle_incoming_event_identify_global(Buffer< GenMessage > *msg)
Callback upon receiving a Defs::MTI_EVENTS_IDENTIFY_GLOBAL message.
void arm(bool delete_self=false)
Arm the EventIdentifyGlobal request.
MessageHandler::GenericHandler eventIdentifyGlobalHandler_
handler for incoming messages
Action fill_buffer()
Fill in allocated buffer and send Event Identify Global message.
uint8_t aborted_
true if message received, abort need to send
Action timeout()
Will be called on the executor of the timer.
Action entry()
Entry/reset point into state machine.
MessageHandler * global_message_write_flow()
Definition If.hxx:200
MessageDispatchFlow * dispatcher()
Definition If.hxx:224
Base class for NMRAnet nodes conforming to the asynchronous interface.
Definition Node.hxx:52
virtual bool is_initialized()=0
string EMPTY_PAYLOAD
A global class / variable for empty or not-yet-initialized payloads.
Definition If.cxx:152
#define MSEC_TO_NSEC(_msec)
Convert a millisecond value to a nanosecond value.
Definition os.h:268
@ MTI_EVENTS_IDENTIFY_GLOBAL
request identify all of every node's events
@ MTI_EXACT
match mask for a single MTI