123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- /*=============================================================================
- Library: CTK
- Copyright (c) German Cancer Research Center,
- Division of Medical and Biological Informatics
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- =============================================================================*/
- #include "ctkEACyclicBarrier_p.h"
- // for ctk::msecsTo() - remove after switching to Qt 4.7
- #include <ctkUtils.h>
- #include <QDateTime>
- #include <QRunnable>
- #include <QDebug>
- #include <dispatch/ctkEAInterruptibleThread_p.h>
- #include <dispatch/ctkEAInterruptedException_p.h>
- #include "ctkEATimeoutException_p.h"
- #include "ctkEABrokenBarrierException_p.h"
- ctkEACyclicBarrier::ctkEACyclicBarrier(int parties, ctkEARunnable* command)
- : parties_(parties), broken_(false), barrierCommand_(command),
- count_(parties), resets_(0)
- {
- if (parties <= 0) throw ctkInvalidArgumentException("parties cannot be negative");
- if (barrierCommand_) ++barrierCommand_->ref;
- }
- ctkEARunnable* ctkEACyclicBarrier::setBarrierCommand(ctkEARunnable* command)
- {
- QMutexLocker lock(&mutex);
- ctkEARunnable* old = barrierCommand_;
- --old->ref;
- barrierCommand_ = command;
- ++barrierCommand_->ref;
- return old;
- }
- bool ctkEACyclicBarrier::broken() const
- {
- QMutexLocker lock(&mutex);
- return broken_;
- }
- void ctkEACyclicBarrier::restart()
- {
- QMutexLocker lock(&mutex);
- broken_ = false;
- ++resets_;
- count_ = parties_;
- waitCond.wakeAll();
- }
- int ctkEACyclicBarrier::parties() const
- {
- return parties_;
- }
- int ctkEACyclicBarrier::barrier()
- {
- return doBarrier(false, 0);
- }
- int ctkEACyclicBarrier::attemptBarrier(long msecs)
- {
- return doBarrier(true, msecs);
- }
- int ctkEACyclicBarrier::doBarrier(bool timed, long msecs)
- {
- QMutexLocker lock(&mutex);
- int index = --count_;
- ctkEAInterruptibleThread* currThread = ctkEAInterruptibleThread::currentThread();
- Q_ASSERT(currThread != 0); // ctkEACyclicBarrier can only be used with ctkEAInterruptibleThread
-
- if (broken_)
- {
- throw ctkEABrokenBarrierException(index);
- }
- else if (ctkEAInterruptibleThread::interrupted())
- {
- broken_ = true;
- waitCond.wakeAll();
- throw ctkEAInterruptedException();
- }
- else if (index == 0)
- { // tripped
- count_ = parties_;
- ++resets_;
- waitCond.wakeAll();
- try
- {
- if (barrierCommand_)
- {
- const bool autoDelete = barrierCommand_->autoDelete();
- barrierCommand_->run();
- if (autoDelete && !--barrierCommand_->ref) delete barrierCommand_;
- }
- return 0;
- }
- catch (...)
- {
- broken_ = true;
- return 0;
- }
- }
- else if (timed && msecs <= 0)
- {
- broken_ = true;
- waitCond.wakeAll();
- throw ctkEATimeoutException(msecs);
- }
- else
- { // wait until next reset
- int r = resets_;
- QDateTime startTime = QDateTime::currentDateTime();
- qint64 waitTime = static_cast<qint64>(msecs);
- forever
- {
- try
- {
- currThread->wait(&mutex, &waitCond, waitTime);
- }
- catch (const ctkEAInterruptedException& ex)
- {
- mutex.lock();
- // Only claim that broken if interrupted before reset
- if (resets_ == r)
- {
- broken_ = true;
- waitCond.wakeAll();
- throw ex;
- }
- else
- {
- currThread->interrupt(); // propagate
- }
- }
- if (broken_)
- {
- throw ctkEABrokenBarrierException(index);
- }
- else if (r != resets_)
- {
- return index;
- }
- else if (timed)
- {
- //TODO use Qt 4.7 API
- //waitTime = msecs - QDateTime::toMSecs(startTime);
- waitTime = static_cast<qint64>(msecs) - ctk::msecsTo(startTime, QDateTime::currentDateTime());
- if (waitTime <= 0)
- {
- broken_ = true;
- waitCond.wakeAll();
- throw ctkEATimeoutException(msecs);
- }
- }
- }
- }
- return 0; // will never be reached
- }
|