Solved Using QThreadStorage in any thread
-
I presume that it is safe to use on any operating system thread as Qt likely relies on the underlying platform support for TLS. (I.e., it doesn't have to be used on threads spawned via QThread.)
Is that correct?
Thanks!
-
@chopper Yes, as long as the operating system supports threads you can use them via QThread.
What do you mean by TLS in this context? -
Thread Local Storage (as opposed to Transport Layer Security ;) )
Thx!
This lets me create a QNetworkAccessManager allocator that returns an instance per thread and store that in a map of <threadID,QNAM*>, and because of QThreadStorage I can mark the thread and avoid the situation where a new thread reuses an old thread ID (Qt::HANDLE) and would otherwise get back a QNAM built for a different thread,
-
I thought I would double check, it turns out that's not correct @jsulm :
From qthreadstorage.cpp
void **QThreadStorageData::set(void *p) { QThreadData *data = QThreadData::current(); if (!data) { qWarning("QThreadStorage::set: QThreadStorage can only be used with threads started with QThread"); return 0; }
-
I'm trying, and testing, the following (requires C++ 11)
thread_local std::unique_ptr<QNetworkAccessManager> tls_pQNetworkAccessManager; QNetworkAccessManager *getQNetworkAccessManager( void ) { if( nullptr == tls_pQNetworkAccessManager ) { tls_pQNetworkAccessManager.reset( new QNetworkAccessManager() ); } return tls_pQNetworkAccessManager.get(); }
-
@chopper Do you really need one QNetworkAccessManager instance per thread?
-
Yes, this is utility code that could be used by any number of threads, and sharing a QNAM between threads requires forcing requests onto another thread - which is a potentially huge performance issue.
-
-
@Grove
Via C++ 11 support:thread_local std::unique_ptr<QNetworkAccessManager> tls_pQNetworkAccessManager; QNetworkAccessManager *getQNetworkAccessManager( void ) { if( nullptr == tls_pQNetworkAccessManager ) { tls_pQNetworkAccessManager.reset( new QNetworkAccessManager() ); } return tls_pQNetworkAccessManager.get(); }