I need to write an application using C++ which handles input signal from various sources and end up with something like this:
InputManager: handle input signals and convert them to messages.
Processor: it will receive all messages from the input. Put it in a
queue and operating one by one.
Other modules.
// define states of the instance
enum class State {
A,
B,
C,
....
};
// handle input message, all the message passed to the Processor queue should be redirect to this function.
void onInput(std::shared_ptr<Message> msg) {
switch(msg->mgsId) {
case 1:
// do something
break;
case 2:
// do something
break;
default:
break;
}
}
....
The thing is, the Processor Class getting bigger and bigger when the number of signals increases; and if I have to do something break the flow like waiting for a specific event before continue operating, the code becomes very hard to read.
I know it's a very newbie question. But I have no idea how to restructure my code in a readable way.
Use the following answer (which I took from a comment by Aconcagua):
I'd write one class per signal type, create one class instance per
concrete signal and have all of them keep a link to the single queue
instance. If you give the classes one common base class, you might
even put all of them into a single std::vector (not by value, though,
otherwise you run into object slicing). – Aconcagua
Related
I'm running some C++ code on an SDK that uses a switch statement for whenever particular events occur. I am working on the case that occurs when the signal strength of a bluetooth signal changes and it will report the new value back. I only want this to report back N times instead of continuously however, how could I achieve this?
case BLE_GAP_EVT_RSSI_CHANGED:
sd_ble_gap_rssi_get(p_ble_evt->evt.gap_evt.conn_handle, &RSSI);
printf("\nRSSI =%d dBm", RSSI);
break;
static int rssi_changed_counter = 0;
switch( /* ... */ ) {
// ...
case BLE_GAP_EVT_RSSI_CHANGED:
if(rssi_changed_counter < N) {
// ...
++rssi_changed_counter;
}
break;
// ...
}
This is not about bluetooth, or signals, or about making a case run N times.
This is about deactivating a piece of code after some condition has been met.
Your condition is that your code has been run through already, N times.
You want your code to do something different on the N+1th time (and, presumably, thereafter).
The best way to do this depends on code that we cannot see. It could be as simple as a counter and if statement. It could be the de-binding of a function pointer. It could be the removal of an event trigger from some third-party library. The choice is yours.
I've written my own access layer to a game engine. There is a GameLoop which gets called every frame which lets me process my own code. I'm able to do specific things and to check if these things happened. In a very basic way it could look like this:
void cycle()
{
//set a specific value
Engine::setText("Hello World");
//read the value
std::string text = Engine::getText();
}
I want to test if my Engine-layer is working by writing automated tests. I have some experience in using the Boost Unittest Framework for simple comparison tests like this.
The problem is, that some things I want the engine to do are just processed after the call to cycle(). So calling Engine::getText() directly after Engine::setText(...) would return an empty string. If I would wait until the next call of cycle() the right value would be returned.
I now am wondering how I should write my tests if it is not possible to process them in the same cycle. Are there any best practices? Is it possible to use the "traditional testing" approach given by Boost Unittest Framework in such an environment? Are there perhaps other frameworks aimed at such a specialised case?
I'm using C++ for everything here, but I could imagine that there are answers unrelated to the programming language.
UPDATE:
It is not possible to access the Engine outside of cycle()
In your example above, std::string text = Engine::getText(); is the code you want to remember from one cycle but execute in the next. You can save it for later execution. For example - using C++11 you could use a lambda to wrap the test into a simple function specified inline.
There are two options with you:
If the library that you have can be used synchronously or using c++11 futures like facility (which can indicate the readyness of the result) then in your test case you can do something as below
void testcycle()
{
//set a specific value
Engine::setText("Hello World");
while (!Engine::isResultReady());
//read the value
assert(Engine::getText() == "WHATEVERVALUEYOUEXPECT");
}
If you dont have the above the best you can do have a timeout (this is not a good option though because you may have spurious failures):
void testcycle()
{
//set a specific value
Engine::setText("Hello World");
while (Engine::getText() != "WHATEVERVALUEYOUEXPECT") {
wait(1 millisec);
if (total_wait_time > 1 sec) // you can put whatever max time
assert(0);
}
}
I have a TcpDevice class which encapsulates a TCP connection, which has an onRemoteDisconnect method which gets called whenever the remote end hangs up. Then, there's a SessionManager object which creates TcpSession objects which take a TcpDevice as a communication channel and inserts them in an internal pointer container for the application to use. In case any of the managed TcpSessions should end, I would like the SessionManager instance to be notified about it and then remove the corresponding session from the container, freeing up the resources associated with it.
I found my problem to be very similar to this question:
Object delete itself from container
but since he has a thread for checking the connections state, it gets a little different from mine and the way I intended to solve it using boost::signals, so I decided to go for a new question geared towards it - I apologize if it's the wrong way to do it... I'm still getting the feel on how to properly use S.O. :)
Since I'm kind of familiar with QT signals/slots, I found boost::signals offers a similar mechanism (I'm already using boost::asio and have no QT in this project), so I decided to implement a remoteDeviceDisconnected signal to be emitted by TcpDevice's onRemoteDisconnect, and for which I would have a slot in SessionManager, which would then delete the disconnected session and device from the container.
To initially try it out I declared the signal as a public member of TcpDevice in tcpdevice.hpp:
class TcpDevice
{
(...)
public:
boost::signal <void ()> remoteDeviceDisconnected;
(...)
}
Then I emitted it from TcpDevice's onRemoteDisconnect method like this:
remoteDeviceDisconnected();
Now, is there any way to connect this signal to my SessionManager slot from inside session manager? I tried this:
unsigned int SessionManager::createSession(TcpDevice* device)
{
unsigned int session_id = session_counter++;
boost::mutex::scoped_lock lock(sessions_mutex);
sessions.push_back(new TcpSession(device, session_id));
device->remoteDeviceDisconnected.connect(boost::bind(&SessionManager::removeDeadSessionSlot, this));
return session_id;
}
It compiles fine but at link time it complains of multiple definitions of remoteDeviceDisconnected in several object code files:
tcpsession.cpp.o:(.bss+0x0): multiple definition of `remoteDeviceDisconnected'
tcpdevice.cpp.o: (.bss+0x0): first defined here
sessionmanager.cpp.o:(.bss+0x0): multiple definition of `remoteDeviceDisconnected'
tcpdevice.cpp.o: (.bss+0x0): first defined here
I found this strange, since I didn't redefine the signal anywhere, but just used it at the createSession method above.
Any tips would be greatly appreciated! Thank you!
My bad! Like we all should expect, the linker was right... there was indeed a second definition, I just couldn't spot it right away because it wasn't defined by any of my classes, but just "floating" around one of my .cpp files, like those found on boost::signals examples.
Just for the record, the initial idea worked like a charm: when a given TcpDevice gets disconnected from the remote end, it emits the remoteDeviceDisconnected signal, which is then caught by the SessionManager object which holds the TcpSession instance that points to that TcpDevice. Once notified, SessionManager's method removeDeadSessionSlot gets executed, iterating through the sessions ptr_list container and removing the one which was disconnected:
void SessionManager::removeDeadSessionSlot()
{
boost::mutex::scoped_lock lock(sessions_mutex);
TcpSession_ptr_list_it it = sessions.begin();
while (it != sessions.end()) {
if (!(*it).device->isConnected())
it = sessions.erase(it);
else
++it;
}
}
Hope that may serve as a reference to somebody!
Recently I was listening to a tech talk on clean coding. The speaker was a test engineer, who emphasized on avoiding the "if" statements in the code and use polymorphism as much as possible. Also he advocated against global states.
I quite agree with him, yet i need a clarification on replacing the global state and "if" statement using polymorphism for the below scenario,
I have 3 states in my document. I want to change the state of the UI components based on the document state. Right now, i use "if" blocks and an enumeration type holding the current state of document to transition the states of UI components.
eg:
enum DOC_STATE
{
DOC_STATE_A = 0,
DOC_STATE_B,
DOC_STATE_C
};
void QMainWindow::handleUi(_docState)
{
switch(_docState)
{
case (DOC_STATE_A):
{
menu.disable();
....
}
case (DOC_STATE_B):
{
menu.enable();
...
}
case (DOC_STATE_C):
{
...
}
}
I think i can have separate child classes for each state and have the handleUI() method in each class. Calling handleUi() method calls the right method call. But say i maintain these objects in my doc, how do i switch from one object to other each time there is a transition in state?
In other words, how to handle UI transition by tracking the change in state of document without using a global state and "if" or Switch statements?
I use Qt. Thanks.
If you are using Qt, take a look at The Qt State Machine Framework and the State Machine Examples. No need to re-invent the wheel when your framework already provides a sports car :)
I don't think I understand the problem because the answer is too trivial: you replace the pointer to your state instance with a new state instance and discard the old one.
I've been trying to follow the principles of Dependency Injection, but after reading this article, I know I'm doing something wrong.
Here's my situation: My application receives different types of physical mail. All the incoming mail passes through my MailFunnel object.
While it's running, MailFunnel receives different types of messages from the outside: Box, Postcard and Magazine.
Each mail type needs to be handled differently. For example, if a Box comes in, I may need to record the weight before delivering it. Consequently, I have BoxHandler, PostcardHandler and MagazineHandler objects.
Each time a new message comes into my MailFunnel, I instantiate a new corresponding MailHandler object.
For example:
class MailFunnel
{
void NewMailArrived( Mail mail )
{
switch (mail.type)
{
case BOX:
BoxHandler * bob = new BoxHandler(shreddingPolicy, maxWeightPolicy);
bob->get_to_work();
break;
case POSTCARD:
PostcardHandler * frank = new PostcardHandler(coolPicturePolicy);
frank->get_to_work();
break;
case MAGAZINE:
MagazineHandler * nancy = new MagazineHandler(censorPolicy);
nancy->get_to_work();
break;
}
}
private:
MaxWeightPolcy & maxWeightPolicy;
ShreddingPolicy & shreddingPolicy;
CoolPicturePolicy & coolPicturePolicy;
CensorPolicy & censorPolicy;
}
On one hand, this is great because it means that if I get five different pieces of mail in, I immediately have five different MailHandlers working concurrently to take care of business. However, this also means that I'm mixing object creation with application logic - a big no-no when it comes to Dependency Injection.
Also, I have all these policy references hanging around in my MailFunnel object that MailFunnel really doesn't need. The only reason that MailFunnel has these objects is to pass them to the MailHandler constructors. Again, this is another thing I want to avoid.
All recommendations welcome. Thanks!
This looks more like a factory to me. Move the invocation of the get_to_work() method out of the invocation and return the handler. The pattern works pretty well for a factory.
class MailHandlerFactory
{
IMailHandler* GetHandler( Mail mail )
{
switch (mail.type)
{
case BOX:
return new BoxHandler(shreddingPolicy, maxWeightPolicy);
break;
case POSTCARD:
return new PostcardHandler(coolPicturePolicy);
break;
case MAGAZINE:
return new MagazineHandler(censorPolicy);
break;
}
}
private:
MaxWeightPolcy & maxWeightPolicy;
ShreddingPolicy & shreddingPolicy;
CoolPicturePolicy & coolPicturePolicy;
CensorPolicy & censorPolicy;
}
class MailFunnel
{
MailHandlerFactory* handlerFactory;
MailFunnel( MailHandlerFactory* factory ) {
handlerFactory = factory;
}
void NewMailArrived( Mail mail ) {
IMailHandler handler = handlerFactory.GetHandler(mail);
handler.get_to_work();
}
}
When you see that switch statement, think polymorphism. This design can only be extended by modification. I'd redo it in such a way that I could add new behavior by adding classes. It's what the open/closed principle is all about.
Why can't you just have three methods that are overloaded which take the different types of mail, and then do the appropriate thing? Or have each type handle itself.
In fact, if you have something like type, chances are you should in fact have different types.
Basically do the following:
1) Make the Mail class abstract.
2) Create a three sub classes of mail, Box, PostCard, and Magazine
3) Give each subclass a method to handle mail, or centralize it in a separate HandlerFactory
4) When passed to the mail funnel, simply have it call the handle mail method, or have the HandlerFactory pass it the mail, and get the appropriate handler back. Again, rather than having awkward switch statements everywhere, use the language, this is what types and method overloading is for.
If your mail handling becomes complex and you want to take it out, you can eventually make a mail handler class and extract those policies into that.
You can also consider using a template method, because the only real difference between each of those seems to be the handler you instance, maybe you could simplify it, such that the mail type determines the handler, the rest of the code is basically the same.
Interesting that you're applying dependency injection to a C++ project; it has been done elsewhere, a quick Google search finds a Google code project Autumn Framework.
But the answer by tvanfosson is what I would suggest trying first, before adopting a new framework.