blob: 34e271b15a0fd431ab9a0fb4622dec2f3d42d720 [file] [log] [blame] [edit]
// Copyright 2013 The Flutter 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 "flutter/fml/synchronization/semaphore.h"
#include "flutter/fml/build_config.h"
#include "flutter/fml/logging.h"
#if FML_OS_MACOSX
#include <dispatch/dispatch.h>
namespace fml {
class PlatformSemaphore {
public:
explicit PlatformSemaphore(uint32_t count)
: _sem(dispatch_semaphore_create(count)), _initial(count) {}
~PlatformSemaphore() {
for (uint32_t i = 0; i < _initial; ++i) {
Signal();
}
if (_sem != nullptr) {
dispatch_release(reinterpret_cast<dispatch_object_t>(_sem));
_sem = nullptr;
}
}
bool IsValid() const { return _sem != nullptr; }
bool Wait() {
if (_sem == nullptr) {
return false;
}
return dispatch_semaphore_wait(_sem, DISPATCH_TIME_FOREVER) == 0;
}
bool TryWait() {
if (_sem == nullptr) {
return false;
}
return dispatch_semaphore_wait(_sem, DISPATCH_TIME_NOW) == 0;
}
void Signal() {
if (_sem != nullptr) {
dispatch_semaphore_signal(_sem);
}
}
private:
dispatch_semaphore_t _sem;
const uint32_t _initial;
FML_DISALLOW_COPY_AND_ASSIGN(PlatformSemaphore);
};
} // namespace fml
#elif FML_OS_WIN
#include <windows.h>
namespace fml {
class PlatformSemaphore {
public:
explicit PlatformSemaphore(uint32_t count)
: _sem(CreateSemaphore(NULL, count, LONG_MAX, NULL)) {}
~PlatformSemaphore() {
if (_sem != nullptr) {
CloseHandle(_sem);
_sem = nullptr;
}
}
bool IsValid() const { return _sem != nullptr; }
bool Wait() {
if (_sem == nullptr) {
return false;
}
return WaitForSingleObject(_sem, INFINITE) == WAIT_OBJECT_0;
}
bool TryWait() {
if (_sem == nullptr) {
return false;
}
return WaitForSingleObject(_sem, 0) == WAIT_OBJECT_0;
}
void Signal() {
if (_sem != nullptr) {
ReleaseSemaphore(_sem, 1, NULL);
}
}
private:
HANDLE _sem;
FML_DISALLOW_COPY_AND_ASSIGN(PlatformSemaphore);
};
} // namespace fml
#else
#include <semaphore.h>
#include "flutter/fml/eintr_wrapper.h"
namespace fml {
class PlatformSemaphore {
public:
explicit PlatformSemaphore(uint32_t count)
: valid_(::sem_init(&sem_, 0 /* not shared */, count) == 0) {}
~PlatformSemaphore() {
if (valid_) {
int result = ::sem_destroy(&sem_);
(void)result;
// Can only be EINVAL which should not be possible since we checked for
// validity.
FML_DCHECK(result == 0);
}
}
bool IsValid() const { return valid_; }
bool Wait() {
if (!valid_) {
return false;
}
return FML_HANDLE_EINTR(::sem_wait(&sem_)) == 0;
}
bool TryWait() {
if (!valid_) {
return false;
}
return FML_HANDLE_EINTR(::sem_trywait(&sem_)) == 0;
}
void Signal() {
if (!valid_) {
return;
}
::sem_post(&sem_);
return;
}
private:
bool valid_;
sem_t sem_;
FML_DISALLOW_COPY_AND_ASSIGN(PlatformSemaphore);
};
} // namespace fml
#endif
namespace fml {
Semaphore::Semaphore(uint32_t count) : _impl(new PlatformSemaphore(count)) {}
Semaphore::~Semaphore() = default;
bool Semaphore::IsValid() const {
return _impl->IsValid();
}
bool Semaphore::Wait() {
return _impl->Wait();
}
bool Semaphore::TryWait() {
return _impl->TryWait();
}
void Semaphore::Signal() {
return _impl->Signal();
}
} // namespace fml