mirror of
https://github.com/libretro/ppsspp.git
synced 2025-02-04 16:06:13 +00:00
Add prioritizedworkqueue, thread stuff, ui tweaks, small optimizations in file util
This commit is contained in:
parent
bff1115f0c
commit
25711066df
@ -41,6 +41,8 @@ LOCAL_SRC_FILES :=\
|
||||
net/http_client.cpp \
|
||||
net/resolve.cpp \
|
||||
profiler/profiler.cpp \
|
||||
thread/threadutil.cpp \
|
||||
thread/prioritizedworkqueue.cpp \
|
||||
gfx_es2/glsl_program.cpp \
|
||||
gfx_es2/gl_state.cpp \
|
||||
gfx_es2/draw_buffer.cpp.arm \
|
||||
@ -62,7 +64,7 @@ LOCAL_SRC_FILES :=\
|
||||
util/text/utf8.cpp
|
||||
|
||||
LOCAL_CFLAGS := -O3 -DGL_GLEXT_PROTOTYPES -DUSING_GLES2 -fsigned-char -fno-strict-aliasing
|
||||
LOCAL_CPPFLAGS := -fno-exceptions -fno-rtti -std=gnu++0x
|
||||
LOCAL_CPPFLAGS := -fno-exceptions -std=gnu++11
|
||||
LOCAL_LDLIBS := -lz
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef _BASE_BASICTYPES
|
||||
#define _BASE_BASICTYPES
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h> // for byte swapping
|
||||
@ -92,5 +91,3 @@ inline uint64 swap64(const uint8* _pData) {return swap64(*(const uint64*)_pData)
|
||||
#ifndef TCHAR
|
||||
typedef char TCHAR;
|
||||
#endif
|
||||
|
||||
#endif // _BASE_BASICTYPES
|
||||
|
88
base/mutex.h
88
base/mutex.h
@ -1,19 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
// Simple cross platform mutex implementation.
|
||||
// Similar to the new C++11 api.
|
||||
|
||||
// Windows and pthreads implementations in one.
|
||||
|
||||
// TODO: Need to clean up these primitives and put them in a reasonable namespace.
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
|
||||
// Zap stupid windows defines
|
||||
// Should move these somewhere clever.
|
||||
#undef p
|
||||
#undef MIN
|
||||
#undef MAX
|
||||
#undef min
|
||||
#undef max
|
||||
#undef DrawText
|
||||
#undef itoa
|
||||
|
||||
@ -125,10 +126,11 @@ public:
|
||||
void wait(recursive_mutex &mtx) {
|
||||
// broken
|
||||
#ifdef _WIN32
|
||||
//mtx.unlock();
|
||||
// This has to be horribly racy.
|
||||
mtx.unlock();
|
||||
WaitForSingleObject(event_, INFINITE);
|
||||
ResetEvent(event_); // necessary?
|
||||
// mtx.lock();
|
||||
mtx.lock();
|
||||
#else
|
||||
pthread_mutex_lock(&mtx.native_handle());
|
||||
pthread_cond_wait(&event_, &mtx.native_handle());
|
||||
@ -167,3 +169,77 @@ private:
|
||||
pthread_cond_t event_;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
class condition_variable {
|
||||
public:
|
||||
#ifdef _WIN32
|
||||
#else
|
||||
#endif
|
||||
condition_variable() {
|
||||
#ifdef _WIN32
|
||||
event_ = CreateEvent(0, FALSE, FALSE, 0);
|
||||
#else
|
||||
pthread_cond_init(&event_, NULL);
|
||||
#endif
|
||||
}
|
||||
~condition_variable() {
|
||||
#ifdef _WIN32
|
||||
CloseHandle(event_);
|
||||
#else
|
||||
pthread_cond_destroy(&event_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void notify_one() {
|
||||
#ifdef _WIN32
|
||||
SetEvent(event_);
|
||||
#else
|
||||
pthread_cond_signal(&event_);
|
||||
#endif
|
||||
}
|
||||
|
||||
// notify_all is not really possible to implement with win32 events?
|
||||
|
||||
void wait(recursive_mutex &mtx) {
|
||||
// broken
|
||||
#ifdef _WIN32
|
||||
// This has to be horribly racy.
|
||||
mtx.unlock();
|
||||
WaitForSingleObject(event_, INFINITE);
|
||||
ResetEvent(event_); // necessary?
|
||||
mtx.lock();
|
||||
#else
|
||||
pthread_cond_wait(&event_, &mtx.native_handle());
|
||||
#endif
|
||||
}
|
||||
|
||||
void wait_for(recursive_mutex &mtx, int milliseconds) {
|
||||
#ifdef _WIN32
|
||||
//mtx.unlock();
|
||||
WaitForSingleObject(event_, milliseconds);
|
||||
ResetEvent(event_); // necessary?
|
||||
// mtx.lock();
|
||||
#else
|
||||
timespec timeout;
|
||||
#ifdef __APPLE__
|
||||
timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
timeout.tv_sec = tv.tv_sec;
|
||||
timeout.tv_nsec = tv.tv_usec * 1000;
|
||||
#else
|
||||
clock_gettime(CLOCK_REALTIME, &timeout);
|
||||
#endif
|
||||
timeout.tv_sec += milliseconds / 1000;
|
||||
timeout.tv_nsec += milliseconds * 1000000;
|
||||
pthread_cond_timedwait(&event_, &mtx.native_handle(), &timeout);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
HANDLE event_;
|
||||
#else
|
||||
pthread_cond_t event_;
|
||||
#endif
|
||||
};
|
||||
|
@ -168,15 +168,12 @@ bool getFileInfo(const char *path, FileInfo *fileInfo)
|
||||
|
||||
#ifdef _WIN32
|
||||
fileInfo->size = 0;
|
||||
FILE *f = fopen(path, "rb");
|
||||
if (f) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
fileInfo->size = ftell(f);
|
||||
fclose(f);
|
||||
WIN32_FILE_ATTRIBUTE_DATA attrs;
|
||||
if (GetFileAttributesExA(path, GetFileExInfoStandard, &attrs)) {
|
||||
fileInfo->size = (uint64_t)attrs.nFileSizeLow | ((uint64_t)attrs.nFileSizeHigh << 32);
|
||||
}
|
||||
DWORD attributes = GetFileAttributes(path);
|
||||
fileInfo->isDirectory = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
fileInfo->isWritable = (attributes & FILE_ATTRIBUTE_READONLY) == 0;
|
||||
fileInfo->isDirectory = (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
fileInfo->isWritable = (attrs.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0;
|
||||
#else
|
||||
struct stat64 file_info;
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/logging.h"
|
||||
#include "gfx/gl_lost_manager.h"
|
||||
|
||||
std::vector<GfxResourceHolder *> *holders;
|
||||
|
||||
GfxResourceHolder::~GfxResourceHolder() {}
|
||||
|
||||
static bool inLost;
|
||||
|
||||
void register_gl_resource_holder(GfxResourceHolder *holder) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
class GfxResourceHolder {
|
||||
public:
|
||||
virtual ~GfxResourceHolder();
|
||||
virtual ~GfxResourceHolder() {}
|
||||
virtual void GLLost() = 0;
|
||||
};
|
||||
|
||||
|
@ -33,6 +33,8 @@ float linearOut(int t, int fadeOutLength) {
|
||||
}
|
||||
|
||||
float ease(float val) {
|
||||
if (val > 1.0f) return 1.0f;
|
||||
if (val < 0.0f) return 0.0f;
|
||||
return ((-cosf(val * PI)) + 1.0f) * 0.5;
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,6 @@
|
||||
<ClInclude Include="base\scoped_ptr.h" />
|
||||
<ClInclude Include="base\stats.h" />
|
||||
<ClInclude Include="base\stringutil.h" />
|
||||
<ClInclude Include="base\threadutil.h" />
|
||||
<ClInclude Include="base\timeutil.h" />
|
||||
<ClInclude Include="data\listable.h" />
|
||||
<ClInclude Include="ext\cityhash\city.h" />
|
||||
@ -242,6 +241,9 @@
|
||||
<ClInclude Include="net\http_client.h" />
|
||||
<ClInclude Include="net\resolve.h" />
|
||||
<ClInclude Include="profiler\profiler.h" />
|
||||
<ClInclude Include="thread\prioritizedworkqueue.h" />
|
||||
<ClInclude Include="thread\thread.h" />
|
||||
<ClInclude Include="thread\threadutil.h" />
|
||||
<ClInclude Include="ui\screen.h" />
|
||||
<ClInclude Include="ui\ui.h" />
|
||||
<ClInclude Include="ui\ui_context.h" />
|
||||
@ -290,7 +292,6 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="base\stringutil.cpp" />
|
||||
<ClCompile Include="base\threadutil.cpp" />
|
||||
<ClCompile Include="base\timeutil.cpp" />
|
||||
<ClCompile Include="ext\cityhash\city.cpp" />
|
||||
<ClCompile Include="ext\rg_etc1\rg_etc1.cpp" />
|
||||
@ -331,6 +332,8 @@
|
||||
<ClCompile Include="net\http_client.cpp" />
|
||||
<ClCompile Include="net\resolve.cpp" />
|
||||
<ClCompile Include="profiler\profiler.cpp" />
|
||||
<ClCompile Include="thread\prioritizedworkqueue.cpp" />
|
||||
<ClCompile Include="thread\threadutil.cpp" />
|
||||
<ClCompile Include="ui\screen.cpp" />
|
||||
<ClCompile Include="ui\ui.cpp" />
|
||||
<ClCompile Include="ui\ui_context.cpp" />
|
||||
|
@ -206,9 +206,6 @@
|
||||
<ClInclude Include="util\random\rng.h">
|
||||
<Filter>util</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="base\threadutil.h">
|
||||
<Filter>base</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ext\stb_image\stb_image.h">
|
||||
<Filter>ext</Filter>
|
||||
</ClInclude>
|
||||
@ -239,6 +236,15 @@
|
||||
<ClInclude Include="ext\rg_etc1\rg_etc1.h">
|
||||
<Filter>ext</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="thread\prioritizedworkqueue.h">
|
||||
<Filter>thread</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="thread\thread.h">
|
||||
<Filter>thread</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="thread\threadutil.h">
|
||||
<Filter>thread</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="gfx\gl_debug_log.cpp">
|
||||
@ -388,9 +394,6 @@
|
||||
<ClCompile Include="util\random\perlin.cpp">
|
||||
<Filter>util</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="base\threadutil.cpp">
|
||||
<Filter>base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ext\stb_image\stb_image.c">
|
||||
<Filter>ext</Filter>
|
||||
</ClCompile>
|
||||
@ -423,6 +426,12 @@
|
||||
<ClCompile Include="ext\rg_etc1\rg_etc1.cpp">
|
||||
<Filter>ext</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="thread\prioritizedworkqueue.cpp">
|
||||
<Filter>thread</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="thread\threadutil.cpp">
|
||||
<Filter>thread</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="gfx">
|
||||
@ -482,5 +491,8 @@
|
||||
<Filter Include="tools">
|
||||
<UniqueIdentifier>{4515306f-4664-46bf-a89b-abfec5520a15}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="thread">
|
||||
<UniqueIdentifier>{caa41117-1d90-47cc-9fba-f7e670e315a3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
82
thread/prioritizedworkqueue.cpp
Normal file
82
thread/prioritizedworkqueue.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
#include <functional>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "thread/thread.h"
|
||||
#include "thread/prioritizedworkqueue.h"
|
||||
|
||||
#if defined(IOS) || (defined(__APPLE__) && !defined(__MAC_10_7))
|
||||
namespace std {
|
||||
using tr1::bind;
|
||||
}
|
||||
#endif
|
||||
|
||||
PrioritizedWorkQueue::~PrioritizedWorkQueue() {
|
||||
if (!done_) {
|
||||
ELOG("PrioritizedWorkQueue destroyed but not done!");
|
||||
}
|
||||
}
|
||||
|
||||
void PrioritizedWorkQueue::Add(PrioritizedWorkQueueItem *item) {
|
||||
mutex_.lock();
|
||||
queue_.push_back(item);
|
||||
mutex_.unlock();
|
||||
notEmpty_.notify_one();
|
||||
}
|
||||
|
||||
void PrioritizedWorkQueue::Stop() {
|
||||
mutex_.lock();
|
||||
done_ = true;
|
||||
notEmpty_.notify_one();
|
||||
mutex_.unlock();
|
||||
}
|
||||
|
||||
// The worker should simply call this in a loop. Will block when appropriate.
|
||||
PrioritizedWorkQueueItem *PrioritizedWorkQueue::Pop() {
|
||||
mutex_.lock();
|
||||
while (queue_.empty()) {
|
||||
notEmpty_.wait(mutex_);
|
||||
if (done_)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Find the top priority item (lowest value).
|
||||
float best_prio = std::numeric_limits<float>::infinity();
|
||||
std::vector<PrioritizedWorkQueueItem *>::iterator best = queue_.end();
|
||||
for (auto iter = queue_.begin(); iter != queue_.end(); ++iter) {
|
||||
if ((*iter)->priority() < best_prio) {
|
||||
best = iter;
|
||||
best_prio = (*iter)->priority();
|
||||
}
|
||||
}
|
||||
PrioritizedWorkQueueItem *poppedItem = *best;
|
||||
queue_.erase(best);
|
||||
mutex_.unlock();
|
||||
return poppedItem;
|
||||
}
|
||||
|
||||
// TODO: This feels ugly. Revisit later.
|
||||
|
||||
static std::thread *workThread;
|
||||
|
||||
static void threadfunc(PrioritizedWorkQueue *wq) {
|
||||
while (true) {
|
||||
PrioritizedWorkQueueItem *item = wq->Pop();
|
||||
if (!item) {
|
||||
if (wq->Done())
|
||||
break;
|
||||
} else {
|
||||
item->run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessWorkQueueOnThreadWhile(PrioritizedWorkQueue *wq) {
|
||||
workThread = new std::thread(std::bind(&threadfunc, wq));
|
||||
}
|
||||
|
||||
void StopProcessingWorkQueue(PrioritizedWorkQueue *wq) {
|
||||
wq->Stop();
|
||||
workThread->join();
|
||||
delete workThread;
|
||||
workThread = 0;
|
||||
}
|
51
thread/prioritizedworkqueue.h
Normal file
51
thread/prioritizedworkqueue.h
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/mutex.h"
|
||||
#include "thread/threadutil.h"
|
||||
|
||||
// Priorities can change dynamically.
|
||||
// Try to make priority() fast, it will be called a lot.
|
||||
|
||||
class PrioritizedWorkQueueItem {
|
||||
public:
|
||||
PrioritizedWorkQueueItem() {}
|
||||
virtual ~PrioritizedWorkQueueItem() {}
|
||||
virtual void run() = 0;
|
||||
virtual float priority() = 0; // Low priority value = high priority!
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(PrioritizedWorkQueueItem);
|
||||
};
|
||||
|
||||
class PrioritizedWorkQueue {
|
||||
public:
|
||||
PrioritizedWorkQueue() : done_(false) {}
|
||||
~PrioritizedWorkQueue();
|
||||
// Takes ownership.
|
||||
void Add(PrioritizedWorkQueueItem *item);
|
||||
|
||||
// The worker should simply call this in a loop. Will block when appropriate.
|
||||
PrioritizedWorkQueueItem *Pop();
|
||||
|
||||
bool Done() { return done_; }
|
||||
void Stop();
|
||||
|
||||
private:
|
||||
bool done_;
|
||||
recursive_mutex mutex_;
|
||||
condition_variable notEmpty_;
|
||||
|
||||
std::vector<PrioritizedWorkQueueItem *> queue_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrioritizedWorkQueue);
|
||||
};
|
||||
|
||||
|
||||
// Starts up a thread that keeps trying to run this workqueue.
|
||||
// TODO: This feels ugly. Revisit later.
|
||||
void ProcessWorkQueueOnThreadWhile(PrioritizedWorkQueue *wq);
|
||||
void StopProcessingWorkQueue(PrioritizedWorkQueue *wq);
|
310
thread/thread.h
Normal file
310
thread/thread.h
Normal file
@ -0,0 +1,310 @@
|
||||
|
||||
#ifndef STD_THREAD_H_
|
||||
#define STD_THREAD_H_
|
||||
|
||||
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
|
||||
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
|
||||
|
||||
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !defined(ANDROID) && !defined(__SYMBIAN32__)
|
||||
// GCC 4.4 provides <thread>
|
||||
#ifndef _GLIBCXX_USE_SCHED_YIELD
|
||||
#define _GLIBCXX_USE_SCHED_YIELD
|
||||
#endif
|
||||
#include <thread>
|
||||
#else
|
||||
|
||||
// partial std::thread implementation for win32/pthread
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
|
||||
#define USE_RVALUE_REFERENCES
|
||||
#endif
|
||||
|
||||
//#ifdef __APPLE__
|
||||
//#import <Foundation/NSAutoreleasePool.h>
|
||||
//#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
// WIN32
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
#if defined(_MSC_VER) && defined(_MT)
|
||||
// When linking with LIBCMT (the multithreaded C library), Microsoft recommends
|
||||
// using _beginthreadex instead of CreateThread.
|
||||
#define USE_BEGINTHREADEX
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_BEGINTHREADEX
|
||||
#define THREAD_ID unsigned
|
||||
#define THREAD_RETURN unsigned __stdcall
|
||||
#else
|
||||
#define THREAD_ID DWORD
|
||||
#define THREAD_RETURN DWORD WINAPI
|
||||
#endif
|
||||
#define THREAD_HANDLE HANDLE
|
||||
|
||||
#else
|
||||
// PTHREAD
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef _POSIX_THREADS
|
||||
#error unsupported platform (no pthreads?)
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define THREAD_ID pthread_t
|
||||
#define THREAD_HANDLE pthread_t
|
||||
#define THREAD_RETURN void*
|
||||
|
||||
#endif
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
class thread
|
||||
{
|
||||
public:
|
||||
typedef THREAD_HANDLE native_handle_type;
|
||||
|
||||
class id
|
||||
{
|
||||
friend class thread;
|
||||
public:
|
||||
id() : m_thread(0) {}
|
||||
id(THREAD_ID _id) : m_thread(_id) {}
|
||||
|
||||
bool operator==(const id& rhs) const
|
||||
{
|
||||
return m_thread == rhs.m_thread;
|
||||
}
|
||||
|
||||
bool operator!=(const id& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
bool operator<(const id& rhs) const
|
||||
{
|
||||
return m_thread < rhs.m_thread;
|
||||
}
|
||||
|
||||
private:
|
||||
THREAD_ID m_thread;
|
||||
};
|
||||
|
||||
// no variadic template support in msvc
|
||||
//template <typename C, typename... A>
|
||||
//thread(C&& func, A&&... args);
|
||||
|
||||
template <typename C>
|
||||
thread(C func)
|
||||
{
|
||||
StartThread(new Func<C>(func));
|
||||
}
|
||||
|
||||
template <typename C, typename A>
|
||||
thread(C func, A arg)
|
||||
{
|
||||
StartThread(new FuncArg<C, A>(func, arg));
|
||||
}
|
||||
|
||||
thread() /*= default;*/ {}
|
||||
|
||||
#ifdef USE_RVALUE_REFERENCES
|
||||
thread(const thread&) /*= delete*/;
|
||||
|
||||
thread(thread&& other)
|
||||
{
|
||||
#else
|
||||
thread(const thread& t)
|
||||
{
|
||||
// ugly const_cast to get around lack of rvalue references
|
||||
thread& other = const_cast<thread&>(t);
|
||||
#endif
|
||||
swap(other);
|
||||
}
|
||||
|
||||
#ifdef USE_RVALUE_REFERENCES
|
||||
thread& operator=(const thread&) /*= delete*/;
|
||||
|
||||
thread& operator=(thread&& other)
|
||||
{
|
||||
#else
|
||||
thread& operator=(const thread& t)
|
||||
{
|
||||
// ugly const_cast to get around lack of rvalue references
|
||||
thread& other = const_cast<thread&>(t);
|
||||
#endif
|
||||
if (joinable())
|
||||
detach();
|
||||
swap(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~thread()
|
||||
{
|
||||
if (joinable())
|
||||
detach();
|
||||
}
|
||||
|
||||
bool joinable() const
|
||||
{
|
||||
return m_id != id();
|
||||
}
|
||||
|
||||
id get_id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
native_handle_type native_handle()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return m_handle;
|
||||
#else
|
||||
return m_id.m_thread;
|
||||
#endif
|
||||
}
|
||||
|
||||
void join()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WaitForSingleObject(m_handle, INFINITE);
|
||||
detach();
|
||||
#else
|
||||
pthread_join(m_id.m_thread, NULL);
|
||||
m_id = id();
|
||||
#endif
|
||||
}
|
||||
|
||||
void detach()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
CloseHandle(m_handle);
|
||||
#else
|
||||
pthread_detach(m_id.m_thread);
|
||||
#endif
|
||||
m_id = id();
|
||||
}
|
||||
|
||||
void swap(thread& other)
|
||||
{
|
||||
std::swap(m_id, other.m_id);
|
||||
#ifdef _WIN32
|
||||
std::swap(m_handle, other.m_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned hardware_concurrency()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO sysinfo;
|
||||
GetSystemInfo(&sysinfo);
|
||||
return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
id m_id;
|
||||
|
||||
#ifdef _WIN32
|
||||
native_handle_type m_handle;
|
||||
#endif
|
||||
|
||||
template <typename F>
|
||||
void StartThread(F* param)
|
||||
{
|
||||
#ifdef USE_BEGINTHREADEX
|
||||
m_handle = (HANDLE)_beginthreadex(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
|
||||
#elif defined(_WIN32)
|
||||
m_handle = CreateThread(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
|
||||
#else
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setstacksize(&attr, 1024 * 1024);
|
||||
if (pthread_create(&m_id.m_thread, &attr, &RunAndDelete<F>, param))
|
||||
m_id = id();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename C>
|
||||
class Func
|
||||
{
|
||||
public:
|
||||
Func(C _func) : func(_func) {}
|
||||
|
||||
void Run() { func(); }
|
||||
|
||||
private:
|
||||
C const func;
|
||||
};
|
||||
|
||||
template <typename C, typename A>
|
||||
class FuncArg
|
||||
{
|
||||
public:
|
||||
FuncArg(C _func, A _arg) : func(_func), arg(_arg) {}
|
||||
|
||||
void Run() { func(arg); }
|
||||
|
||||
private:
|
||||
C const func;
|
||||
A arg;
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
static THREAD_RETURN RunAndDelete(void* param)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
#endif
|
||||
static_cast<F*>(param)->Run();
|
||||
delete static_cast<F*>(param);
|
||||
#ifdef __APPLE__
|
||||
// [pool release];
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
|
||||
inline void yield()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SwitchToThread();
|
||||
#else
|
||||
sleep(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline thread::id get_id()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return GetCurrentThreadId();
|
||||
#else
|
||||
return pthread_self();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace this_thread
|
||||
|
||||
} // namespace std
|
||||
|
||||
#undef USE_RVALUE_REFERENCES
|
||||
#undef USE_BEGINTHREADEX
|
||||
#undef THREAD_ID
|
||||
#undef THREAD_RETURN
|
||||
#undef THREAD_HANDLE
|
||||
|
||||
#endif
|
||||
#endif
|
@ -1,7 +1,7 @@
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include "base/threadutil.h"
|
||||
#include "thread/threadutil.h"
|
||||
|
||||
void setCurrentThreadName(const char* szThreadName)
|
||||
{
|
@ -3,7 +3,10 @@
|
||||
#include <functional>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
|
||||
#include <unistd.h>
|
||||
@ -36,3 +39,18 @@ public:
|
||||
|
||||
}
|
||||
};*/
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define THREAD_HANDLE HANDLE
|
||||
#else
|
||||
#define THREAD_HANDLE pthread_t
|
||||
#endif
|
||||
|
||||
|
||||
// TODO: replace this abomination with std::thread
|
||||
|
||||
class thread {
|
||||
public:
|
||||
virtual void Run();
|
||||
};
|
@ -3,9 +3,6 @@
|
||||
#include "ui/screen.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
Screen::Screen(bool isUiScreen) : screenManager_(0), isUiScreen_(isUiScreen) { }
|
||||
Screen::~Screen() { }
|
||||
|
||||
ScreenManager::ScreenManager() {
|
||||
nextScreen_ = 0;
|
||||
uiContext_ = 0;
|
||||
|
@ -33,8 +33,9 @@ class UIContext;
|
||||
|
||||
class Screen {
|
||||
public:
|
||||
Screen(bool isUiScreen = false);
|
||||
virtual ~Screen();
|
||||
Screen(bool isUiScreen = false) : screenManager_(0), isUiScreen_(isUiScreen) { }
|
||||
virtual ~Screen() {}
|
||||
|
||||
virtual void update(InputState &input) = 0;
|
||||
virtual void render() {}
|
||||
virtual void deviceLost() {}
|
||||
|
@ -234,7 +234,7 @@ int UIImageButton(int id, const LayoutManager &layout, float w, int image, int b
|
||||
return clicked;
|
||||
}
|
||||
|
||||
int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align) // uses current UI atlas for fetching images.
|
||||
int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align, uint32_t color) // uses current UI atlas for fetching images.
|
||||
{
|
||||
float x, y;
|
||||
layout.GetPos(&w, &h, &x, &y);
|
||||
@ -294,7 +294,7 @@ int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w
|
||||
Texture::Unbind();
|
||||
}
|
||||
|
||||
ui_draw2d.DrawTexRect(x, y, x+w, y+h, 0, 0, 1, 1, 0xFFFFFFFF);
|
||||
ui_draw2d.DrawTexRect(x, y, x+w, y+h, 0, 0, 1, 1, color);
|
||||
ui_draw2d.Flush();
|
||||
ctx->RebindTexture();
|
||||
|
||||
|
4
ui/ui.h
4
ui/ui.h
@ -20,7 +20,7 @@
|
||||
#define GEN_ID_LOOP(i) (int)((IMGUI_SRC_ID) + (__LINE__) + (i) * 13612)
|
||||
#else
|
||||
#define GEN_ID (__LINE__)
|
||||
#define GEN_ID_LOOP(i) ((__LINE__) + (i) * 13612)
|
||||
#define GEN_ID_LOOP(i) ((__LINE__) + ((int)i) * 13612)
|
||||
#endif
|
||||
|
||||
#include "gfx_es2/draw_buffer.h"
|
||||
@ -244,7 +244,7 @@ void UIReset();
|
||||
// Returns 1 if clicked
|
||||
int UIButton(int id, const LayoutManager &layout, float w, float h, const char *text, int button_align);
|
||||
int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, int button_align); // uses current UI atlas for fetching images.
|
||||
int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align); // uses current UI atlas for fetching images.
|
||||
int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align, uint32_t color = 0xFFFFFFFF); // uses current UI atlas for fetching images.
|
||||
|
||||
// Returns 1 if clicked, puts the value in *value (where it also gets the current state).
|
||||
int UICheckBox(int id, int x, int y, const char *text, int align, bool *value);
|
||||
|
Loading…
x
Reference in New Issue
Block a user