OLD | NEW |
| (Empty) |
1 /* libs/graphics/ports/SkOSEvent_android.cpp | |
2 ** | |
3 ** Copyright 2006, The Android Open Source Project | |
4 ** | |
5 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
6 ** you may not use this file except in compliance with the License. | |
7 ** You may obtain a copy of the License at | |
8 ** | |
9 ** http://www.apache.org/licenses/LICENSE-2.0 | |
10 ** | |
11 ** Unless required by applicable law or agreed to in writing, software | |
12 ** distributed under the License is distributed on an "AS IS" BASIS, | |
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 ** See the License for the specific language governing permissions and | |
15 ** limitations under the License. | |
16 */ | |
17 | |
18 #include "SkEvent.h" | |
19 #include "utils/threads.h" | |
20 #include <stdio.h> | |
21 | |
22 using namespace android; | |
23 | |
24 Mutex gEventQMutex; | |
25 Condition gEventQCondition; | |
26 | |
27 void SkEvent::SignalNonEmptyQueue() | |
28 { | |
29 gEventQCondition.broadcast(); | |
30 } | |
31 | |
32 /////////////////////////////////////////////////////////////////// | |
33 | |
34 #ifdef FMS_ARCH_ANDROID_ARM | |
35 | |
36 // don't have pthreads.h, and therefore no timedwait(), so we punt for the demo | |
37 | |
38 void SkEvent::SignalQueueTimer(SkMSec delay) | |
39 { | |
40 } | |
41 | |
42 void SkEvent_start_timer_thread() | |
43 { | |
44 } | |
45 | |
46 void SkEvent_stop_timer_thread() | |
47 { | |
48 } | |
49 | |
50 #else | |
51 | |
52 #include <pthread.h> | |
53 #include <errno.h> | |
54 | |
55 static pthread_t gTimerThread; | |
56 static pthread_mutex_t gTimerMutex; | |
57 static pthread_cond_t gTimerCond; | |
58 static timespec gTimeSpec; | |
59 | |
60 static void* timer_event_thread_proc(void*) | |
61 { | |
62 for (;;) | |
63 { | |
64 int status; | |
65 | |
66 pthread_mutex_lock(&gTimerMutex); | |
67 | |
68 timespec spec = gTimeSpec; | |
69 // mark our global to be zero | |
70 // so we don't call timedwait again on a stale value | |
71 gTimeSpec.tv_sec = 0; | |
72 gTimeSpec.tv_nsec = 0; | |
73 | |
74 if (spec.tv_sec == 0 && spec.tv_nsec == 0) | |
75 status = pthread_cond_wait(&gTimerCond, &gTimerMutex); | |
76 else | |
77 status = pthread_cond_timedwait(&gTimerCond, &gTimerMutex, &spec); | |
78 | |
79 if (status == 0) // someone signaled us with a new time | |
80 { | |
81 pthread_mutex_unlock(&gTimerMutex); | |
82 } | |
83 else | |
84 { | |
85 SkASSERT(status == ETIMEDOUT); // no need to unlock the mutex (its
unlocked) | |
86 // this is the payoff. Signal the event queue to wake up | |
87 // and also check the delay-queue | |
88 gEventQCondition.broadcast(); | |
89 } | |
90 } | |
91 return 0; | |
92 } | |
93 | |
94 #define kThousand (1000) | |
95 #define kMillion (kThousand * kThousand) | |
96 #define kBillion (kThousand * kThousand * kThousand) | |
97 | |
98 void SkEvent::SignalQueueTimer(SkMSec delay) | |
99 { | |
100 pthread_mutex_lock(&gTimerMutex); | |
101 | |
102 if (delay) | |
103 { | |
104 struct timeval tv; | |
105 gettimeofday(&tv, NULL); | |
106 | |
107 // normalize tv | |
108 if (tv.tv_usec >= kMillion) | |
109 { | |
110 tv.tv_sec += tv.tv_usec / kMillion; | |
111 tv.tv_usec %= kMillion; | |
112 } | |
113 | |
114 // add tv + delay, scale each up to land on nanoseconds | |
115 gTimeSpec.tv_nsec = (tv.tv_usec + (delay % kThousand) * kThousand) * k
Thousand; | |
116 gTimeSpec.tv_sec = (tv.tv_sec + (delay / kThousand) * kThousand) * kT
housand; | |
117 | |
118 // check for overflow in nsec | |
119 if ((unsigned long)gTimeSpec.tv_nsec >= kBillion) | |
120 { | |
121 gTimeSpec.tv_nsec -= kBillion; | |
122 gTimeSpec.tv_sec += 1; | |
123 SkASSERT((unsigned long)gTimeSpec.tv_nsec < kBillion); | |
124 } | |
125 | |
126 // printf("SignalQueueTimer(%d) timespec(%d %d)\n", delay, gTimeSpec.tv_sec
, gTimeSpec.tv_nsec); | |
127 } | |
128 else // cancel the timer | |
129 { | |
130 gTimeSpec.tv_nsec = 0; | |
131 gTimeSpec.tv_sec = 0; | |
132 } | |
133 | |
134 pthread_mutex_unlock(&gTimerMutex); | |
135 pthread_cond_signal(&gTimerCond); | |
136 } | |
137 | |
138 void SkEvent_start_timer_thread() | |
139 { | |
140 int status; | |
141 pthread_attr_t attr; | |
142 | |
143 status = pthread_attr_init(&attr); | |
144 SkASSERT(status == 0); | |
145 status = pthread_create(&gTimerThread, &attr, timer_event_thread_proc, 0); | |
146 SkASSERT(status == 0); | |
147 } | |
148 | |
149 void SkEvent_stop_timer_thread() | |
150 { | |
151 int status = pthread_cancel(gTimerThread); | |
152 SkASSERT(status == 0); | |
153 } | |
154 | |
155 #endif | |
OLD | NEW |