Results 1 to 9 of 9

Thread: Advice sought on signal handling design

  1. #1
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Advice sought on signal handling design

    I have a class that deals with QNetworkReply instances and emits different signals of the same signature template void signalEmit(instance*):

    Qt Code:
    1. class signalHandler
    2. {
    3. signals:
    4. void onRequestComplete (classA* request);
    5. void onRequestComplete (classB* request);
    6. void onRequestComplete (classC* request);
    7. …
    8. }
    To copy to clipboard, switch view to plain text mode 

    Where classA, classB, classC etc are all descendants of classRoot and QObject

    Selection of the appropritate signal is done like this:

    Qt Code:
    1. classRoot* r= reinterpret_cast< classRoot*>(reply->request().originatingObject());
    2. if (dynamic_cast<classA*>(r) != 0)
    3. {
    4. classA * r= reinterpret_cast< classA*>(reply->request().originatingObject());
    5. emit requestIsCompleted (r);
    6. }
    7. else if (dynamic_cast<classB*>(r) != 0)
    8. {
    9. classB * r= reinterpret_cast< classB*>(reply->request().originatingObject());
    10. emit requestIsCompleted (r);
    11. }
    To copy to clipboard, switch view to plain text mode 
    …

    There are numerous problems in this design. First of all, the giant switch code. Next, types of classA, classB, classC are growing as I am adding more and more network request/response functionality. Usage of templates with QObject-descendant classes are forbidden.

    I’d like to be able to “register” classA, classB types with signalHandler and let it deal with routing and emitting appropriate signal without modifying signalHandler for each new classX type.

    Any advise will be greatly appreciated.

  2. #2
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Advice sought on signal handling design

    Have a look at QSignalMapper.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  3. The following user says thank you to high_flyer for this useful post:

    TorAn (8th April 2011)

  4. #3
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Advice sought on signal handling design

    Thanks, high_flyer.

    I am evaluating QSignalMapper for the usage in my scenario. I'll post results here.

  5. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Advice sought on signal handling design

    You could also use double dispatch.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  6. #5
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Advice sought on signal handling design

    My original question was raised after reviewing my own implementation of webservice requests and handling responses.

    Following is a pseudo-code for my current implementation

    Qt Code:
    1. class classRoot : public QObject {};
    2. class classA :public classRoot{};
    3. class classB :public classRoot{};
    4. class classC :public classRoot{};
    5.  
    6. class requestTransport : public QObject
    7. {
    8. signals:
    9. void onRequestComplete (classA* request);
    10. void onRequestComplete (classB* request);
    11. void onRequestComplete (classC* request);
    12. }
    13.  
    14. class responseProcessor : public QObject
    15. {
    16. public slots:
    17. void requestCompleted (classA* request);
    18. void requestCompleted (classB* request);
    19. void requestCompleted (classC* request);
    20. };
    21.  
    22. void main()
    23. {
    24. requestTransport st;
    25. responseProcessor rp;
    26.  
    27. connect(&st, SIGNAL(onRequestComplete(classA*)), &rp, SLOT(requestCompleted(classA*)));
    28. ...
    29. connect(&st, SIGNAL(onRequestComplete(classC*)), &rp, SLOT(requestCompleted(classC*)));
    30. }
    To copy to clipboard, switch view to plain text mode 


    The advantage of this design is that there is explicit contract between requestTransport and responseProcessor for each type of request.
    The major problem with the design is that it does not scale. Each new request type requires change in requestTransport, responseProcessor and main
    in respect to the signal/slot connectivity

    I am trying to find out if I can have something like the pseudo-code below. QSignalMapper, as far as I can see, cannot be used for this purpose

    Qt Code:
    1. class requestTransport
    2. {
    3. public:
    4. template<typename T> registerRequestType();
    5. template<typename T> addRequest(T* request);
    6. private signals:
    7. void onRequestComplete(classRoot* request);
    8. }
    9.  
    10. void main()
    11. {
    12. requestTransport st;
    13. responseProcessor rp;
    14.  
    15. // following three lines register request types with signal Transport. Each call performs QObject::connect or some other
    16. // metaobject call to wire onRequestComplete signal to the appropriate requestCompleted slot in responseProcessor instance
    17. st.registerRequestType<classA> (&rp);
    18. st.registerRequestType<classB> (&rp);
    19. st.registerRequestType<classC> (&rp);
    20.  
    21. // this line adds new instance of the request to be sent via Transport. Upon completion the appropriate slot in the responseProcessor
    22. // should be called.
    23. st.addRequest<classB>(new classB());
    24. }
    To copy to clipboard, switch view to plain text mode 

    The main advantage for me is that for every new type of request I have to only add new slot handler and register request type with the transport
    It also adds clarity to the code, making visible the types of requests the transport is processing.

    I don't care if it is templates or other technique, I want to know if it is possible to implement it Qt-way.

    Any advice/discussion/solution will be greatly appreciated.

  7. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Advice sought on signal handling design

    As I already said, I'd probably use double-dispatch here. Or maybe some QMetaObject magic.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  8. #7
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Advice sought on signal handling design

    Wysota, how would you handle the runtime types of double-dispatch ? Use the methods of QObject ?

  9. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Advice sought on signal handling design

    The original example used dynamic_cast. If you see a dynamic cast, that's usually a candidate for double-dispatch. The "signalHandler" class already looks like it was prepared for double-dispatch, only "the other way round" - the class should have slots and not signals. Then you can use something similar to the visitor pattern to perform double-dispatch.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  10. #9
    Join Date
    Nov 2009
    Location
    US, Midwest
    Posts
    215
    Thanks
    62
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Advice sought on signal handling design

    Solution is found.

    It is indeed, as Wysota puts it - "a QMetaObject magic". The issue was discussed and published here, it also includes working example.

Similar Threads

  1. Thread design advice needed
    By jonks in forum Qt Programming
    Replies: 3
    Last Post: 22nd October 2009, 21:32
  2. advise sought on TreeView model design
    By QPlace in forum Qt Programming
    Replies: 0
    Last Post: 25th June 2009, 14:36
  3. Replies: 1
    Last Post: 7th August 2008, 14:49
  4. Request Qwt histogram design advice
    By goes2bob in forum Qwt
    Replies: 1
    Last Post: 10th April 2008, 10:12
  5. Need some advice for design decision
    By BeS in forum Qt Programming
    Replies: 2
    Last Post: 28th March 2006, 23:06

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.