Pull some processing out of environmentMutex critical sections

Move most string handling code out of the environmentMutex critical
sections to increase parallelism (Amdahl's Law).

I drew the line at temporarily dropping the mutex to allocate memory
for the return QByteArrays, as that would have meant to loop over
obtaining the size, allocating it, and then copying the data which
would have overly complicated the code.

Pick-to: 6.4
Change-Id: I980cbf7fda76fc8057f84b2539b4a299e06cae82
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Marc Mutz 2022-08-04 14:25:21 +02:00
parent c25cc34a05
commit 0beb58cf58
1 changed files with 12 additions and 4 deletions

View File

@ -108,17 +108,18 @@ QByteArray qgetenv(const char *varName)
QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
{
#if defined(Q_OS_WIN)
const auto locker = qt_scoped_lock(environmentMutex);
QVarLengthArray<wchar_t, 32> wname(qsizetype(strlen(varName)) + 1);
for (qsizetype i = 0; i < wname.size(); ++i) // wname.size() is correct: will copy terminating null
wname[i] = uchar(varName[i]);
size_t requiredSize = 0;
auto locker = qt_unique_lock(environmentMutex);
_wgetenv_s(&requiredSize, 0, 0, wname.data());
if (requiredSize == 0)
return defaultValue;
QString buffer(qsizetype(requiredSize), Qt::Uninitialized);
_wgetenv_s(&requiredSize, reinterpret_cast<wchar_t *>(buffer.data()), requiredSize,
wname.data());
locker.unlock();
// requiredSize includes the terminating null, which we don't want.
Q_ASSERT(buffer.endsWith(QChar(u'\0')));
buffer.chop(1);
@ -261,18 +262,22 @@ bool qEnvironmentVariableIsSet(const char *varName) noexcept
*/
bool qputenv(const char *varName, const QByteArray &value)
{
const auto locker = qt_scoped_lock(environmentMutex);
#if defined(Q_CC_MSVC)
const auto locker = qt_scoped_lock(environmentMutex);
return _putenv_s(varName, value.constData()) == 0;
#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_HAIKU)
// POSIX.1-2001 has setenv
const auto locker = qt_scoped_lock(environmentMutex);
return setenv(varName, value.constData(), true) == 0;
#else
QByteArray buffer(varName);
buffer += '=';
buffer += value;
char *envVar = qstrdup(buffer.constData());
int result = putenv(envVar);
int result = [&] {
const auto locker = qt_scoped_lock(environmentMutex);
return putenv(envVar);
}();
if (result != 0) // error. we have to delete the string.
delete[] envVar;
return result == 0;
@ -292,16 +297,18 @@ bool qputenv(const char *varName, const QByteArray &value)
*/
bool qunsetenv(const char *varName)
{
const auto locker = qt_scoped_lock(environmentMutex);
#if defined(Q_CC_MSVC)
const auto locker = qt_scoped_lock(environmentMutex);
return _putenv_s(varName, "") == 0;
#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_BSD4) || defined(Q_OS_HAIKU)
// POSIX.1-2001, BSD and Haiku have unsetenv
const auto locker = qt_scoped_lock(environmentMutex);
return unsetenv(varName) == 0;
#elif defined(Q_CC_MINGW)
// On mingw, putenv("var=") removes "var" from the environment
QByteArray buffer(varName);
buffer += '=';
const auto locker = qt_scoped_lock(environmentMutex);
return putenv(buffer.constData()) == 0;
#else
// Fallback to putenv("var=") which will insert an empty var into the
@ -309,6 +316,7 @@ bool qunsetenv(const char *varName)
QByteArray buffer(varName);
buffer += '=';
char *envVar = qstrdup(buffer.constData());
const auto locker = qt_scoped_lock(environmentMutex);
return putenv(envVar) == 0;
#endif
}