diff options
Diffstat (limited to 'libsgl/ports/SkOSEvent_android.cpp')
-rw-r--r-- | libsgl/ports/SkOSEvent_android.cpp | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/libsgl/ports/SkOSEvent_android.cpp b/libsgl/ports/SkOSEvent_android.cpp new file mode 100644 index 0000000..59d6191 --- /dev/null +++ b/libsgl/ports/SkOSEvent_android.cpp @@ -0,0 +1,155 @@ +/* libs/graphics/ports/SkOSEvent_android.cpp +** +** Copyright 2006, The Android Open Source Project +** +** 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 "SkEvent.h" +#include "utils/threads.h" +#include <stdio.h> + +using namespace android; + +Mutex gEventQMutex; +Condition gEventQCondition; + +void SkEvent::SignalNonEmptyQueue() +{ + gEventQCondition.broadcast(); +} + +/////////////////////////////////////////////////////////////////// + +#ifdef FMS_ARCH_ANDROID_ARM + +// don't have pthreads.h, and therefore no timedwait(), so we punt for the demo + +void SkEvent::SignalQueueTimer(SkMSec delay) +{ +} + +void SkEvent_start_timer_thread() +{ +} + +void SkEvent_stop_timer_thread() +{ +} + +#else + +#include <pthread.h> +#include <errno.h> + +static pthread_t gTimerThread; +static pthread_mutex_t gTimerMutex; +static pthread_cond_t gTimerCond; +static timespec gTimeSpec; + +static void* timer_event_thread_proc(void*) +{ + for (;;) + { + int status; + + pthread_mutex_lock(&gTimerMutex); + + timespec spec = gTimeSpec; + // mark our global to be zero + // so we don't call timedwait again on a stale value + gTimeSpec.tv_sec = 0; + gTimeSpec.tv_nsec = 0; + + if (spec.tv_sec == 0 && spec.tv_nsec == 0) + status = pthread_cond_wait(&gTimerCond, &gTimerMutex); + else + status = pthread_cond_timedwait(&gTimerCond, &gTimerMutex, &spec); + + if (status == 0) // someone signaled us with a new time + { + pthread_mutex_unlock(&gTimerMutex); + } + else + { + SkASSERT(status == ETIMEDOUT); // no need to unlock the mutex (its unlocked) + // this is the payoff. Signal the event queue to wake up + // and also check the delay-queue + gEventQCondition.broadcast(); + } + } + return 0; +} + +#define kThousand (1000) +#define kMillion (kThousand * kThousand) +#define kBillion (kThousand * kThousand * kThousand) + +void SkEvent::SignalQueueTimer(SkMSec delay) +{ + pthread_mutex_lock(&gTimerMutex); + + if (delay) + { + struct timeval tv; + gettimeofday(&tv, NULL); + + // normalize tv + if (tv.tv_usec >= kMillion) + { + tv.tv_sec += tv.tv_usec / kMillion; + tv.tv_usec %= kMillion; + } + + // add tv + delay, scale each up to land on nanoseconds + gTimeSpec.tv_nsec = (tv.tv_usec + (delay % kThousand) * kThousand) * kThousand; + gTimeSpec.tv_sec = (tv.tv_sec + (delay / kThousand) * kThousand) * kThousand; + + // check for overflow in nsec + if ((unsigned long)gTimeSpec.tv_nsec >= kBillion) + { + gTimeSpec.tv_nsec -= kBillion; + gTimeSpec.tv_sec += 1; + SkASSERT((unsigned long)gTimeSpec.tv_nsec < kBillion); + } + + // printf("SignalQueueTimer(%d) timespec(%d %d)\n", delay, gTimeSpec.tv_sec, gTimeSpec.tv_nsec); + } + else // cancel the timer + { + gTimeSpec.tv_nsec = 0; + gTimeSpec.tv_sec = 0; + } + + pthread_mutex_unlock(&gTimerMutex); + pthread_cond_signal(&gTimerCond); +} + +void SkEvent_start_timer_thread() +{ + int status; + pthread_attr_t attr; + + status = pthread_attr_init(&attr); + SkASSERT(status == 0); + status = pthread_create(&gTimerThread, &attr, timer_event_thread_proc, 0); + SkASSERT(status == 0); +} + +void SkEvent_stop_timer_thread() +{ + int status = pthread_cancel(gTimerThread); + SkASSERT(status == 0); +} + +#endif |