Browse Source

base: re-add the threading and getopt classes.

wip/core-clipp
Sam Hocevar 4 years ago
parent
commit
c45a494ad5
7 changed files with 107 additions and 47 deletions
  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 View File

@@ -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 View File


+ 1
- 0
include/lol/base/string.h View File

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

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

#include <vector>
#include <string>


legacy/lol/sys/thread.h → include/lol/base/thread.h View File

@@ -1,7 +1,7 @@
//
// 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
// the extent permitted by applicable law. You can redistribute it
@@ -14,14 +14,17 @@

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

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

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

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

/* XXX: workaround for missing std::thread in mingw */
#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 far /* Fuck Microsoft again */
#endif
@@ -48,6 +51,50 @@
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
class mutex
{
@@ -74,7 +121,7 @@ public:
{
std::unique_lock<std::mutex> uni_lock(m_mutex);

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

do_push(value); /* Push value */

if (has_threads())
if (thread::has_threads())
{
// Release lock and notify empty condition var (in that order)
uni_lock.unlock();
@@ -95,7 +142,7 @@ public:
{
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
if (!uni_lock.try_lock())
@@ -107,7 +154,7 @@ public:

do_push(value);

if (has_threads())
if (thread::has_threads())
{
// Release lock and notify empty condition var (in that order)
uni_lock.unlock();
@@ -120,7 +167,7 @@ public:
// Will block the thread if another has already locked
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
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);

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

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

if (has_threads())
if (thread::has_threads())
{
// Release lock and notify full condition var (in that order)
uni_lock.unlock();
@@ -186,37 +233,5 @@ private:
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 */


+ 2
- 0
include/lol/math/polynomial.h View File

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

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

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



+ 1
- 0
include/lol/math/real.h View File

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

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

#include <vector>
#include <string>


+ 0
- 2
legacy/lol/base/features.h View File

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

namespace lol
{
extern bool has_threads();

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


Loading…
Cancel
Save