![]() |
User Manual, Developers Guide and API Documentation |
![]() |
To define a custom functionalUnit we declare our custom Command that we will use later for our functionalUnit.
class FunkyCommand : public Command { public: FunkyCommand() { local.somethingFunky = 23; local.destructorCalled = NULL; } ~FunkyCommand() { if(NULL != local.destructorCalled) *local.destructorCalled = true; } virtual Bit getSize() const { return FUNKY_LENGTH; } struct { long somethingFunky; long *destructorCalled; } local; struct {} peer; struct {} magic; };
In this example the Command contains two members: somethingFunky and a pointer to a long, destructorCalled. Further a constructor, a destructor and the assignment operator are declared and defined. The getSize() method returns the size of the Command.
This FunkyCommand shall be the Command that is handled by the FunkyFunctionalUnit:
class FunkyFunctionalUnit : public virtual FunctionalUnit, public CommandTypeSpecifier<FunkyCommand>, public HasReceptor<>, public HasConnector<>, public HasDeliverer<>, public Cloneable<FunkyFunctionalUnit> { public: FunkyFunctionalUnit(fun::FUN* fuNet) : CommandTypeSpecifier<FunkyCommand>(fuNet), HasReceptor<>(), HasConnector<>(), HasDeliverer<>(), Cloneable<FunkyFunctionalUnit>(), destructorCalled(false) {} long foo(CommandPool* commandPool) { FunkyCommand* command = activateCommand(commandPool); command->local.destructorCalled = &destructorCalled; return command->local.somethingFunky; } long bar(CommandPool* commandPool) { FunkyCommand* command = getCommand(commandPool); command->local.destructorCalled = &destructorCalled; return command->local.somethingFunky; } long destructorCalled; void doOnData(const CompoundPtr&) {} void doSendData(const CompoundPtr&) {} private: // CompoundHandlerInterface bool doIsAccepting(const CompoundPtr&) const { return true; } void doWakeup() {} };
The FunkyFunctionalUnit is derived from the CommandTypeSpecifier and the functionalUnit has to handle FunkyCommands. Like almost all functionalUnits the FunkyFunctionalUnit has an upper and a lower interface. Incoming and outgoing Compounds are handled by the methods doOnData() and doSendData(), respectively. Here you have the possibility to alter the Compound and especially the previously defined FunkyCommand. This is the place to write or read custom data like sequence numbers. At the end of the doOnData() method the Compound is given to the next higher functionalUnit by calling its doOnData(). Resepctively downgoing packets are given to the next lower functionalUnit by calling doSendData() of the next lower functionalUnit. To learn more about interacting functionalUnits see LayerPage.
The wakeup() method is called by lower functionalUnits if they are able to receive new compounds from higher functionalUnits. This is only the case if the lower functionalUnit is able to block the packet flow. Finally the isAccepting() method is called immediately before a new PDU arrives at the doSendData() method. Here the functionalUnit is able to block the packet flow.
There are currently three different interfaces to choose from:
Use the Processor interface, whenever your FunctionalUnit has no internal storage for compounds, performs mutation only and forwards compounds without delay.
Use the Delayed interface, whenever your FunctionalUnit has internal storage, wants to inject new compounds into the FunctionalUnit stack or wants to drop compounds.
1.5.5