瀏覽代碼

base: re-add the threading and getopt classes.

wip/core-clipp
Sam Hocevar 5 年之前
父節點
當前提交
c45a494ad5
共有 7 個檔案被更改,包括 107 行新增47 行删除
  1. +43
    -0
      include/lol/base/core.h
  2. +0
    -0
      include/lol/base/getopt.h
  3. +1
    -0
      include/lol/base/string.h
  4. +60
    -45
      include/lol/base/thread.h
  5. +2
    -0
      include/lol/math/polynomial.h
  6. +1
    -0
      include/lol/math/real.h
  7. +0
    -2
      legacy/lol/base/features.h

+ 43
- 0
include/lol/base/core.h 查看文件

@@ -0,0 +1,43 @@
//
// Lol Engine
//
// Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#pragma once

#include <cstdlib> // _dupenv_s / std::getenv

namespace lol
{

namespace os
{

static inline std::string getenv(std::string const &var)
{
#if _MSC_VER
char *buf = nullptr;
size_t count = 0;
if (_dupenv_s(&buf, &count, var.c_str()) == 0 && buf)
{
std::string ret(buf);
free(buf);
return ret;
}
#else
if (auto val = std::getenv(var.c_str()))
return std::string(val);
#endif
return std::string();
}

} // namespace os

} // namespace lol

legacy/lol/sys/getopt.h → include/lol/base/getopt.h 查看文件


+ 1
- 0
include/lol/base/string.h 查看文件

@@ -20,6 +20,7 @@
// //


#include <lol/base/features.h> #include <lol/base/features.h>
#include <lol/base/core.h>


#include <vector> #include <vector>
#include <string> #include <string>


legacy/lol/sys/thread.h → include/lol/base/thread.h 查看文件

@@ -1,7 +1,7 @@
// //
// Lol Engine // Lol Engine
// //
// Copyright © 2010—2019 Sam Hocevar <sam@hocevar.net>
// Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net>
// //
// Lol Engine is free software. It comes without any warranty, to // Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it // the extent permitted by applicable law. You can redistribute it
@@ -14,14 +14,17 @@


// //
// The Threading classes // The Threading classes
// ---------------------
// —————————————————————
// //


#include <functional>
#include <lol/base/features.h>
#include <lol/base/core.h>


#include <functional> // std::function
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <condition_variable> #include <condition_variable>
#include <cassert> // assert()


/* XXX: workaround for a bug in Visual Studio 2012 and 2013! /* XXX: workaround for a bug in Visual Studio 2012 and 2013!
* https://connect.microsoft.com/VisualStudio/feedback/details/747145 */ * https://connect.microsoft.com/VisualStudio/feedback/details/747145 */
@@ -38,9 +41,9 @@


/* XXX: workaround for missing std::thread in mingw */ /* XXX: workaround for missing std::thread in mingw */
#if _GLIBCXX_MUTEX && !_GLIBCXX_HAS_GTHREADS && _WIN32 #if _GLIBCXX_MUTEX && !_GLIBCXX_HAS_GTHREADS && _WIN32
# include "mingw.thread.h"
# include "mingw.mutex.h"
# include "mingw.condition_variable.h"
# include "../3rdparty/mingw-std-threads/mingw.thread.h"
# include "../3rdparty/mingw-std-threads/mingw.mutex.h"
# include "../3rdparty/mingw-std-threads/mingw.condition_variable.h"
# undef near /* Fuck Microsoft */ # undef near /* Fuck Microsoft */
# undef far /* Fuck Microsoft again */ # undef far /* Fuck Microsoft again */
#endif #endif
@@ -48,6 +51,50 @@
namespace lol namespace lol
{ {


// Base class for threads
class thread
{
public:
thread(std::function<void(thread*)> fn)
: m_function(fn)
{
m_thread = std::thread(trampoline, this);
}

~thread()
{
#if LOL_VISUAL_STUDIO_BUG_747145_WORKAROUND
m_thread.detach();
#else
m_thread.join();
#endif
}

// FIXME: move to os::has_threads?
static bool has_threads()
{
static bool const disable_threads = os::getenv("LOL_NOTHREADS").size() > 0;
#if defined __EMSCRIPTEN__ && !defined __EMSCRIPTEN_PTHREADS__
// For some reason hardware_concurrency() will return the actual number
// of threads/cores even though the system cannot spawn threads.
return false;
#endif
return !disable_threads && std::thread::hardware_concurrency() > 1;
}

private:
static void trampoline(thread *that)
{
that->m_function(that);
#if LOL_VISUAL_STUDIO_BUG_747145_WORKAROUND
ExitThread(0);
#endif
}

std::thread m_thread;
std::function<void(thread*)> m_function;
};

// This is like std::mutex but we can add debug information to it // This is like std::mutex but we can add debug information to it
class mutex class mutex
{ {
@@ -74,7 +121,7 @@ public:
{ {
std::unique_lock<std::mutex> uni_lock(m_mutex); std::unique_lock<std::mutex> uni_lock(m_mutex);


if (has_threads())
if (thread::has_threads())
{ {
// Wait for the mutex availability or non-fullness // Wait for the mutex availability or non-fullness
m_full_cond.wait(uni_lock, [&]{ return m_count < CAPACITY; }); m_full_cond.wait(uni_lock, [&]{ return m_count < CAPACITY; });
@@ -82,7 +129,7 @@ public:


do_push(value); /* Push value */ do_push(value); /* Push value */


if (has_threads())
if (thread::has_threads())
{ {
// Release lock and notify empty condition var (in that order) // Release lock and notify empty condition var (in that order)
uni_lock.unlock(); uni_lock.unlock();
@@ -95,7 +142,7 @@ public:
{ {
std::unique_lock<std::mutex> uni_lock(m_mutex, std::defer_lock); std::unique_lock<std::mutex> uni_lock(m_mutex, std::defer_lock);


if (has_threads())
if (thread::has_threads())
{ {
// Try to lock, bail out if we fail // Try to lock, bail out if we fail
if (!uni_lock.try_lock()) if (!uni_lock.try_lock())
@@ -107,7 +154,7 @@ public:


do_push(value); do_push(value);


if (has_threads())
if (thread::has_threads())
{ {
// Release lock and notify empty condition var (in that order) // Release lock and notify empty condition var (in that order)
uni_lock.unlock(); uni_lock.unlock();
@@ -120,7 +167,7 @@ public:
// Will block the thread if another has already locked // Will block the thread if another has already locked
T pop() T pop()
{ {
ASSERT(has_threads(), "Pop should only be used with threads. Use try_pop instead.");
assert(thread::has_threads());


// Wait for the mutex availability or non-emptiness // Wait for the mutex availability or non-emptiness
std::unique_lock<std::mutex> uni_lock(m_mutex); std::unique_lock<std::mutex> uni_lock(m_mutex);
@@ -140,7 +187,7 @@ public:
{ {
std::unique_lock<std::mutex> uni_lock(m_mutex, std::defer_lock); std::unique_lock<std::mutex> uni_lock(m_mutex, std::defer_lock);


if (has_threads())
if (thread::has_threads())
{ {
if (!uni_lock.try_lock()) if (!uni_lock.try_lock())
return false; return false;
@@ -151,7 +198,7 @@ public:


ret = do_pop(); /* Pop value */ ret = do_pop(); /* Pop value */


if (has_threads())
if (thread::has_threads())
{ {
// Release lock and notify full condition var (in that order) // Release lock and notify full condition var (in that order)
uni_lock.unlock(); uni_lock.unlock();
@@ -186,37 +233,5 @@ private:
std::condition_variable m_empty_cond, m_full_cond; std::condition_variable m_empty_cond, m_full_cond;
}; };


// Base class for threads
class thread
{
public:
thread(std::function<void(thread*)> fn)
: m_function(fn)
{
m_thread = std::thread(trampoline, this);
}

~thread()
{
#if LOL_VISUAL_STUDIO_BUG_747145_WORKAROUND
m_thread.detach();
#else
m_thread.join();
#endif
}

private:
static void trampoline(thread *that)
{
that->m_function(that);
#if LOL_VISUAL_STUDIO_BUG_747145_WORKAROUND
ExitThread(0);
#endif
}

std::thread m_thread;
std::function<void(thread*)> m_function;
};

} /* namespace lol */ } /* namespace lol */



+ 2
- 0
include/lol/math/polynomial.h 查看文件

@@ -20,6 +20,8 @@
// //


#include <lol/base/features.h> #include <lol/base/features.h>
#include <lol/base/core.h>

#include <tuple> // std::tuple #include <tuple> // std::tuple
#include <cassert> // assert() #include <cassert> // assert()




+ 1
- 0
include/lol/math/real.h 查看文件

@@ -18,6 +18,7 @@
// //


#include <lol/base/features.h> #include <lol/base/features.h>
#include <lol/base/core.h>


#include <vector> #include <vector>
#include <string> #include <string>


+ 0
- 2
legacy/lol/base/features.h 查看文件

@@ -118,8 +118,6 @@ static inline int isnan(float f)


namespace lol namespace lol
{ {
extern bool has_threads();

// A handy endianness test function // A handy endianness test function
static inline bool is_big_endian() static inline bool is_big_endian()
{ {


Loading…
取消
儲存