123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- /*=============================================================================
- 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 "ctkEALinkedQueue_p.h"
- #include "ctkEAInterruptibleThread_p.h"
- #include "ctkEAInterruptedException_p.h"
- // for ctk::msecsTo() - remove after switching to Qt 4.7
- #include <ctkUtils.h>
- #include <QDateTime>
- ctkEALinkedQueue::ctkEALinkedQueue()
- : head_(new ctkEALinkedNode()), last_(head_), waitingForTake_(0)
- {
- }
- ctkEALinkedQueue::~ctkEALinkedQueue()
- {
- delete head_;
- }
- void ctkEALinkedQueue::put(ctkEARunnable* x)
- {
- if (x == 0) throw ctkInvalidArgumentException("QRunnable cannot be null");
- if (ctkEAInterruptibleThread::interrupted()) throw ctkEAInterruptedException();
- insert(x);
- }
- bool ctkEALinkedQueue::offer(ctkEARunnable* x, long msecs)
- {
- Q_UNUSED(msecs)
- if (x == 0) throw ctkInvalidArgumentException("QRunnable cannot be null");
- if (ctkEAInterruptibleThread::interrupted()) throw ctkEAInterruptedException();
- insert(x);
- return true;
- }
- ctkEARunnable* ctkEALinkedQueue::take()
- {
- if (ctkEAInterruptibleThread::interrupted()) throw ctkEAInterruptedException();
- // try to extract. If fail, then enter wait-based retry loop
- ctkEARunnable* x = extract();
- if (x != 0)
- return x;
- else
- {
- {
- QMutexLocker l(&putLock_);
- try
- {
- ++waitingForTake_;
- forever
- {
- x = extract();
- if (x != 0)
- {
- --waitingForTake_;
- return x;
- }
- else
- {
- ctkEAInterruptibleThread::currentThread()->wait(&putLock_, &putLockWait_);
- }
- }
- }
- catch(const ctkEAInterruptedException& ex)
- {
- --waitingForTake_;
- if (x && x->autoDelete() && !--x->ref) delete x;
- putLockWait_.wakeOne();
- throw ex;
- }
- }
- }
- }
- ctkEARunnable* ctkEALinkedQueue::peek() const
- {
- QMutexLocker l(&headLock_);
- ctkEALinkedNode* first = head_->next;
- if (first)
- return first->value;
- else
- return 0;
- }
- bool ctkEALinkedQueue::isEmpty() const
- {
- QMutexLocker l(&headLock_);
- return !(head_->next);
- }
- ctkEARunnable* ctkEALinkedQueue::poll(long msecs)
- {
- if (ctkEAInterruptibleThread::interrupted()) throw ctkEAInterruptedException();
- ctkEARunnable* x = extract();
- if (x != 0)
- return x;
- else
- {
- QMutexLocker l(&putLock_);
- try {
- qint64 waitTime = static_cast<qint64>(msecs);
- //TODO Use Qt4.7 API
- //long start = (msecs <= 0)? 0 : System.currentTimeMillis();
- QDateTime start = QDateTime::currentDateTime();
- ++waitingForTake_;
- forever
- {
- x = extract();
- if (x != 0 || waitTime <= 0)
- {
- --waitingForTake_;
- return x;
- }
- else
- {
- ctkEAInterruptibleThread::currentThread()->wait(&putLock_, &putLockWait_, waitTime);
- //waitTime = msecs - (System.currentTimeMillis() - start);
- waitTime = static_cast<qint64>(msecs) - ctk::msecsTo(start, QDateTime::currentDateTime());
- }
- }
- }
- catch(const ctkEAInterruptedException& ex)
- {
- --waitingForTake_;
- if (x && x->autoDelete() && !--x->ref) delete x;
- putLockWait_.wakeOne();
- throw ex;
- }
- }
- }
- void ctkEALinkedQueue::insert(ctkEARunnable* x)
- {
- QMutexLocker l(&putLock_);
- ctkEALinkedNode* p = new ctkEALinkedNode(x);
- {
- QMutexLocker l2(&lastLock_);
- last_->next = p;
- last_ = p;
- }
- if (waitingForTake_ > 0)
- {
- putLockWait_.wakeOne();
- }
- }
- ctkEARunnable* ctkEALinkedQueue::extract()
- {
- QMutexLocker lock(&mutex_);
- {
- QMutexLocker l(&headLock_);
- ctkEARunnable* x = 0;
- ctkEALinkedNode* first(head_->next);
- if (first)
- {
- x = first->value;
- first->value = 0;
- delete head_;
- head_ = first;
- }
- return x;
- }
- }
|