ppsspp/Common/Thread.h
Sacha 41f5abab31 PPSSPP ported to Blackberry10
Now builds on Playbook and Dev Alpha
Make emulator more compatible with other OS (case sensitivity, defines, includes)
Uses Android's code paths and backend
2012-11-05 23:09:49 +10:00

177 lines
3.5 KiB
C++

// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _THREAD_H_
#define _THREAD_H_
#include "StdThread.h"
#include "StdMutex.h"
#include "StdConditionVariable.h"
// Don't include common.h here as it will break LogManager
#include "CommonTypes.h"
#include <stdio.h>
#include <string.h>
// This may not be defined outside _WIN32
#ifndef _WIN32
#ifndef INFINITE
#define INFINITE 0xffffffff
#endif
#if !defined(ANDROID) && !defined(BLACKBERRY)
#include <xmmintrin.h>
#endif
//for gettimeofday and struct time(spec|val)
#include <time.h>
#include <sys/time.h>
#endif
namespace Common
{
int CurrentThreadId();
// In Windows 7 SP1 or later, stops Windows from swallowing crashes in WndProcs and other callbacks.
void EnableCrashingOnCrashes();
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
void SetCurrentThreadAffinity(u32 mask);
class Event
{
public:
Event()
: is_set(false)
{};
void Set()
{
std::lock_guard<std::mutex> lk(m_mutex);
if (!is_set)
{
is_set = true;
m_condvar.notify_one();
}
}
void Wait()
{
std::unique_lock<std::mutex> lk(m_mutex);
m_condvar.wait(lk, IsSet(this));
is_set = false;
}
void Reset()
{
std::unique_lock<std::mutex> lk(m_mutex);
// no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration
is_set = false;
}
private:
class IsSet
{
public:
IsSet(const Event* ev)
: m_event(ev)
{}
bool operator()()
{
return m_event->is_set;
}
private:
const Event* const m_event;
};
volatile bool is_set;
std::condition_variable m_condvar;
std::mutex m_mutex;
};
// TODO: doesn't work on windows with (count > 2)
class Barrier
{
public:
Barrier(size_t count)
: m_count(count), m_waiting(0)
{}
// block until "count" threads call Sync()
bool Sync()
{
std::unique_lock<std::mutex> lk(m_mutex);
// TODO: broken when next round of Sync()s
// is entered before all waiting threads return from the notify_all
if (m_count == ++m_waiting)
{
m_waiting = 0;
m_condvar.notify_all();
return true;
}
else
{
m_condvar.wait(lk, IsDoneWating(this));
return false;
}
}
private:
class IsDoneWating
{
public:
IsDoneWating(const Barrier* bar)
: m_bar(bar)
{}
bool operator()()
{
return (0 == m_bar->m_waiting);
}
private:
const Barrier* const m_bar;
};
std::condition_variable m_condvar;
std::mutex m_mutex;
const size_t m_count;
volatile size_t m_waiting;
};
void SleepCurrentThread(int ms);
void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
// Use this function during a spin-wait to make the current thread
// relax while another thread is working. This may be more efficient
// than using events because event functions use kernel calls.
inline void YieldCPU()
{
std::this_thread::yield();
}
void SetCurrentThreadName(const char *name);
} // namespace Common
#endif // _THREAD_H_