Files
igl/external/embree/common/sys/sync/condition.cpp
T

149 lines
4.1 KiB
C++
Executable File

// ======================================================================== //
// Copyright 2009-2014 Intel Corporation //
// //
// 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 "condition.h"
#if defined(__WIN32__) && !defined(PTHREADS_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
namespace embree
{
#if (_WIN32_WINNT >= 0x0600)
struct ConditionImplementation
{
__forceinline ConditionImplementation () {
InitializeConditionVariable(&cond);
}
__forceinline ~ConditionImplementation () {
}
__forceinline void wait(MutexSys& mutex_in) {
SleepConditionVariableCS(&cond, (LPCRITICAL_SECTION)mutex_in.mutex, INFINITE);
}
__forceinline void broadcast() {
WakeAllConditionVariable(&cond);
}
public:
CONDITION_VARIABLE cond;
};
#else
#pragma message ("WARNING: This condition variable implementation has known performance issues!")
struct ConditionImplementation
{
__forceinline ConditionImplementation () : count(0) {
event = CreateEvent(NULL,TRUE,FALSE,NULL);
}
__forceinline ~ConditionImplementation () {
CloseHandle(event);
}
__forceinline void wait(MutexSys& mutex_in)
{
/* atomically increment thread count */
ssize_t cnt0 = atomic_add(&count,+1);
mutex_in.unlock();
/* all threads except the last one are wait in the barrier */
if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
THROW_RUNTIME_ERROR("WaitForSingleObject failed");
/* atomically decrement thread count */
mutex_in.lock();
ssize_t cnt1 = atomic_add(&count,-1);
/* the last thread that left the barrier resets the event again */
if (cnt1 == 1) {
if (ResetEvent(event) == 0)
THROW_RUNTIME_ERROR("ResetEvent failed");
}
}
__forceinline void broadcast()
{
/* we support only one broadcast at a given time */
bool hasWaiters = count > 0;
/* if threads are waiting, let them continue */
if (hasWaiters)
if (SetEvent(event) == 0)
THROW_RUNTIME_ERROR("SetEvent failed");
}
public:
HANDLE event;
volatile atomic_t count;
};
#endif
}
#endif
#if defined(__UNIX__) || defined(PTHREADS_WIN32)
#include <pthread.h>
namespace embree
{
struct ConditionImplementation
{
__forceinline ConditionImplementation () {
pthread_cond_init(&cond,NULL);
}
__forceinline ~ConditionImplementation() {
pthread_cond_destroy(&cond);
}
__forceinline void wait(MutexSys& mutex) {
pthread_cond_wait(&cond, (pthread_mutex_t*)mutex.mutex);
}
__forceinline void broadcast() {
pthread_cond_broadcast(&cond);
}
public:
pthread_cond_t cond;
};
}
#endif
namespace embree
{
ConditionSys::ConditionSys () {
cond = new ConditionImplementation;
}
ConditionSys::~ConditionSys() {
delete (ConditionImplementation*) cond;
}
void ConditionSys::wait(MutexSys& mutex) {
((ConditionImplementation*) cond)->wait(mutex);
}
void ConditionSys::broadcast() {
((ConditionImplementation*) cond)->broadcast();
}
}