// Copyright 2011 Google Inc. All Rights Reserved. // // Use of this source code is governed by a BSD-style license // that can be found in the COPYING file in the root of the source // tree. An additional intellectual property rights grant can be found // in the file PATENTS. All contributing project authors may // be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // // Multi-threaded worker // // Author: Skal (pascal.massimino@gmail.com)
#include <assert.h> #include <string.h> // for memset() #include"src/utils/thread_utils.h" #include"src/utils/utils.h"
staticint pthread_cond_signal(pthread_cond_t* const condition) { int ok = 1; #ifdef USE_WINDOWS_CONDITION_VARIABLE
WakeConditionVariable(condition); #else if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) { // a thread is waiting in pthread_cond_wait: allow it to be notified
ok = SetEvent(condition->signal_event_); // wait until the event is consumed so the signaler cannot consume // the event via its own pthread_cond_wait.
ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) !=
WAIT_OBJECT_0);
} #endif return !ok;
}
staticint pthread_cond_wait(pthread_cond_t* const condition,
pthread_mutex_t* const mutex) { int ok; #ifdef USE_WINDOWS_CONDITION_VARIABLE
ok = SleepConditionVariableCS(condition, mutex, INFINITE); #else // note that there is a consumer available so the signal isn't dropped in // pthread_cond_signal if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL)) return 1; // now unlock the mutex so pthread_cond_signal may be issued
pthread_mutex_unlock(mutex);
ok = (WaitForSingleObject(condition->signal_event_, INFINITE) ==
WAIT_OBJECT_0);
ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL);
pthread_mutex_lock(mutex); #endif return !ok;
}
static THREADFN ThreadLoop(void* ptr) {
WebPWorker* const worker = (WebPWorker*)ptr;
WebPWorkerImpl* const impl = (WebPWorkerImpl*)worker->impl_; int done = 0; while (!done) {
pthread_mutex_lock(&impl->mutex_); while (worker->status_ == OK) { // wait in idling mode
pthread_cond_wait(&impl->condition_, &impl->mutex_);
} if (worker->status_ == WORK) {
WebPGetWorkerInterface()->Execute(worker);
worker->status_ = OK;
} elseif (worker->status_ == NOT_OK) { // finish the worker
done = 1;
} // signal to the main thread that we're done (for Sync()) // Note the associated mutex does not need to be held when signaling the // condition. Unlocking the mutex first may improve performance in some // implementations, avoiding the case where the waiting thread can't // reacquire the mutex when woken.
pthread_mutex_unlock(&impl->mutex_);
pthread_cond_signal(&impl->condition_);
} return THREAD_RETURN(NULL); // Thread is finished
}
// main thread state control staticvoid ChangeState(WebPWorker* const worker, WebPWorkerStatus new_status) { // No-op when attempting to change state on a thread that didn't come up. // Checking status_ without acquiring the lock first would result in a data // race.
WebPWorkerImpl* const impl = (WebPWorkerImpl*)worker->impl_; if (impl == NULL) return;
pthread_mutex_lock(&impl->mutex_); if (worker->status_ >= OK) { // wait for the worker to finish while (worker->status_ != OK) {
pthread_cond_wait(&impl->condition_, &impl->mutex_);
} // assign new status and release the working thread if needed if (new_status != OK) {
worker->status_ = new_status; // Note the associated mutex does not need to be held when signaling the // condition. Unlocking the mutex first may improve performance in some // implementations, avoiding the case where the waiting thread can't // reacquire the mutex when woken.
pthread_mutex_unlock(&impl->mutex_);
pthread_cond_signal(&impl->condition_); return;
}
}
pthread_mutex_unlock(&impl->mutex_);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.