aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/utils/SkThreadUtils_pthread.cpp
diff options
context:
space:
mode:
authorGravatar bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-05-14 14:09:24 +0000
committerGravatar bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-05-14 14:09:24 +0000
commit554875210043b34178f7ed6ac5bd682b1fad367b (patch)
treefdadeb167ef502f98784117a3c05378c72fceeec /src/utils/SkThreadUtils_pthread.cpp
parentf105b109264f71dfb0bfd9977e6a5dd0a5a12f57 (diff)
Add bench and test for SkRefCnt.
http://codereview.appspot.com/6195071/ This also adds a cross platform SkThread for testing purposes. git-svn-id: http://skia.googlecode.com/svn/trunk@3921 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/utils/SkThreadUtils_pthread.cpp')
-rw-r--r--src/utils/SkThreadUtils_pthread.cpp105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/utils/SkThreadUtils_pthread.cpp b/src/utils/SkThreadUtils_pthread.cpp
new file mode 100644
index 0000000000..17a2075ab0
--- /dev/null
+++ b/src/utils/SkThreadUtils_pthread.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkTypes.h"
+
+#include "SkThreadUtils.h"
+#include "SkThreadUtils_pthread.h"
+
+#include <pthread.h>
+#include <signal.h>
+
+SkThread_PThreadData::SkThread_PThreadData(SkThread::entryPointProc entryPoint, void* data)
+ : fPThread()
+ , fValidPThread(false)
+ , fParam(data)
+ , fEntryPoint(entryPoint)
+ , fStarted(false)
+{
+ pthread_mutex_init(&fStartMutex, NULL);
+
+ pthread_cond_init(&fStartCondition, NULL);
+
+ pthread_attr_init(&fAttr);
+ pthread_attr_setdetachstate(&fAttr, PTHREAD_CREATE_JOINABLE);
+}
+SkThread_PThreadData::~SkThread_PThreadData() {
+ pthread_attr_destroy(&fAttr);
+ pthread_cond_destroy(&fStartCondition);
+ pthread_mutex_destroy(&fStartMutex);
+}
+
+static void* thread_start(void* arg) {
+ SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(arg);
+ //Wait for start signal
+ pthread_mutex_lock(&(pthreadData->fStartMutex));
+ while (!pthreadData->fStarted) {
+ pthread_cond_wait(&(pthreadData->fStartCondition), &(pthreadData->fStartMutex));
+ }
+ pthread_mutex_unlock(&(pthreadData->fStartMutex));
+
+ //See if this thread was canceled before starting.
+ pthread_testcancel();
+
+ pthreadData->fEntryPoint(pthreadData->fParam);
+ return NULL;
+}
+
+SkThread::SkThread(entryPointProc entryPoint, void* data) {
+ SkThread_PThreadData* pthreadData = new SkThread_PThreadData(entryPoint, data);
+ fData = pthreadData;
+
+ int ret = pthread_create(&(pthreadData->fPThread),
+ &(pthreadData->fAttr),
+ thread_start,
+ pthreadData);
+
+ pthreadData->fValidPThread = (0 == ret);
+}
+
+SkThread::~SkThread() {
+ if (fData != NULL) {
+ SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
+ // If created thread but start was never called, kill the thread.
+ if (pthreadData->fValidPThread && !pthreadData->fStarted) {
+ if (pthread_cancel(pthreadData->fPThread) == 0) {
+ if (this->start()) {
+ this->join();
+ }
+ } else {
+ //kill with prejudice
+ pthread_kill(pthreadData->fPThread, SIGKILL);
+ }
+ }
+ delete pthreadData;
+ }
+}
+
+bool SkThread::start() {
+ SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
+ if (!pthreadData->fValidPThread) {
+ return false;
+ }
+
+ if (pthreadData->fStarted) {
+ return false;
+ }
+ pthreadData->fStarted = true;
+ pthread_mutex_lock(&(pthreadData->fStartMutex));
+ pthread_cond_signal(&(pthreadData->fStartCondition));
+ pthread_mutex_unlock(&(pthreadData->fStartMutex));
+ return true;
+}
+
+void SkThread::join() {
+ SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
+ if (!pthreadData->fValidPThread || !pthreadData->fStarted) {
+ return;
+ }
+
+ pthread_join(pthreadData->fPThread, NULL);
+}