Semaphore.cc AOSP源码

android5.1\external\chromium_org\v8\src\base\platform\semaphore.h

// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_BASE_PLATFORM_SEMAPHORE_H_
#define V8_BASE_PLATFORM_SEMAPHORE_H_
#include "src/base/lazy-instance.h"
#if V8_OS_WIN
#include "src/base/win32-headers.h"
#endif
#if V8_OS_MACOSX
#include <mach/semaphore.h>  // NOLINT
#elif V8_OS_POSIX
#include <semaphore.h>  // NOLINT
#endif
namespace v8 {
namespace base {
// Forward declarations.
class TimeDelta;
// ----------------------------------------------------------------------------
// Semaphore
//
// A semaphore object is a synchronization object that maintains a count. The
// count is decremented each time a thread completes a wait for the semaphore
// object and incremented each time a thread signals the semaphore. When the
// count reaches zero,  threads waiting for the semaphore blocks until the
// count becomes non-zero.
class Semaphore FINAL {
 public:
  explicit Semaphore(int count);
  ~Semaphore();
  // Increments the semaphore counter.
  void Signal();
  // Suspends the calling thread until the semaphore counter is non zero
  // and then decrements the semaphore counter.
  void Wait();
  // Suspends the calling thread until the counter is non zero or the timeout
  // time has passed. If timeout happens the return value is false and the
  // counter is unchanged. Otherwise the semaphore counter is decremented and
  // true is returned.
  bool WaitFor(const TimeDelta& rel_time) WARN_UNUSED_RESULT;
#if V8_OS_MACOSX
  typedef semaphore_t NativeHandle;
#elif V8_OS_POSIX
  typedef sem_t NativeHandle;
#elif V8_OS_WIN
  typedef HANDLE NativeHandle;
#endif
  NativeHandle& native_handle() {
    return native_handle_;
  }
  const NativeHandle& native_handle() const {
    return native_handle_;
  }
 private:
  NativeHandle native_handle_;
  DISALLOW_COPY_AND_ASSIGN(Semaphore);
};
// POD Semaphore initialized lazily (i.e. the first time Pointer() is called).
// Usage:
//   // The following semaphore starts at 0.
//   static LazySemaphore<0>::type my_semaphore = LAZY_SEMAPHORE_INITIALIZER;
//
//   void my_function() {
//     // Do something with my_semaphore.Pointer().
//   }
//
template <int N>
struct CreateSemaphoreTrait {
  static Semaphore* Create() {
    return new Semaphore(N);
  }
};
template <int N>
struct LazySemaphore {
  typedef typename LazyDynamicInstance<Semaphore, CreateSemaphoreTrait<N>,
                                       ThreadSafeInitOnceTrait>::type type;
};
#define LAZY_SEMAPHORE_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
} }  // namespace v8::base
#endif  // V8_BASE_PLATFORM_SEMAPHORE_H_

android5.1\external\chromium_org\v8\src\base\platform\semaphore.cc

// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/base/platform/semaphore.h"
#if V8_OS_MACOSX
#include <mach/mach_init.h>
#include <mach/task.h>
#endif
#include <errno.h>
#include "src/base/logging.h"
#include "src/base/platform/elapsed-timer.h"
#include "src/base/platform/time.h"
namespace v8 {
namespace base {
#if V8_OS_MACOSX
Semaphore::Semaphore(int count) {
  kern_return_t result = semaphore_create(
      mach_task_self(), &native_handle_, SYNC_POLICY_FIFO, count);
  DCHECK_EQ(KERN_SUCCESS, result);
  USE(result);
}
Semaphore::~Semaphore() {
  kern_return_t result = semaphore_destroy(mach_task_self(), native_handle_);
  DCHECK_EQ(KERN_SUCCESS, result);
  USE(result);
}
void Semaphore::Signal() {
  kern_return_t result = semaphore_signal(native_handle_);
  DCHECK_EQ(KERN_SUCCESS, result);
  USE(result);
}
void Semaphore::Wait() {
  while (true) {
    kern_return_t result = semaphore_wait(native_handle_);
    if (result == KERN_SUCCESS) return;  // Semaphore was signalled.
    DCHECK_EQ(KERN_ABORTED, result);
  }
}
bool Semaphore::WaitFor(const TimeDelta& rel_time) {
  TimeTicks now = TimeTicks::Now();
  TimeTicks end = now + rel_time;
  while (true) {
    mach_timespec_t ts;
    if (now >= end) {
      // Return immediately if semaphore was not signalled.
      ts.tv_sec = 0;
      ts.tv_nsec = 0;
    } else {
      ts = (end - now).ToMachTimespec();
    }
    kern_return_t result = semaphore_timedwait(native_handle_, ts);
    if (result == KERN_SUCCESS) return true;  // Semaphore was signalled.
    if (result == KERN_OPERATION_TIMED_OUT) return false;  // Timeout.
    DCHECK_EQ(KERN_ABORTED, result);
    now = TimeTicks::Now();
  }
}
#elif V8_OS_POSIX
Semaphore::Semaphore(int count) {
  DCHECK(count >= 0);
  int result = sem_init(&native_handle_, 0, count);
  DCHECK_EQ(0, result);
  USE(result);
}
Semaphore::~Semaphore() {
  int result = sem_destroy(&native_handle_);
  DCHECK_EQ(0, result);
  USE(result);
}
void Semaphore::Signal() {
  int result = sem_post(&native_handle_);
  DCHECK_EQ(0, result);
  USE(result);
}
void Semaphore::Wait() {
  while (true) {
    int result = sem_wait(&native_handle_);
    if (result == 0) return;  // Semaphore was signalled.
    // Signal caused spurious wakeup.
    DCHECK_EQ(-1, result);
    DCHECK_EQ(EINTR, errno);
  }
}
bool Semaphore::WaitFor(const TimeDelta& rel_time) {
#if V8_OS_NACL
  // PNaCL doesn't support sem_timedwait, do ugly busy waiting.
  ElapsedTimer timer;
  timer.Start();
  do {
    int result = sem_trywait(&native_handle_);
    if (result == 0) return true;
    DCHECK(errno == EAGAIN || errno == EINTR);
  } while (!timer.HasExpired(rel_time));
  return false;
#else
  // Compute the time for end of timeout.
  const Time time = Time::NowFromSystemTime() + rel_time;
  const struct timespec ts = time.ToTimespec();
  // Wait for semaphore signalled or timeout.
  while (true) {
    int result = sem_timedwait(&native_handle_, &ts);
    if (result == 0) return true;  // Semaphore was signalled.
#if V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
    if (result > 0) {
      // sem_timedwait in glibc prior to 2.3.4 returns the errno instead of -1.
      errno = result;
      result = -1;
    }
#endif
    if (result == -1 && errno == ETIMEDOUT) {
      // Timed out while waiting for semaphore.
      return false;
    }
    // Signal caused spurious wakeup.
    DCHECK_EQ(-1, result);
    DCHECK_EQ(EINTR, errno);
  }
#endif
}
#elif V8_OS_WIN
Semaphore::Semaphore(int count) {
  DCHECK(count >= 0);
  native_handle_ = ::CreateSemaphoreA(NULL, count, 0x7fffffff, NULL);
  DCHECK(native_handle_ != NULL);
}
Semaphore::~Semaphore() {
  BOOL result = CloseHandle(native_handle_);
  DCHECK(result);
  USE(result);
}
void Semaphore::Signal() {
  LONG dummy;
  BOOL result = ReleaseSemaphore(native_handle_, 1, &dummy);
  DCHECK(result);
  USE(result);
}
void Semaphore::Wait() {
  DWORD result = WaitForSingleObject(native_handle_, INFINITE);
  DCHECK(result == WAIT_OBJECT_0);
  USE(result);
}
bool Semaphore::WaitFor(const TimeDelta& rel_time) {
  TimeTicks now = TimeTicks::Now();
  TimeTicks end = now + rel_time;
  while (true) {
    int64_t msec = (end - now).InMilliseconds();
    if (msec >= static_cast<int64_t>(INFINITE)) {
      DWORD result = WaitForSingleObject(native_handle_, INFINITE - 1);
      if (result == WAIT_OBJECT_0) {
        return true;
      }
      DCHECK(result == WAIT_TIMEOUT);
      now = TimeTicks::Now();
    } else {
      DWORD result = WaitForSingleObject(
          native_handle_, (msec < 0) ? 0 : static_cast<DWORD>(msec));
      if (result == WAIT_TIMEOUT) {
        return false;
      }
      DCHECK(result == WAIT_OBJECT_0);
      return true;
    }
  }
}
#endif  // V8_OS_MACOSX
} }  // namespace v8::base

单元测试

android5.1\external\chromium_org\v8\src\base\platform\semaphore-unittest.cc

// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstring>
#include "src/base/platform/platform.h"
#include "src/base/platform/semaphore.h"
#include "src/base/platform/time.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace base {
namespace {
static const char kAlphabet[] = "XKOAD";
static const size_t kAlphabetSize = sizeof(kAlphabet) - 1;
static const size_t kBufferSize = 987;  // GCD(buffer size, alphabet size) = 1
static const size_t kDataSize = kBufferSize * kAlphabetSize * 10;
class ProducerThread FINAL : public Thread {
 public:
  ProducerThread(char* buffer, Semaphore* free_space, Semaphore* used_space)
      : Thread(Options("ProducerThread")),
        buffer_(buffer),
        free_space_(free_space),
        used_space_(used_space) {}
  virtual ~ProducerThread() {}
  virtual void Run() OVERRIDE {
    for (size_t n = 0; n < kDataSize; ++n) {
      free_space_->Wait();
      buffer_[n % kBufferSize] = kAlphabet[n % kAlphabetSize];
      used_space_->Signal();
    }
  }
 private:
  char* buffer_;
  Semaphore* const free_space_;
  Semaphore* const used_space_;
};
class ConsumerThread FINAL : public Thread {
 public:
  ConsumerThread(const char* buffer, Semaphore* free_space,
                 Semaphore* used_space)
      : Thread(Options("ConsumerThread")),
        buffer_(buffer),
        free_space_(free_space),
        used_space_(used_space) {}
  virtual ~ConsumerThread() {}
  virtual void Run() OVERRIDE {
    for (size_t n = 0; n < kDataSize; ++n) {
      used_space_->Wait();
      EXPECT_EQ(kAlphabet[n % kAlphabetSize], buffer_[n % kBufferSize]);
      free_space_->Signal();
    }
  }
 private:
  const char* buffer_;
  Semaphore* const free_space_;
  Semaphore* const used_space_;
};
class WaitAndSignalThread FINAL : public Thread {
 public:
  explicit WaitAndSignalThread(Semaphore* semaphore)
      : Thread(Options("WaitAndSignalThread")), semaphore_(semaphore) {}
  virtual ~WaitAndSignalThread() {}
  virtual void Run() OVERRIDE {
    for (int n = 0; n < 100; ++n) {
      semaphore_->Wait();
      ASSERT_FALSE(semaphore_->WaitFor(TimeDelta::FromMicroseconds(1)));
      semaphore_->Signal();
    }
  }
 private:
  Semaphore* const semaphore_;
};
}  // namespace
TEST(Semaphore, ProducerConsumer) {
  char buffer[kBufferSize];
  std::memset(buffer, 0, sizeof(buffer));
  Semaphore free_space(kBufferSize);
  Semaphore used_space(0);
  ProducerThread producer_thread(buffer, &free_space, &used_space);
  ConsumerThread consumer_thread(buffer, &free_space, &used_space);
  producer_thread.Start();
  consumer_thread.Start();
  producer_thread.Join();
  consumer_thread.Join();
}
TEST(Semaphore, WaitAndSignal) {
  Semaphore semaphore(0);
  WaitAndSignalThread t1(&semaphore);
  WaitAndSignalThread t2(&semaphore);
  t1.Start();
  t2.Start();
  // Make something available.
  semaphore.Signal();
  t1.Join();
  t2.Join();
  semaphore.Wait();
  EXPECT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1)));
}
TEST(Semaphore, WaitFor) {
  Semaphore semaphore(0);
  // Semaphore not signalled - timeout.
  ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0)));
  ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100)));
  ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000)));
  // Semaphore signalled - no timeout.
  semaphore.Signal();
  ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0)));
  semaphore.Signal();
  ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100)));
  semaphore.Signal();
  ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000)));
}
}  // namespace base
}  // namespace v8

硬件中使用的Semaphore

android5.1\hardware\ti\omap4-aah\libtiutils\Semaphore.cpp

/*
 * Copyright (C) Texas Instruments - http://www.ti.com/
 *
 * 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 "Semaphore.h"
#include "ErrorUtils.h"
#include <utils/Log.h>
#include <time.h>
namespace Ti {
namespace Utils {
/**
   @brief Constructor for the semaphore class
   @param none
   @return none
 */
Semaphore::Semaphore()
{
    ///Initialize the semaphore to NULL
    mSemaphore = NULL;
}
/**
   @brief Destructor of the semaphore class
   @param none
   @return none
 */
Semaphore::~Semaphore()
{
    Release();
}
/**
   @brief: Releases semaphore
   @param count >=0
   @return NO_ERROR On Success
   @return One of the android error codes based on semaphore de-initialization
 */
status_t Semaphore::Release()
{
    int status = 0;
    ///Destroy only if the semaphore has been created
    if(mSemaphore)
        {
        status = sem_destroy(mSemaphore);
        free(mSemaphore);
        mSemaphore = NULL;
        }
    ///Initialize the semaphore and return the status
    return ErrorUtils::posixToAndroidError(status);
}
/**
   @brief Create the semaphore with initial count value
   @param count >=0
   @return NO_ERROR On Success
   @return NO_MEMORY If unable to allocate memory for the semaphore
   @return BAD_VALUE If an invalid count value is passed (<0)
   @return One of the android error codes based on semaphore initialization
 */
status_t Semaphore::Create(int count)
{
    status_t ret = NO_ERROR;
    ///count cannot be less than zero
    if(count<0)
        {
        return BAD_VALUE;
        }
    ret = Release();
    if ( NO_ERROR != ret )
        {
        return ret;
        }
    ///allocate memory for the semaphore
    mSemaphore = (sem_t*)malloc(sizeof(sem_t)) ;
    ///if memory is unavailable, return error
    if(!mSemaphore)
        {
        return NO_MEMORY;
        }
    ///Initialize the semaphore and return the status
    return ErrorUtils::posixToAndroidError(sem_init(mSemaphore, 0x00, count));
}
/**
   @brief Wait operation
   @param none
   @return BAD_VALUE if the semaphore is not initialized
   @return NO_ERROR On success
   @return One of the android error codes based on semaphore wait operation
 */
status_t Semaphore::Wait()
{
    ///semaphore should have been created first
    if(!mSemaphore)
        {
        return BAD_VALUE;
        }
    ///Wait and return the status after signalling
    return ErrorUtils::posixToAndroidError(sem_wait(mSemaphore));
}
/**
   @brief Signal operation
   @param none
     @return BAD_VALUE if the semaphore is not initialized
     @return NO_ERROR On success
     @return One of the android error codes based on semaphore signal operation
   */
status_t Semaphore::Signal()
{
    ///semaphore should have been created first
    if(!mSemaphore)
        {
        return BAD_VALUE;
        }
    ///Post to the semaphore
    return ErrorUtils::posixToAndroidError(sem_post(mSemaphore));
}
/**
   @brief Current semaphore count
   @param none
   @return Current count value of the semaphore
 */
int Semaphore::Count()
{
    int val;
    ///semaphore should have been created first
    if(!mSemaphore)
        {
        return BAD_VALUE;
        }
    ///get the value of the semaphore
    sem_getvalue(mSemaphore, &val);
    return val;
}
/**
   @brief Wait operation with a timeout
     @param timeoutMicroSecs The timeout period in micro seconds
     @return BAD_VALUE if the semaphore is not initialized
     @return NO_ERROR On success
     @return One of the android error codes based on semaphore wait operation
   */
status_t Semaphore::WaitTimeout(int timeoutMicroSecs)
{
    status_t ret = NO_ERROR;
    struct timespec timeSpec;
    struct timeval currentTime;
    ///semaphore should have been created first
    if( NULL == mSemaphore)
        {
        ret = BAD_VALUE;
        }
    if ( NO_ERROR == ret )
        {
        ///setup the timeout values - timeout is specified in seconds and nanoseconds
        gettimeofday(¤tTime, NULL);
        timeSpec.tv_sec = currentTime.tv_sec;
        timeSpec.tv_nsec = currentTime.tv_usec * 1000;
        timeSpec.tv_sec += ( timeoutMicroSecs / 1000000 );
        timeSpec.tv_nsec += ( timeoutMicroSecs % 1000000) * 1000;
        ///Wait for the timeout or signal and return the result based on whichever event occurred first
        ret = sem_timedwait(mSemaphore, &timeSpec);
        }
    if ( NO_ERROR != ret )
      {
        Signal();
        Create(0);
      }
    return ret;
}
} // namespace Utils
} // namespace Ti



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值