Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Make QNetworkAccessManager threadsafe
Forum Updated to NodeBB v4.3 + New Features

Make QNetworkAccessManager threadsafe

Scheduled Pinned Locked Moved Solved General and Desktop
13 Posts 4 Posters 4.6k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Phoenox
    20 Dec 2016, 12:50

    Hello everyone,

    in my application, I'm using a QNetworkAccessManager (cached and with a QNetworkCookieJar).
    The documentation mentions that QNetworkAccessManager is just reentrant, not threadsafe.
    This SO post also says that if using multiple threads, one should use one instance per thread.

    Question 1: Is this correct? It seems a bit counter-intuitive that I have to create multiple instances of a QNetworkAccessManager for multi-threaded applications, although the documentation also mentions that "One QNetworkAccessManager should be enough for the whole Qt application."

    If the QNetworkAccessManager is indeed just reentrant, my plan is to work around this limitation by running just one QNetworkAccessManager in a dedicated thread, which is managed by a threadsafe object. Requests would then only be sent through this threadsafe object.

    Question 2: Is this feasible? Is there an easier solution? My only requirements are that I want to have only one instance of the QNetworkAccessManager and still use it from different threads.

    Cheers
    PhoeNox

    K Offline
    K Offline
    kshegunov
    Moderators
    wrote on 20 Dec 2016, 18:54 last edited by
    #4

    @Phoenox said in Make QNetworkAccessManager threadsafe:

    Question 1: Is this correct?

    Yes, that's correct. NAM uses threading internally though.

    Question 2: Is this feasible?

    It's a good plan. However you can just use plain ol' signal and slots instead of using your own thread-safe wrapper around the (single) NAM instance.

    @Buckwheat said in Make QNetworkAccessManager threadsafe:

    Typically "re-entrant" implies thread-safe as variables are on the stack and do not interfere with each other.

    Not exactly. Reentrant literally means a thread can be interrupted and then the reentry can be made without side effects. This implies that the variables are thread-local (independent of stack or heap), i.e. there are no globals to take care of.

    Read and abide by the Qt Code of Conduct

    1 Reply Last reply
    3
    • B Offline
      B Offline
      Buckwheat
      wrote on 20 Dec 2016, 19:11 last edited by
      #5

      @kshegunov ... correct. but add... there are no side-effects if invoked again before the last invocation finishes. Hence no static (global) members. The safest way is still to use mutexing and protect yourself.

      Dave Fileccia

      K 1 Reply Last reply 20 Dec 2016, 22:46
      0
      • B Buckwheat
        20 Dec 2016, 19:11

        @kshegunov ... correct. but add... there are no side-effects if invoked again before the last invocation finishes. Hence no static (global) members. The safest way is still to use mutexing and protect yourself.

        K Offline
        K Offline
        kshegunov
        Moderators
        wrote on 20 Dec 2016, 22:46 last edited by
        #6

        @Buckwheat said in Make QNetworkAccessManager threadsafe:

        ... correct. but add...

        No "but". It means safe for re-entry. It doesn't include "if invoked again". A global may be modified from anywhere, and a thread context switch can happen (almost) anywhere, so there's no reason to think that there's need for a condition to be put to the function to be called a second time.

        Read and abide by the Qt Code of Conduct

        1 Reply Last reply
        0
        • B Offline
          B Offline
          Buckwheat
          wrote on 21 Dec 2016, 13:08 last edited by
          #7

          @kshegunov ...

          https://en.wikipedia.org/wiki/Reentrancy_(computing)

          Reentrancy (computing) In computing, a computer program or subroutine is called reentrant if it can be interrupted in the middle of its execution, and then be safely called again ("re-entered") before its previous invocations complete execution.

          That is the definition I grew up in computing when concurrency was a nifty trick and threads were not part of the OS. So, both are correct. I had already mentioned the exception of globals. So, no need to be angry and snotty.

          Dave Fileccia

          K 1 Reply Last reply 21 Dec 2016, 13:20
          0
          • B Buckwheat
            21 Dec 2016, 13:08

            @kshegunov ...

            https://en.wikipedia.org/wiki/Reentrancy_(computing)

            Reentrancy (computing) In computing, a computer program or subroutine is called reentrant if it can be interrupted in the middle of its execution, and then be safely called again ("re-entered") before its previous invocations complete execution.

            That is the definition I grew up in computing when concurrency was a nifty trick and threads were not part of the OS. So, both are correct. I had already mentioned the exception of globals. So, no need to be angry and snotty.

            K Offline
            K Offline
            kshegunov
            Moderators
            wrote on 21 Dec 2016, 13:20 last edited by
            #8

            @Buckwheat

            So, no need to be angry and snotty.

            Not intended as such, sorry if it was perceived this way. I meant the following (real code):

            int testFunction()
            {
                int x = 0;
                return x + 5;
            }
            

            leading to:

                        11 [1]	{
            0x5555555568f0                   55                    push   %rbp
            0x5555555568f1  <+0x0001>        48 89 e5              mov    %rsp,%rbp
                    12 [1]	    int x = 0;
            0x5555555568f4  <+0x0004>        c7 45 fc 00 00 00 00  movl   $0x0,-0x4(%rbp)
                    13 [1]	    return x + 5;
            0x5555555568fb  <+0x000b>        8b 45 fc              mov    -0x4(%rbp),%eax
            0x5555555568fe  <+0x000e>        83 c0 05              add    $0x5,%eax
                    14 [1]	}
            0x555555556901  <+0x0011>        5d                    pop    %rbp
            0x555555556902  <+0x0012>        c3                    retq
            

            This function can be thought reentrant if a thread breaks after the movl $0x0,-0x4(%rbp) and when re-entering it can execute mov -0x4(%rbp),%eax without side effects, which is the implication that another thread can't (or will not) modify -0x4(%rbp) while the former is sleeping. And since one can't control where context switches are done, we get the implication that globals break reentrancy. So that's what I meant by It doesn't include "if invoked again".

            Kind regards.

            Read and abide by the Qt Code of Conduct

            1 Reply Last reply
            0
            • B Offline
              B Offline
              Buckwheat
              wrote on 21 Dec 2016, 13:32 last edited by
              #9

              @kshegunov ... I said globals are bad: "That being said, if there are static methods being called using static members than that can cause problems." I hate to date myself, but I was writing machine guidance and avionics before you were actually born! LOL!

              Dave Fileccia

              K B 2 Replies Last reply 21 Dec 2016, 13:38
              0
              • B Buckwheat
                21 Dec 2016, 13:32

                @kshegunov ... I said globals are bad: "That being said, if there are static methods being called using static members than that can cause problems." I hate to date myself, but I was writing machine guidance and avionics before you were actually born! LOL!

                K Offline
                K Offline
                kshegunov
                Moderators
                wrote on 21 Dec 2016, 13:38 last edited by
                #10

                @Buckwheat said in Make QNetworkAccessManager threadsafe:

                I said globals are bad

                Never claimed you hadn't. I was just expanding on my comment, making it clearer what I meant, or at least I hope.

                Read and abide by the Qt Code of Conduct

                1 Reply Last reply
                0
                • B Buckwheat
                  21 Dec 2016, 13:32

                  @kshegunov ... I said globals are bad: "That being said, if there are static methods being called using static members than that can cause problems." I hate to date myself, but I was writing machine guidance and avionics before you were actually born! LOL!

                  B Offline
                  B Offline
                  Buckwheat
                  wrote on 21 Dec 2016, 13:38 last edited by
                  #11

                  @kshegunov ... I said globals are bad: "That being said, if there are static methods being called using static members than that can cause problems."

                  One more thing. Your example is always re-entrant and always thread-safe no matter what circumstances because it is all stack/frame pointer based. So it proves the point I was making. Only in languages like FORTRAN where all variables are static would there be a problem. But you can also make some really cool design strategies with it.

                  Dave Fileccia

                  1 Reply Last reply
                  0
                  • B Offline
                    B Offline
                    Buckwheat
                    wrote on 21 Dec 2016, 13:39 last edited by
                    #12

                    @kshegunov ... OK. It is hard to have tech discussions like this. A large cup of coffee and a nice Xtreme session would be ideal :D

                    Dave Fileccia

                    1 Reply Last reply
                    1
                    • P Offline
                      P Offline
                      Phoenox
                      wrote on 2 Jan 2017, 13:36 last edited by
                      #13

                      Okay, I just protected my single instance of the QNetworkAccessManager with mutexes, as @Buckwheat suggested.
                      Until now, I'm not experiencing any problems.

                      Thanks everyone for the tips and the clarification on reentrancy/thread-safety.

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved