Author: [email protected]
Date: Wed Mar 18 02:04:24 2009
New Revision: 1526

Modified:
    branches/bleeding_edge/SConstruct
    branches/bleeding_edge/src/platform-freebsd.cc
    branches/bleeding_edge/src/platform-linux.cc
    branches/bleeding_edge/src/platform-macos.cc
    branches/bleeding_edge/src/platform-win32.cc
    branches/bleeding_edge/src/platform.h
    branches/bleeding_edge/test/cctest/test-lock.cc

Log:
Added a wait with timeout to the platform semaphore class.

The code has been compiled and tested on Windows, Linux and Mac OS.

The FreeBSD version is a copy of the Linux version which should work on  
FreeBSD as well. According to the FreeBSD documentation clock_gettime is  
part of the standard C library so the assumption is that no additional link  
libraries is required for FreeBSD.
Review URL: http://codereview.chromium.org/48123

Modified: branches/bleeding_edge/SConstruct
==============================================================================
--- branches/bleeding_edge/SConstruct   (original)
+++ branches/bleeding_edge/SConstruct   Wed Mar 18 02:04:24 2009
@@ -151,7 +151,7 @@
  MKSNAPSHOT_EXTRA_FLAGS = {
    'gcc': {
      'os:linux': {
-      'LIBS': ['pthread'],
+      'LIBS': ['pthread', 'rt'],
      },
      'os:macos': {
        'LIBS': ['pthread'],
@@ -195,7 +195,7 @@
        'LIBPATH': [abspath('.')]
      },
      'os:linux': {
-      'LIBS':         ['pthread'],
+      'LIBS':         ['pthread', 'rt'],
      },
      'os:macos': {
        'LIBS':         ['pthread'],
@@ -233,7 +233,7 @@
        'LIBPATH': ['.']
      },
      'os:linux': {
-      'LIBS':         ['pthread'],
+      'LIBS':         ['pthread', 'rt'],
      },
      'os:macos': {
        'LIBS':         ['pthread'],
@@ -301,7 +301,7 @@
        'LIBS': ['readline']
      },
      'os:linux': {
-      'LIBS': ['pthread'],
+      'LIBS': ['pthread', 'rt'],
      },
      'os:macos': {
        'LIBS': ['pthread'],

Modified: branches/bleeding_edge/src/platform-freebsd.cc
==============================================================================
--- branches/bleeding_edge/src/platform-freebsd.cc      (original)
+++ branches/bleeding_edge/src/platform-freebsd.cc      Wed Mar 18 02:04:24 2009
@@ -608,11 +608,13 @@
    virtual ~FreeBSDSemaphore() { sem_destroy(&sem_); }

    virtual void Wait();
+  virtual bool Wait(int timeout);
    virtual void Signal() { sem_post(&sem_); }
   private:
    sem_t sem_;
  };

+
  void FreeBSDSemaphore::Wait() {
    while (true) {
      int result = sem_wait(&sem_);
@@ -620,6 +622,39 @@
      CHECK(result == -1 && errno == EINTR);  // Signal caused spurious  
wakeup.
    }
  }
+
+
+bool FreeBSDSemaphore::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 real time clock.
+  struct timespec ts;
+  if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
+    return false;
+  }
+
+  // Calculate realtime 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 FreeBSDSemaphore(count);

Modified: branches/bleeding_edge/src/platform-linux.cc
==============================================================================
--- branches/bleeding_edge/src/platform-linux.cc        (original)
+++ branches/bleeding_edge/src/platform-linux.cc        Wed Mar 18 02:04:24 2009
@@ -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_);
@@ -604,6 +606,39 @@
      CHECK(result == -1 && errno == EINTR);  // Signal caused spurious  
wakeup.
    }
  }
+
+
+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);

Modified: branches/bleeding_edge/src/platform-macos.cc
==============================================================================
--- branches/bleeding_edge/src/platform-macos.cc        (original)
+++ branches/bleeding_edge/src/platform-macos.cc        Wed Mar 18 02:04:24 2009
@@ -565,11 +565,21 @@
    // platform is not needed here.
    void Wait() { semaphore_wait(semaphore_); }

+  bool Wait(int timeout);
+
    void Signal() { semaphore_signal(semaphore_); }

   private:
    semaphore_t semaphore_;
  };
+
+
+bool MacOSSemaphore::Wait(int timeout) {
+  mach_timespec_t ts;
+  ts.tv_sec = timeout / 1000000;
+  ts.tv_nsec = (timeout % 1000000) * 1000;
+  return semaphore_timedwait(semaphore_, ts) != KERN_OPERATION_TIMED_OUT;
+}


  Semaphore* OS::CreateSemaphore(int count) {

Modified: branches/bleeding_edge/src/platform-win32.cc
==============================================================================
--- branches/bleeding_edge/src/platform-win32.cc        (original)
+++ branches/bleeding_edge/src/platform-win32.cc        Wed Mar 18 02:04:24 2009
@@ -1538,6 +1538,12 @@
      WaitForSingleObject(sem, INFINITE);
    }

+  bool Wait(int timeout) {
+    // Timeout in Windows API is in milliseconds.
+    DWORD millis_timeout = timeout / 1000;
+    return WaitForSingleObject(sem, millis_timeout) != WAIT_TIMEOUT;
+  }
+
    void Signal() {
      LONG dummy;
      ReleaseSemaphore(sem, 1, &dummy);

Modified: branches/bleeding_edge/src/platform.h
==============================================================================
--- branches/bleeding_edge/src/platform.h       (original)
+++ branches/bleeding_edge/src/platform.h       Wed Mar 18 02:04:24 2009
@@ -410,9 +410,15 @@
   public:
    virtual ~Semaphore() {}

-  // Suspends the calling thread until the counter is non zero
+  // Suspends the calling thread until the semaphore counter is non zero
    // and then decrements the semaphore counter.
    virtual void Wait() = 0;
+
+  // Suspends the calling thread until the counter is non zero or the  
timeout
+  // time has passsed. If timeout happens the return value is false and the
+  // counter is unchanged. Otherwise the semaphore counter is decremented  
and
+  // true is returned. The timeout value is specified in microseconds.
+  virtual bool Wait(int timeout) = 0;

    // Increments the semaphore counter.
    virtual void Signal() = 0;

Modified: branches/bleeding_edge/test/cctest/test-lock.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-lock.cc     (original)
+++ branches/bleeding_edge/test/cctest/test-lock.cc     Wed Mar 18 02:04:24 2009
@@ -38,3 +38,26 @@
    CHECK_EQ(0, mutex->Unlock());
    delete mutex;
  }
+
+
+TEST(SemaphoreTimeout) {
+  bool ok;
+  Semaphore* sem = OS::CreateSemaphore(0);
+
+  // Semaphore not signalled - timeout.
+  ok = sem->Wait(0);
+  CHECK(!ok);
+  ok = sem->Wait(100);
+  CHECK(!ok);
+  ok = sem->Wait(1000);
+  CHECK(!ok);
+
+  // Semaphore signalled - no timeout.
+  sem->Signal();
+  ok = sem->Wait(0);
+  sem->Signal();
+  ok = sem->Wait(100);
+  sem->Signal();
+  ok = sem->Wait(1000);
+  CHECK(ok);
+}

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to