Index: src/platform-linux.cc |
=================================================================== |
--- src/platform-linux.cc (revision 1525) |
+++ src/platform-linux.cc (working copy) |
@@ -592,11 +592,13 @@ |
virtual ~LinuxSemaphore() { sem_destroy(&sem_); } |
virtual void Wait(); |
+ virtual bool Wait(int timeout); |
virtual void Signal() { sem_post(&sem_); } |
private: |
sem_t sem_; |
}; |
+ |
void LinuxSemaphore::Wait() { |
while (true) { |
int result = sem_wait(&sem_); |
@@ -605,6 +607,39 @@ |
} |
} |
+ |
+bool LinuxSemaphore::Wait(int timeout) { |
+ const long kOneSecondMicros = 1000000; // NOLINT |
+ const long kOneSecondNanos = 1000000000; // NOLINT |
+ |
+ // Split timeout into second and nanosecond parts. |
+ long nanos = (timeout % kOneSecondMicros) * 1000; // NOLINT |
+ time_t secs = timeout / kOneSecondMicros; |
+ |
+ // Get the current realtime clock. |
+ struct timespec ts; |
+ if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { |
+ return false; |
+ } |
+ |
+ // Calculate real time for end of timeout. |
+ ts.tv_nsec += nanos; |
+ if (ts.tv_nsec >= kOneSecondNanos) { |
+ ts.tv_nsec -= kOneSecondNanos; |
+ ts.tv_nsec++; |
+ } |
+ ts.tv_sec += secs; |
+ |
+ // Wait for semaphore signalled or timeout. |
+ while (true) { |
+ int result = sem_timedwait(&sem_, &ts); |
+ if (result == 0) return true; // Successfully got semaphore. |
+ if (result == -1 && errno == ETIMEDOUT) return false; // Timeout. |
+ CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. |
+ } |
+} |
+ |
+ |
Semaphore* OS::CreateSemaphore(int count) { |
return new LinuxSemaphore(count); |
} |