I'm asking about a ring topology network, I'm looking to send a message from the node to hub and then to another node then back to the hub but when it simulates there is an error that pops up. I'm not sure what is the issue.
send()/sendDelayed(): No gate index specified when accessing vector gate 'out' -- in module (node) Startop.node[0] (id=2), during network initialization
Here is my .ned file:
package startop;
simple node
{
parameters:
#display("i=device/pc2_s");
gates:
input in[];
output out[];
}
simple hub
{
parameters:
#display("i=device/switch");
gates:
input in[];
output out[];
}
network Startop
{
parameters:
int n #prompt("Number of stations") = default(2);
submodules:
node[n]: node;
hub: hub {
#display("p=222,170");
}
connections allowunconnected:
for i=0..n-1 {
node[i].out++ --> hub.in++;
hub.out++ --> node[i].in++;
}
}
This is the .cc file:
#include <stdio.h>
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
class node : public cSimpleModule
{
private:
simtime_t timeout; // timeout
cMessage *timeoutEvent; // holds pointer to the timeout self-message
public:
node();
virtual ~node();
protected:
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(node);
node::node()
{
timeoutEvent = nullptr;
}
node::~node()
{
cancelAndDelete(timeoutEvent);
}
void node::initialize()
{
// Initialize variables.
timeout = 1.0;
timeoutEvent = new cMessage("timeoutEvent");
// Generate and send initial message.
EV << "Sending initial message\n";
cMessage *msg = new cMessage("StarMsg");
send(msg, "out");
scheduleAt(simTime()+timeout, timeoutEvent);
}
void node::handleMessage(cMessage *msg)
{
if (msg == timeoutEvent) {
// If we receive the timeout event, that means the packet hasn't
// arrived in time and we have to re-send it.
EV << "Timeout expired, resending message and restarting timer\n";
cMessage *newMsg = new cMessage("StarMsg");
send(newMsg, "out");
scheduleAt(simTime()+timeout, timeoutEvent);
}
else { // message arrived
// Acknowledgement received -- delete the received message and cancel
// the timeout event.
EV << "Timer cancelled.\n";
cancelEvent(timeoutEvent);
delete msg;
// Ready to send another one.
cMessage *newMsg = new cMessage("starMsg");
send(newMsg, "out");
scheduleAt(simTime()+timeout, timeoutEvent);
}
}
class hub : public cSimpleModule
{
protected:
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(hub);
void hub::handleMessage(cMessage *msg)
{
if (uniform(0, 1) < 0.1) {
EV << "\"Losing\" message.\n";
bubble("message lost"); // making animation more informative...
delete msg;
}
else {
EV << "Sending back same message as acknowledgement.\n";
send(msg, "out");
}
}
May I know how to solve this problem?
The issue is exactly what the error message said. The NED file defines the out gate a vector both in node and hub:
output out[];
However your c++ code always uses the send method send(msg, "out") without specifying which out gate should be used. i.e. it never specifies the index. You must use the send(msg, "out", getIndex) for this.
Related
Whenever I run my simulation the msg that is initial created at rdrchk1 gets stuck going between
rdrchk1 and rdrsucess1.
Here is my C++ code:
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
class rdr : public cSimpleModule
{
protected:
// The following redefined virtual function holds the algorithm.
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
// The module class needs to be registered with OMNeT++
Define_Module(rdr);
void rdr::initialize()
{
int v1 = rand() % 100;
int v2 = rand() % 100;
int v3 = rand() % 100;
if (strcmp("rdrchk1", getName()) == 0) {
cMessage *msg = new cMessage("objectcheck");
if (v1<78|| v2 < 82 || v3 <69){
int n = 0;
send(msg, "out", n);
}
else{
int d=1;
send(msg, "out", d);
}
}
}
void rdr::handleMessage(cMessage *msg)
{
int t = 0;
send(msg, "out",t);
}
Here is my NED code:
simple rdr
{
parameters:
#display("i=block/routing");
gates:
input in[4];
output out[4];
}
//
network radr
{
#display("bgb=356,232");
submodules:
rdrchk1: rdr {
#display("p=85,67");
}
rdrfail1: rdr {
#display("p=275,133;i=block/wheelbarrow");
}
rdrsucess1: rdr {
#display("p=291,61");
}
connections allowunconnected:
rdrchk1.out[1] --> rdrfail1.in++;
rdrchk1.out[0] --> rdrsucess1.in++;
rdrchk1.in[2] <-- rdrfail1.out++;
rdrchk1.in[3] <-- rdrsucess1.out++;
}
I know it's stuck because whenever I edit my code so that it is guaranteed to go to rdrfail1 the next step it is stuck going between rdrchk1 and rdrsucess1. Can any one tell me why it is doing that and what I could do to fix it. Thank you for your time.
Here is what is happening in your model.
In initialize() of rdrchk1 a new message is created. Then that message is sent:
a. to rdrsucess1 when the condition if (v1<78|| v2 < 82 || v3 <69) is true
or
b. to rdrfail1 otherwise
If rdrsucess1 receives the message, it immediately sends that message to rdrchk1 (because in your network port with index 0 of gate out of rdrsucess1 is connected to rdrchk1).
If rdrfail1 receives the message, it immediately sends that message to rdrchk1 (because in your network port with index 0 of gate out of rdrfail1 is connected to rdrchk1).
Then rdrchk1 receives the message and sends it immediately to rdrsucess1.
Then points 2 and 4 are repeated endlessly.
I'm making a randomly generated network where the node will send an update massage after asking if the other node already know the update. Currently the update status is still predefined. I'm getting this error message when running the simulation:
send()/sendDelayed(): Gate index 1048576 out of range when accessing vector gate 'out[]' with size 1 -- in module (Sg1) Simplegossip1.node[2] (id=4), at t=0s event #1
Here's my code:
simplegossip1.ned
simple Sg1
{
parameters:
#display("i=block/routing");
bool updated;
gates:
input in[]; // declare in[] and out[] to be vector gates
output out[];
}
network Simplegossip1
{
parameters:
int count;
double connectedness; // 0.0<x<1.0
#display("bgb=640,444");
submodules:
node[count]: Sg1 {
gates:
in[]; // removed the size of gate
out[];
}
connections allowunconnected:
for i=0..count-2, for j=i+1..count-1, if uniform(0,1)<connectedness {
node[i].out++ --> node[j].in++;
node[i].in++ <-- node[j].out++;
}
}
Here's the cc file.
sg1.cc
#include <stdio.h>
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
/**
* First attempt for gossip protocol
*/
class Sg1 : public cSimpleModule
{
protected:
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Sg1);
void Sg1::initialize()
{
if (getIndex() == 0) {
cMessage *askupdated = new cMessage("Ask Update");
int m = gateSize("out");
int l = intuniform(0, m-1);
send(askupdated, "out",l);
}
}
void Sg1::handleMessage(cMessage *msg)
{
//gate randomizer
int n = gateSize("out");
int k = intuniform(0, n-1);
int sid = msg->getArrivalGateId();
bool updatestatus = par("updated");
EV << "Received message `" << msg->getName() << "', sending it out again\n";
if (strncmp (msg->getName(),"Ask Update",2) == 0) {
if (updatestatus == true){
delete msg;
cMessage *updated = new cMessage("Updated");
send(updated, "out", sid);
}
else {
delete msg;
cMessage *unupdated = new cMessage("Unupdated");
send(unupdated, "out", sid);
}
}
else if (strncmp (msg->getName(),"Unupdated",2) == 0) {
delete msg;
cMessage *update = new cMessage("Here is the update");
send(update, "out", sid);
}
else {
delete msg;
cMessage *askupdated = new cMessage("Ask Update");
send(askupdated, "out", sid);
}
}
And an omnet.ini file that only calling the Simplegossip1 network.
How do I solve this? Thanks in advance.
In the line:
int sid = msg->getArrivalGateId();
you read the gate ID. Then you use this value as a gate index:
send(updated, "out", sid);
However, a gate ID is not the same as gate index. Therefore there is an error during send().
In the simulation every object (e.g. module, gate, message) has a unique number (i.e. ID). It is clearly mentioned in
OMNeT++ Simulation Library.
You should check the current size of the gate and be sure that you do not try to send via index out of scope.
I'm making a randomly generated network where the node will send an update massage after asking if the other node already know the update. Currently the update status is still predefined. I'm getting this error message when running the simulation:
"(omnetpp::cModule)Simplegossip1: Unknown parameter 'updated' -- in module (Sg1) Simplegossip1.node[0] (id=2), at t=0s, event #1"
Here's my code:
simplegossip1.ned (I'm using code from here How to create a randomly connected graph in OMNeT++?)
simple Sg1
{
parameters:
#display("i=block/routing");
bool updated;
gates:
input in[]; // declare in[] and out[] to be vector gates
output out[];
}
network Simplegossip1
{
parameters:
int count;
double connectedness; // 0.0<x<1.0
submodules:
node[count]: Sg1 {
gates:
in[]; // removed the size of gate
out[];
}
connections allowunconnected:
for i=0..count-2, for j=i+1..count-1, if uniform(0,1)<connectedness {
node[i].out++ --> node[j].in++;
node[i].in++ <-- node[j].out++;
}
}
sg1.cc
#include <stdio.h>
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
/**
* First attempt for gossip protocol
*/
class Sg1 : public cSimpleModule
{
public:
cMessage *askupdated = new cMessage("Ask Update");
cMessage *updated = new cMessage("Updated");
cMessage *unupdated = new cMessage("Unupdated");
cMessage *update = new cMessage("Here is the update");
protected:
virtual void forwardMessage(cMessage *msg, int dest);
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Sg1);
void Sg1::initialize()
{
if (getIndex() == 0) {
// Boot the process scheduling the initial message as a self-message.
char msgname[20];
sprintf(msgname, "tic-%d", getIndex());
cMessage *msg = new cMessage(msgname);
scheduleAt(0.0, msg);
}
}
void Sg1::handleMessage(cMessage *msg)
{
int n = gateSize("out");
int k = intuniform(0, n-1);
int sid = msg->getArrivalGateId();
bool updatestatus = getParentModule()->par("updated");
if (msg == askupdated) {
if (updatestatus == true){
forwardMessage(updated,sid);
}
else {
forwardMessage(unupdated,sid);
}
}
else if (msg == unupdated) {
forwardMessage(update,sid);
}
else {
forwardMessage(askupdated,k);
}
}
void Sg1::forwardMessage(cMessage *msg, int dest)
{
// In this example, we just pick a random gate to send it on.
// We draw a random number between 0 and the size of gate `out[]'.
EV << "Forwarding message " << msg << " on port out[" << dest << "]\n";
send(msg, "out", dest);
}
And an omnet.ini file that only calling the Simplegossip1 network.
How do I solve this? Thanks in advance.
You have to change the line
bool updatestatus = getParentModule()->par("updated");
into
bool updatestatus = par("updated");
because updated is the parameter of Sg1 not of the parent of Sg1.
Our company is rewriting most of the legacy C code in C++11. (Which also means I am a C programmer learning C++). I need advice on message handlers.
We have distributed system - Server process sends a packed message over TCP to client process.
In C code this was being done:
- parse message based on type and subtype, which are always the first 2 fields
- call a handler as handler[type](Message *msg)
- handler creates temporary struct say, tmp_struct to hold the parsed values and ..
- calls subhandler[type][subtype](tmp_struct)
There is only one handler per type/subtype.
Moving to C++11 and mutli-threaded environment. The basic idea I had was to -
1) Register a processor object for each type/subtype combination. This is
actually a vector of vectors -
vector< vector >
class MsgProcessor {
// Factory function
virtual Message *create();
virtual Handler(Message *msg)
}
This will be inherited by different message processors
class AMsgProcessor : public MsgProcessor {
Message *create() override();
handler(Message *msg);
}
2) Get the processor using a lookup into the vector of vectors.
Get the message using the overloaded create() factory function.
So that we can keep the actual message and the parsed values inside the message.
3) Now a bit of hack, This message should be send to other threads for the heavy processing. To avoid having to lookup in the vector again, added a pointer to proc inside the message.
class Message {
const MsgProcessor *proc; // set to processor,
// which we got from the first lookup
// to get factory function.
};
So other threads, will just do
Message->proc->Handler(Message *);
This looks bad, but hope, is that this will help to separate message handler from the factory. This is for the case, when multiple type/subtype wants to create same Message, but handle it differently.
I was searching about this and came across :
http://www.drdobbs.com/cpp/message-handling-without-dependencies/184429055?pgno=1
It provides a way to completely separate the message from the handler. But I was wondering if my simple scheme above will be considered an acceptable design or not. Also is this a wrong way of achieving what I want?
Efficiency, as in speed, is the most important requirement from this application. Already we are doing couple of memory Jumbs => 2 vectors + virtual function call the create the message. There are 2 deference to get to the handler, which is not good from caching point of view I guess.
Though your requirement is unclear, I think I have a design that might be what you are looking for.
Check out http://coliru.stacked-crooked.com/a/f7f9d5e7d57e6261 for the fully fledged example.
It has following components:
An interface class for Message processors IMessageProcessor.
A base class representing a Message. Message
A registration class which is essentially a singleton for storing the message processors corresponding to (Type, Subtype) pair. Registrator. It stores the mapping in a unordered_map. You can also tweak it a bit for better performance. All the exposed API's of Registrator are protected by a std::mutex.
Concrete implementations of MessageProcessor. AMsgProcessor and BMsgProcessor in this case.
simulate function to show how it all fits together.
Pasting the code here as well:
/*
* http://stackoverflow.com/questions/40230555/efficient-message-factory-and-handler-in-c
*/
#include <iostream>
#include <vector>
#include <tuple>
#include <mutex>
#include <memory>
#include <cassert>
#include <unordered_map>
class Message;
class IMessageProcessor
{
public:
virtual Message* create() = 0;
virtual void handle_message(Message*) = 0;
virtual ~IMessageProcessor() {};
};
/*
* Base message class
*/
class Message
{
public:
virtual void populate() = 0;
virtual ~Message() {};
};
using Type = int;
using SubType = int;
using TypeCombo = std::pair<Type, SubType>;
using IMsgProcUptr = std::unique_ptr<IMessageProcessor>;
/*
* Registrator class maintains all the registrations in an
* unordered_map.
* This class owns the MessageProcessor instance inside the
* unordered_map.
*/
class Registrator
{
public:
static Registrator* instance();
// Diable other types of construction
Registrator(const Registrator&) = delete;
void operator=(const Registrator&) = delete;
public:
// TypeCombo assumed to be cheap to copy
template <typename ProcT, typename... Args>
std::pair<bool, IMsgProcUptr> register_proc(TypeCombo typ, Args&&... args)
{
auto proc = std::make_unique<ProcT>(std::forward<Args>(args)...);
bool ok;
{
std::lock_guard<std::mutex> _(lock_);
std::tie(std::ignore, ok) = registrations_.insert(std::make_pair(typ, std::move(proc)));
}
return (ok == true) ? std::make_pair(true, nullptr) :
// Return the heap allocated instance back
// to the caller if the insert failed.
// The caller now owns the Processor
std::make_pair(false, std::move(proc));
}
// Get the processor corresponding to TypeCombo
// IMessageProcessor passed is non-owning pointer
// i.e the caller SHOULD not delete it or own it
std::pair<bool, IMessageProcessor*> processor(TypeCombo typ)
{
std::lock_guard<std::mutex> _(lock_);
auto fitr = registrations_.find(typ);
if (fitr == registrations_.end()) {
return std::make_pair(false, nullptr);
}
return std::make_pair(true, fitr->second.get());
}
// TypeCombo assumed to be cheap to copy
bool is_type_used(TypeCombo typ)
{
std::lock_guard<std::mutex> _(lock_);
return registrations_.find(typ) != registrations_.end();
}
bool deregister_proc(TypeCombo typ)
{
std::lock_guard<std::mutex> _(lock_);
return registrations_.erase(typ) == 1;
}
private:
Registrator() = default;
private:
std::mutex lock_;
/*
* Should be replaced with a concurrent map if at all this
* data structure is the main contention point (which I find
* very unlikely).
*/
struct HashTypeCombo
{
public:
std::size_t operator()(const TypeCombo& typ) const noexcept
{
return std::hash<decltype(typ.first)>()(typ.first) ^
std::hash<decltype(typ.second)>()(typ.second);
}
};
std::unordered_map<TypeCombo, IMsgProcUptr, HashTypeCombo> registrations_;
};
Registrator* Registrator::instance()
{
static Registrator inst;
return &inst;
/*
* OR some other DCLP based instance creation
* if lifetime or creation of static is an issue
*/
}
// Define some message processors
class AMsgProcessor final : public IMessageProcessor
{
public:
class AMsg final : public Message
{
public:
void populate() override {
std::cout << "Working on AMsg\n";
}
AMsg() = default;
~AMsg() = default;
};
Message* create() override
{
std::unique_ptr<AMsg> ptr(new AMsg);
return ptr.release();
}
void handle_message(Message* msg) override
{
assert (msg);
auto my_msg = static_cast<AMsg*>(msg);
//.... process my_msg ?
//.. probably being called in some other thread
// Who owns the msg ??
(void)my_msg; // only for suppressing warning
delete my_msg;
return;
}
~AMsgProcessor();
};
AMsgProcessor::~AMsgProcessor()
{
}
class BMsgProcessor final : public IMessageProcessor
{
public:
class BMsg final : public Message
{
public:
void populate() override {
std::cout << "Working on BMsg\n";
}
BMsg() = default;
~BMsg() = default;
};
Message* create() override
{
std::unique_ptr<BMsg> ptr(new BMsg);
return ptr.release();
}
void handle_message(Message* msg) override
{
assert (msg);
auto my_msg = static_cast<BMsg*>(msg);
//.... process my_msg ?
//.. probably being called in some other thread
//Who owns the msg ??
(void)my_msg; // only for suppressing warning
delete my_msg;
return;
}
~BMsgProcessor();
};
BMsgProcessor::~BMsgProcessor()
{
}
TypeCombo read_from_network()
{
return {1, 2};
}
struct ParsedData {
};
Message* populate_message(Message* msg, ParsedData& pdata)
{
// Do something with the message
// Calling a dummy populate method now
msg->populate();
(void)pdata;
return msg;
}
void simulate()
{
TypeCombo typ = read_from_network();
bool ok;
IMessageProcessor* proc = nullptr;
std::tie(ok, proc) = Registrator::instance()->processor(typ);
if (!ok) {
std::cerr << "FATAL!!!" << std::endl;
return;
}
ParsedData parsed_data;
//..... populate parsed_data here ....
proc->handle_message(populate_message(proc->create(), parsed_data));
return;
}
int main() {
/*
* TODO: Not making use or checking the return types after calling register
* its a must in production code!!
*/
// Register AMsgProcessor
Registrator::instance()->register_proc<AMsgProcessor>(std::make_pair(1, 1));
Registrator::instance()->register_proc<BMsgProcessor>(std::make_pair(1, 2));
simulate();
return 0;
}
UPDATE 1
The major source of confusion here seems to be because the architecture of the even system is unknown.
Any self respecting event system architecture would look something like below:
A pool of threads polling on the socket descriptors.
A pool of threads for handling timer related events.
Comparatively small number (depends on application) of threads to do long blocking jobs.
So, in your case:
You will get network event on the thread doing epoll_wait or select or poll.
Read the packet completely and get the processor using Registrator::get_processor call.
NOTE: get_processor call can be made without any locking if one can guarantee that the underlying unordered_map does not get modified i.e no new inserts would be made once we start receiving events.
Using the obtained processor we can get the Message and populate it.
Now, this is the part that I am not that sure of how you want it to be. At this point, we have the processor on which you can call handle_message either from the current thread i.e the thread which is doing epoll_wait or dispatch it to another thread by posting the job (Processor and Message) to that threads receiving queue.
In omnet ++ while programing tic toc , if there are three nodes and all are connected to one another then how to send tic toc message to a specific node. for example i want to send message first to node A and then Node B and then Node C ; how would i code this.
#include <string.h>
#include <omnetpp.h>
int x=0;
class computerf : public cSimpleModule
{
protected:
virtual void initialize();
virtual void handleMessage(cMessage *msg);virtual void forwardMessage(cMessage *msg);
};
Define_Module(computerf);
void computerf::initialize()
{
if (strcmp("computer1", getName()) == 0)
{
cMessage *msg = new cMessage("tictocMsg");
forwardMessage(msg);
}
}
void computerf::handleMessage(cMessage *msg)
{
{
forwardMessage(msg);
}
}
void computerf::forwardMessage(cMessage *msg)
{
// In this example, we just pick a random gate to send it on.
// We draw a random number between 0 and the size of gate `out[]'.
int n = gateSize("out");
int k = intuniform(0,n-1);
EV << "Forwarding message " << msg << " on port out[" << k << "]\n";
send(msg, "out", 1);
EV <<"n is "<<n;
}
here in this code forwardMessage function sends message on random gate but i want to send message on specific gate.
this is the .ned file
simple computer
{
gates:
input in[2];
output out[2];
}
//
// TODO documentation
//
network Network
{
#display("bgb=545,242");
submodules:
A: computer {
#display("p=52,86");
}
B: computer {
#display("p=311,83");
}
C: computer {
#display("p=175,189");
}
connections:
A.out[0] --> B.in[0];
B.out[0] --> A.in[0];
A.out[1] --> C.in[1];
C.out[1] --> A.in[1];
C.out[0] --> B.in[1];
B.out[1] --> C.in[0];
}
basically i want node A to send message to node C and Node A to send message to node B simultaneously
if i use the hanlde message function
void computer::handleMessage(cMessage *msg)
{
send(msg, "out",0); //send(msg, "out",0);
}
now here in out send(msg, "out",0); i want to specify which "out" i want send message to node C and then to Node B but how?
The third parameter of the send(msg, "gate", index) is the actual gate index you can use while sending out messages on a vector gate. According to your NED file, send(msg, "out",0); sends the message to B while send(msg, "out",1); sends it to C.
You need to create those gates in Your ned file:
simple Txc
{
parameters:
#display("i=block/routing"); // add a default icon
gates:
input in1;
output out1;
input in2;
output out2;
}
network Tictoc
{
submodules:
tic: Txc {
parameters:
#display("i=,cyan");
}
toc: Txc {
parameters:
#display("i=,cyan");
}
toctic: Txc {
parameters:
#display("i=,cyan");
}
connections:
tic.out --> { delay = 100ms; } --> toc.in;
tic.in <-- { delay = 100ms; } <-- toc.out;
toctic.out2 --> { delay = 100ms; } --> toc.in2;
toctic.in2 <-- { delay = 100ms; } <-- toc.out2;
//....
}
With this You could send messages like this:
void computerf::forwardMessage(cMessage *msg)
{
int n = gateSize("out");
int k = intuniform(0,n-1);
send(msg, "out1", 1);
//Second message
send(msg, "out2", 1);
}
Hope this helps.
Best