Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
NodeInitializeFlow.hxx
1
35#ifndef _OPENLCB_NODEINITIALIZEFLOW_HXX_
36#define _OPENLCB_NODEINITIALIZEFLOW_HXX_
37
39#include "openlcb/If.hxx"
40#include "nmranet_config.h"
41#include "utils/Singleton.hxx"
42
43namespace openlcb
44{
45
49{
51 : node(nullptr)
52 {
53 }
54 Node *node;
55};
56
58
65 public Singleton<InitializeFlow>
66{
67public:
70 {
71 }
72
74
75private:
76 Node *node()
77 {
78 return message()->data()->node;
79 }
80
82 {
83 if (!node())
84 {
85 return release_and_exit();
86 }
87 HASSERT(message()->data()->node);
88 return allocate_and_call(
89 node()->iface()->global_message_write_flow(),
90 STATE(send_initialized));
91 }
92
93 Action send_initialized()
94 {
95 auto *b = get_allocation_result(
96 node()->iface()->global_message_write_flow());
97 done_.reset(this);
98 NodeID id = node()->node_id();
99 b->data()->reset(
101 b->data()->set_flag_dst(GenMessage::WAIT_FOR_LOCAL_LOOPBACK);
102 b->set_done(&done_);
103 node()->iface()->global_message_write_flow()->send(
104 b, b->data()->priority());
105 return wait_and_call(STATE(initialization_complete));
106 }
107
108 Action initialization_complete()
109 {
110 node()->set_initialized();
111 return call_immediately(STATE(identify_events));
112 }
113
114 Action identify_events()
115 {
116 if (config_node_init_identify() != CONSTANT_TRUE)
117 {
118 return release_and_exit();
119 }
120 // Get the dispatch flow.
121 return allocate_and_call(
122 node()->iface()->dispatcher(), STATE(initiate_local_identify));
123 }
124
125 Action initiate_local_identify()
126 {
127 auto *b = get_allocation_result(node()->iface()->dispatcher());
128 b->set_done(done_.reset(this));
129 GenMessage *m = b->data();
131 m->payload.clear();
132 m->dst.id = node()->node_id();
133 m->dstNode = node();
134 m->src.alias = 0;
135 m->src.id = node()->node_id();
136 node()->iface()->dispatcher()->send(b, b->data()->priority());
137 return wait_and_call(STATE(wait_for_local_identify));
138 }
139
140 Action wait_for_local_identify()
141 {
142 return release_and_exit();
143 }
144
145 BarrierNotifiable done_;
146};
147
150void StartInitializationFlow(Node *node);
151
157public:
158 ReinitAllNodes(If* iface) : StateFlowBase(iface) {
159 nextNode_ = iface->first_local_node();
160 start_flow(STATE(allocate_entry));
161 }
162
163private:
164 Action allocate_entry() {
165 if (!nextNode_) {
166 return delete_this();
167 }
168 return allocate_and_call(tgt(), STATE(send_init_request));
169 }
170
171 Action send_init_request() {
172 auto* b = get_allocation_result(tgt());
173 b->data()->node = nextNode_;
174 b->set_done(bn_.reset(this));
175 tgt()->send(b);
176 return wait_and_call(STATE(init_done));
177 }
178
179 Action init_done() {
180 nextNode_ = iface()->next_local_node(nextNode_->node_id());
181 return call_immediately(STATE(allocate_entry));
182 }
183
184 InitializeFlow* tgt() {
186 }
187
188 If* iface() {
189 return static_cast<If*>(service());
190 }
191
195};
196
197} // namespace openlcb
198
199#endif // _OPENLCB_NODEINITIALIZEFLOW_HXX_
#define STATE(_fn)
Turns a function name into an argument to be supplied to functions expecting a state.
Definition StateFlow.hxx:61
A BarrierNotifiable allows to create a number of child Notifiable and wait for all of them to finish.
BarrierNotifiable * reset(Notifiable *done)
Resets the barrier. Returns &*this. Asserts that is_done().
virtual void send(MessageType *message, unsigned priority=UINT_MAX)=0
Entry point to the flow.
Node information.
Definition Devtab.hxx:549
A list of queues.
Definition Queue.hxx:466
Collection of related state machines that pend on incoming messages.
Singleton class.
Definition Singleton.hxx:65
static T * instance()
Definition Singleton.hxx:77
Return type for a state flow callback.
Base class for state machines.
Service * service()
Return a pointer to the service I am bound to.
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.
StateFlowBase()
Default constructor.
Action delete_this()
Terminates the flow and deletes *this.
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 wait_and_call(Callback c)
Wait for resource to become available before proceeding to next state.
Action release_and_exit()
Terminates the processing of the current message.
State flow with a given typed input queue.
Base::Action Action
Allows using Action without having StateFlowBase:: prefix in front of it.
void send(MessageType *msg, unsigned priority=UINT_MAX) OVERRIDE
Sends a message to the state flow for processing.
Action call_immediately(Callback c)
Imediately call the next state upon return.
Abstract class representing an OpenLCB Interface.
Definition If.hxx:185
MessageHandler * global_message_write_flow()
Definition If.hxx:200
MessageDispatchFlow * dispatcher()
Definition If.hxx:224
Node * first_local_node()
Definition If.hxx:289
Node * next_local_node(NodeID previous)
Iterator helper on the local nodes map.
Definition If.hxx:304
Performs upon-startup initialization of virtual nodes.
Action entry() OVERRIDE
Entry into the StateFlow activity.
Base class for NMRAnet nodes conforming to the asynchronous interface.
Definition Node.hxx:52
virtual void set_initialized()
Callback from the node initialization flow when the node finished initialization.
Definition Node.hxx:67
StateFlow that iterates through all local nodes and sends out node initialization complete for each o...
Node * nextNode_
Which node to send identify next. If nullptr, we're done.
#define CONSTANT_TRUE
We cannot compare constants to zero, so we use 1 and 2 as constant values for booleans.
#define OVERRIDE
Function attribute for virtual functions declaring that this funciton is overriding a funciton that s...
Definition macros.h:180
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
string node_id_to_buffer(NodeID id)
Convenience function to render a 48-bit NMRAnet node ID into a new buffer.
Definition If.cxx:45
uint64_t NodeID
48-bit NMRAnet Node ID type
void StartInitializationFlow(Node *node)
Helper function that sends a local virtual node to the static InitializeFlow.
@ MTI_EVENTS_IDENTIFY_ADDRESSED
request identify all of a node's events
@ MTI_INITIALIZATION_COMPLETE
initialization complete
@ WAIT_FOR_LOCAL_LOOPBACK
Specifies that the stack should wait for the local loopback processing before invoking the done notif...
Definition If.hxx:159
Request to send to instruct InitializeFlow to perform the initialization function of a single virtual...