Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
NonAuthoritativeEventProducer.cxx
Go to the documentation of this file.
1
37#include "openlcb/NonAuthoritativeEventProducer.hxx"
39
40namespace openlcb
41{
42
43//
44// BitRangeNonauthoritativeEventP::send_query_consumer()
45//
47 WriteHelper *writer,
49{
50 HASSERT(bit < size_);
51 uint64_t event = eventBaseOff_ == 0 ? eventBase_ + (bit * 2) :
52 eventBaseOn_ + bit;
54 WriteHelper::global(),
55 eventid_to_buffer(event), done);
56}
57
58//
59// BitRangeNonauthoritativeEventP::handle_event_report()
60//
62 const EventRegistryEntry& entry,
63 EventReport *event,
65{
66 done->notify();
67 if (!stateCallback_)
68 {
69 // there is nobody to notify
70 return;
71 }
72
73 switch (entry.user_arg)
74 {
75 default:
76 // uninteresting event range, should never get here
77 HASSERT(0);
78 case EVENT_BASE:
79 if (event->event >= eventBase_ &&
80 event->event < (eventBase_ + (size_ * 2)))
81 {
82 bool value = (event->event % 2) == (eventBase_ % 2);
83 stateCallback_((event->event - eventBase_) / 2, value);
84 }
85 break;
86 case EVENT_BASE_ON:
87 if (event->event >= eventBaseOn_ &&
88 event->event < (eventBaseOn_ + size_))
89 {
90 stateCallback_((event->event - eventBaseOn_), true);
91 }
92 break;
93 case EVENT_BASE_OFF:
94 if (event->event >= eventBaseOff_ &&
95 event->event < (eventBaseOff_ + size_))
96 {
97 stateCallback_((event->event - eventBaseOff_), false);
98 }
99 break;
100 }
101}
102
103//
104// BitRangeNonauthoritativeEventP::handle_consumer_identified()
105//
107 const EventRegistryEntry& entry,
108 EventReport *event,
109 BarrierNotifiable *done)
110{
111 done->notify();
112 if (!stateCallback_)
113 {
114 // there is nobody to notify
115 return;
116 }
117
118 bool value;
119 if (event->state == EventState::VALID)
120 {
121 value = true;
122 }
123 else if (event->state == EventState::INVALID)
124 {
125 value = false;
126 }
127 else
128 {
129 return; // nothing to learn from this message.
130 }
131
132 switch (entry.user_arg)
133 {
134 default:
135 // uninteresting event range, should never get here
136 HASSERT(0);
137 case EVENT_BASE:
138 if (event->event >= eventBase_ &&
139 event->event < (eventBase_ + (size_ * 2)))
140 {
141 if ((event->event % 2) != (eventBase_ % 2))
142 {
143 value = !value;
144 }
145 stateCallback_((event->event - eventBase_) / 2, value);
146 }
147 break;
148 case EVENT_BASE_ON:
149 if (event->event >= eventBaseOn_ &&
150 event->event < (eventBaseOn_ + size_))
151 {
152 stateCallback_((event->event - eventBase_), value);
153 }
154 break;
155 case EVENT_BASE_OFF:
156 if (event->event >= eventBaseOff_ &&
157 event->event < (eventBaseOff_ + size_))
158 {
159 stateCallback_((event->event - eventBaseOff_), !value);
160 }
161 break;
162 }
163}
164
165//
166// BitRangeNonauthoritativeEventP::handle_identify_producer()
167//
169 const EventRegistryEntry& entry,
170 EventReport *event,
171 BarrierNotifiable *done)
172{
173 if (event->dst_node && event->dst_node != node_)
174 {
175 done->notify();
176 }
177 else
178 {
179 uint64_t range;
180 switch (entry.user_arg)
181 {
182 default:
183 // uninteresting event range, should never get here
184 HASSERT(0);
185 case EVENT_BASE:
186 range = EncodeRange(eventBase_, size_ * 2);
187 break;
188 case EVENT_BASE_ON:
190 break;
191 case EVENT_BASE_OFF:
193 break;
194 }
195 event->event_write_helper<1>()->WriteAsync(node_,
196 Defs::MTI_PRODUCER_IDENTIFIED_RANGE, WriteHelper::global(),
197 eventid_to_buffer(range), done);
198 }
199}
200
201//
202// BitRangeNonauthoritativeEventP::handle_identify_producer()
203//
205 const EventRegistryEntry& entry,
206 EventReport *event,
207 BarrierNotifiable *done)
208{
209 bool valid = false;
210 switch (entry.user_arg)
211 {
212 default:
213 // uninteresting event range, should never get here
214 HASSERT(0);
215 case EVENT_BASE:
216 if (event->event >= eventBase_ &&
217 event->event < (eventBase_ + (size_ * 2)))
218 {
219 valid = true;
220 }
221 break;
222 case EVENT_BASE_ON:
223 if (event->event >= eventBaseOn_ &&
224 event->event < (eventBaseOn_ + size_))
225 {
226 valid = true;
227 }
228 break;
229 case EVENT_BASE_OFF:
230 if (event->event >= eventBaseOff_ &&
231 event->event < (eventBaseOff_ + size_))
232 {
233 valid = true;
234 }
235 break;
236 }
237
238 if (valid)
239 {
240 event->event_write_helper<1>()->WriteAsync(node_,
241 Defs::MTI_PRODUCER_IDENTIFIED_UNKNOWN, WriteHelper::global(),
242 eventid_to_buffer(event->event), done);
243 }
244 else
245 {
246 done->notify();
247 }
248}
249
250//
251// BitRangeNonauthoritativeEventP::set()
252//
253void BitRangeNonAuthoritativeEventP::set(unsigned bit, bool new_value,
254 WriteHelper *writer,
255 BarrierNotifiable *done)
256{
257 HASSERT(bit < size_);
258
259 uint64_t event;
260 if (new_value)
261 {
262 event = eventBaseOff_ == 0 ? eventBase_ + (bit * 2) :
263 eventBaseOn_ + bit;
264 }
265 else
266 {
267 event = eventBaseOff_ == 0 ? eventBase_ + (bit * 2) + 1 :
268 eventBaseOff_ + bit;
269 }
270
271 writer->WriteAsync(node_, Defs::MTI_EVENT_REPORT, WriteHelper::global(),
272 eventid_to_buffer(event), done);
273}
274
275} // namespace openlcb
A BarrierNotifiable allows to create a number of child Notifiable and wait for all of them to finish.
void notify() override
Implementation of the barrier semantics.
void set(unsigned bit, bool new_value, WriteHelper *writer, BarrierNotifiable *done)
Requests the event associated with the current value of the bit to be produced (unconditionally).
void handle_identify_global(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Handle an incoming identify global or addressed message.
uint64_t eventBaseOn_
base event ID for "on" range
void handle_event_report(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Handle an incoming event.
void handle_consumer_identified(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Handle an incoming consumer identified message.
uint64_t eventBaseOff_
base event ID for "off" range
void handle_identify_producer(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Handle an incoming identify producer message.
std::function< void(unsigned, bool)> stateCallback_
Callback method that will be invoked when a consumer identified message is received with a known stat...
uint64_t eventBase_
base event ID of the full range
Node * node_
Node ID that this producer is attached to.
void send_query_consumer(unsigned bit, WriteHelper *writer, BarrierNotifiable *done)
Queries consumer and acquires the current state of the bit.
@ EVENT_BASE_ON
one unified range starting at eventBase_
Structure used in registering event handlers.
uint32_t user_arg
Opaque user argument.
A statically allocated buffer for sending one message to the OpenLCB bus.
void WriteAsync(Node *node, Defs::MTI mti, NodeHandle dst, const payload_type &buffer, Notifiable *done)
Originates an NMRAnet message from a particular node.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
uint64_t EncodeRange(uint64_t begin, unsigned size)
Creates a single encoded event range from the beginning of the range and the number fo events to cove...
Payload eventid_to_buffer(uint64_t eventid)
Converts an Event ID to a Payload suitable to be sent as an event report.
Definition If.cxx:72
@ MTI_PRODUCER_IDENTIFIED_RANGE
producer broadcast about a range of producers
@ MTI_CONSUMER_IDENTIFY
query about consumers
@ MTI_PRODUCER_IDENTIFIED_UNKNOWN
producer broadcast, validity unknown
Shared notification structure that is assembled for each incoming event-related message,...
EventState state
For producer/consumer identified messages, specifies the state of the producer/consumer as the sender...
EventId event
The event ID from the incoming message.
Node * dst_node
nullptr for global messages; points to the specific virtual node for addressed events identify messag...