mirror of
https://bitbucket.org/smil3y/katie.git
synced 2025-02-24 19:02:59 +00:00
effectively revert QWaitCondition changes
Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
This commit is contained in:
parent
8e18728348
commit
53aa704af0
2 changed files with 78 additions and 29 deletions
|
@ -25,6 +25,12 @@ static inline QString fromstrerror_helper(const char *str, const QByteArray &)
|
|||
}
|
||||
#endif
|
||||
|
||||
static inline void report_error(int code, const char *where, const char *what)
|
||||
{
|
||||
if (code != 0)
|
||||
qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QCORECOMMON_P_H
|
||||
|
|
|
@ -31,13 +31,16 @@
|
|||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qplatformdefs.h"
|
||||
#include "qwaitcondition.h"
|
||||
#include "qmutex.h"
|
||||
#include "qreadwritelock.h"
|
||||
#include "qatomic.h"
|
||||
#include "qstring.h"
|
||||
#include "qreadwritelock_p.h"
|
||||
#include "qcorecommon_p.h"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <chrono>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef QT_NO_THREAD
|
||||
|
||||
|
@ -45,32 +48,83 @@ QT_BEGIN_NAMESPACE
|
|||
|
||||
class QWaitConditionPrivate {
|
||||
public:
|
||||
std::mutex mutex;
|
||||
std::condition_variable cond;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
int waiters;
|
||||
int wakeups;
|
||||
|
||||
bool wait(unsigned long time)
|
||||
{
|
||||
int code;
|
||||
forever {
|
||||
if (time != ULONG_MAX) {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, Q_NULLPTR);
|
||||
|
||||
timespec ti;
|
||||
ti.tv_nsec = (tv.tv_usec + (time % 1000) * 1000) * 1000;
|
||||
ti.tv_sec = tv.tv_sec + (time / 1000) + (ti.tv_nsec / 1000000000);
|
||||
ti.tv_nsec %= 1000000000;
|
||||
|
||||
code = pthread_cond_timedwait(&cond, &mutex, &ti);
|
||||
} else {
|
||||
code = pthread_cond_wait(&cond, &mutex);
|
||||
}
|
||||
if (code == 0 && wakeups == 0) {
|
||||
// many vendors warn of spurios wakeups from
|
||||
// pthread_cond_wait(), especially after signal delivery,
|
||||
// even though POSIX doesn't allow for it... sigh
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Q_ASSERT_X(waiters > 0, "QWaitCondition::wait", "internal error (waiters)");
|
||||
--waiters;
|
||||
if (code == 0) {
|
||||
Q_ASSERT_X(wakeups > 0, "QWaitCondition::wait", "internal error (wakeups)");
|
||||
--wakeups;
|
||||
}
|
||||
report_error(pthread_mutex_unlock(&mutex), "QWaitCondition::wait()", "mutex unlock");
|
||||
|
||||
if (code && code != ETIMEDOUT)
|
||||
report_error(code, "QWaitCondition::wait()", "cv wait");
|
||||
|
||||
return (code == 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
QWaitCondition::QWaitCondition()
|
||||
: d(new QWaitConditionPrivate)
|
||||
{
|
||||
d = new QWaitConditionPrivate;
|
||||
report_error(pthread_mutex_init(&d->mutex, NULL), "QWaitCondition", "mutex init");
|
||||
report_error(pthread_cond_init(&d->cond, NULL), "QWaitCondition", "cv init");
|
||||
d->waiters = d->wakeups = 0;
|
||||
}
|
||||
|
||||
|
||||
QWaitCondition::~QWaitCondition()
|
||||
{
|
||||
report_error(pthread_cond_destroy(&d->cond), "QWaitCondition", "cv destroy");
|
||||
report_error(pthread_mutex_destroy(&d->mutex), "QWaitCondition", "mutex destroy");
|
||||
delete d;
|
||||
}
|
||||
|
||||
void QWaitCondition::wakeOne()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(d->mutex);
|
||||
d->cond.notify_one();
|
||||
report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wakeOne()", "mutex lock");
|
||||
d->wakeups = qMin(d->wakeups + 1, d->waiters);
|
||||
report_error(pthread_cond_signal(&d->cond), "QWaitCondition::wakeOne()", "cv signal");
|
||||
report_error(pthread_mutex_unlock(&d->mutex), "QWaitCondition::wakeOne()", "mutex unlock");
|
||||
}
|
||||
|
||||
void QWaitCondition::wakeAll()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(d->mutex);
|
||||
d->cond.notify_all();
|
||||
report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wakeAll()", "mutex lock");
|
||||
d->wakeups = d->waiters;
|
||||
report_error(pthread_cond_broadcast(&d->cond), "QWaitCondition::wakeAll()", "cv broadcast");
|
||||
report_error(pthread_mutex_unlock(&d->mutex), "QWaitCondition::wakeAll()", "mutex unlock");
|
||||
}
|
||||
|
||||
bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
|
||||
|
@ -82,21 +136,15 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
|
|||
return false;
|
||||
}
|
||||
|
||||
report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wait()", "mutex lock");
|
||||
++d->waiters;
|
||||
mutex->unlock();
|
||||
|
||||
std::unique_lock<std::mutex> lock(d->mutex);
|
||||
|
||||
std::cv_status returnValue;
|
||||
if (time != ULONG_MAX) {
|
||||
returnValue = d->cond.wait_for(lock, std::chrono::milliseconds(time));
|
||||
} else {
|
||||
returnValue = std::cv_status::no_timeout;
|
||||
d->cond.wait(lock);
|
||||
}
|
||||
bool returnValue = d->wait(time);
|
||||
|
||||
mutex->lock();
|
||||
|
||||
return returnValue == std::cv_status::no_timeout;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
|
||||
|
@ -108,25 +156,20 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
|
|||
return false;
|
||||
}
|
||||
|
||||
report_error(pthread_mutex_lock(&d->mutex), "QWaitCondition::wait()", "mutex lock");
|
||||
++d->waiters;
|
||||
|
||||
int previousAccessCount = readWriteLock->d->accessCount;
|
||||
readWriteLock->unlock();
|
||||
|
||||
std::unique_lock<std::mutex> lock(d->mutex);
|
||||
|
||||
std::cv_status returnValue;
|
||||
if (time != ULONG_MAX) {
|
||||
returnValue = d->cond.wait_for(lock, std::chrono::milliseconds(time));
|
||||
} else {
|
||||
returnValue = std::cv_status::no_timeout;
|
||||
d->cond.wait(lock);
|
||||
}
|
||||
bool returnValue = d->wait(time);
|
||||
|
||||
if (previousAccessCount < 0)
|
||||
readWriteLock->lockForWrite();
|
||||
else
|
||||
readWriteLock->lockForRead();
|
||||
|
||||
return returnValue == std::cv_status::no_timeout;
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
Loading…
Add table
Reference in a new issue