35#ifndef _EXECUTOR_DISPATCHER_HXX_
36#define _EXECUTOR_DISPATCHER_HXX_
50template <
int NUM_PRIO>
179 return (this->
id ==
id && this->mask ==
mask &&
204#ifdef TARGET_LPC11Cxx
205#define BASE_NUM_PRIO 4
209#define BASE_NUM_PRIO NUM_PRIO
214template <
class MessageType,
int NUM_PRIO>
235 typedef typename MessageType::value_type::id_type
ID;
287 return this->
message()->data()->id();
311 copy->set_done(this->
message()->new_child());
312 *copy->data() = *this->
message()->data();
328template <
int NUM_PRIO>
331 , negateMatch_(false)
332 , lastHandlerToCall_(nullptr)
336template<
int NUM_PRIO>
342template<
int NUM_PRIO>
347 for (
auto &h : handlers_)
357template<
int NUM_PRIO>
363 while (idx < handlers_.size() && handlers_[idx].handler)
367 if (idx >= handlers_.size())
369 handlers_.resize(handlers_.size() + 1);
371 handlers_[idx].handler = handler;
372 handlers_[idx].id = id;
373 handlers_[idx].mask = mask;
376template<
int NUM_PRIO>
384 while (idx < handlers_.size() && !handlers_[idx].Equals(
id, mask, handler))
389 HASSERT(idx < handlers_.size() &&
390 "Tried to unregister a handler not previously registered.");
391 if (lastHandlerToCall_ == handlers_[idx].handler) {
392 lastHandlerToCall_ =
nullptr;
394 handlers_[idx].handler =
nullptr;
395 if (idx == handlers_.size() - 1)
397 handlers_.resize(handlers_.size() - 1);
401template<
int NUM_PRIO>
406 for (
size_t i = 0; i < handlers_.size(); ++i)
408 if (handlers_[i].handler == handler)
410 handlers_[i].handler =
nullptr;
413 while (!handlers_.empty() && handlers_.back().handler ==
nullptr)
415 handlers_.pop_back();
419template<
int NUM_PRIO>
423 lastHandlerToCall_ =
nullptr;
424 return call_immediately(
STATE(iterate));
427template<
int NUM_PRIO>
430 ID id = get_message_id();
435 for (; currentIndex_ < handlers_.size(); ++currentIndex_)
437 auto &h = handlers_[currentIndex_];
442 if (negateMatch_ && (
id & h.mask) == (h.id & h.mask))
446 if ((!negateMatch_) && (
id & h.mask) != (h.id & h.mask))
451 if (!lastHandlerToCall_)
454 lastHandlerToCall_ = handlers_[currentIndex_].handler;
460 if (currentIndex_ >= handlers_.size())
462 return iteration_done();
466 return allocate_and_clone();
469template<
int NUM_PRIO>
472 lastHandlerToCall_ = handlers_[currentIndex_].handler;
474 return call_immediately(
STATE(iterate));
477template<
int NUM_PRIO>
480 if (lastHandlerToCall_)
484 else if (fallbackHandler_)
488 lastHandlerToCall_ = fallbackHandler_;
491 return release_and_exit();
#define STATE_FLOW_STATE(_state)
Declare a state callback in a StateFlow.
#define STATE(_fn)
Turns a function name into an argument to be supplied to functions expecting a state.
Abstract base class for all Buffers.
This class takes registrations of StateFlows for incoming messages.
UntypedHandler * fallbackHandler_
Handler to give all messages that were not matched by any other handler registration.
virtual void send_transfer()=0
Sends the current message to lastHandlerToCall, transferring ownership.
Action iteration_done()
State when the entire iteration is done.
void unregister_handler_all(UntypedHandler *handler)
Removes all instances of a handler from this dispatcher.
void UntypedHandler
Generic handler type.
StateFlowBase::Action Action
Allows using Action without having StateFlowBase:: prefix in front of it.
Action clone_done()
State after a clone-and-send operation is complete.
void register_fallback_handler(UntypedHandler *handler)
Sets one handler to receive all messages that no other handler has matched.
OSMutex lock_
Protects handler add / remove against iteration.
bool negateMatch_
true if this flow should negate the match condition.
vector< HandlerInfo > handlers_
Registered handlers.
virtual ID get_message_id()=0
Returns the current message's ID.
Action entry() override
Entry into the StateFlow activity.
Action iterate()
Iterate on potential handlers, matching the ID of the incoming message to the handlers' masks.
DispatchFlowBase(Service *service)
Construct a dispatchflow.
void unregister_handler(UntypedHandler *handler, ID id, ID mask)
Removes a specific instance of a handler from this dispatcher.
void register_handler(UntypedHandler *handler, ID id, ID mask)
Adds a new handler to this dispatcher.
virtual Action allocate_and_clone()=0
Allocates an entry from lastHandlerToCall_, invoking clone() when done: return allocate_and_call(last...
UntypedHandler * lastHandlerToCall_
If non-NULL we still need to call this handler.
size_t currentIndex_
Index of the next handler to look at.
uint32_t ID
Proxy the identifier type for customers to use.
Type-specific implementations of the DispatchFlow methods.
MessageType::value_type::id_type ID
Maskable type of the dispatched messages upon which handlers can configure to trigger.
Base::ID get_message_id() OVERRIDE
void register_handler(HandlerType *handler, ID id, ID mask)
Adds a new handler to this dispatcher.
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 entry() OVERRIDE
Override method that will be called after each incoming message is dequeued.
void register_fallback_handler(HandlerType *handler)
Sets one handler to receive all messages that no other handler has matched.
void send_transfer() OVERRIDE
Takes the existing buffer and sends off to the target flow.
DispatchFlow(Service *service)
Constructor.
FlowInterface< MessageType > HandlerType
Interface type for handlers that can be registered.
Action allocate_and_clone() OVERRIDE
Requests allocating a new buffer for sending off a clone.
StateFlowBase::Action Action
Imports types and functions to allow less typing for the implementation.
Action clone()
Takes the allocated new buffer, copies the message into it and sends off to the clone target.
Buffer< T > * get_allocation_result(FlowInterface< Buffer< T > > *target_flow)
Takes the result of the asynchronous allocation.
void unregister_handler_all(HandlerType *handler)
Removes all instances of a handler from this dispatcher.
Action call_immediately(Callback c)
Imediately call the next state upon return.
void unregister_handler(HandlerType *handler, ID id, ID mask)
Removes a specific instance of a handler from this dispatcher.
TypedStateFlow< MessageType, DispatchFlowBase< BASE_NUM_PRIO > > Base
Helper typedef of the base class of *this.
Abstract class for message recipients.
virtual void send(MessageType *message, unsigned priority=UINT_MAX)=0
Entry point to the flow.
Templated implementation of the HubFlow.
Class to allow convenient locking and unlocking of mutexes in a C context.
This class provides a mutex API.
Collection of related state machines that pend on incoming messages.
Return type for a state flow callback.
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.
Buffer< T > * get_allocation_result(FlowInterface< Buffer< T > > *target_flow)
Takes the result of the asynchronous allocation.
Action again()
Call the current state again via call_immediately.
Action call_immediately(Callback c)
Imediately call the next state upon return.
void cast_allocation_result(T **member)
Takes the result of the asynchronous allocation without resetting the object.
Action release_and_exit()
Terminates the processing of the current message.
Helper class in the StateFlow hierarchy.
MessageType * transfer_message()
Releases ownership of the current message.
State flow base class with queue but generic message type.
#define OVERRIDE
Function attribute for virtual functions declaring that this funciton is overriding a funciton that s...
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Internal information we store about each registered handler: identifier, mask, handler pointer.
ID mask
Mask that should be applied for the bits check.
ID id
Bits that this handler is registered for.
bool Equals(ID id, ID mask, UntypedHandler *handler)
Equality comparison function on the handlers.
UntypedHandler * handler
Handler to call. NULL if the handler has been removed.