bsnes/nall/thread.hpp
Tim Allen 82293c95ae Update to v099r14 release.
byuu says:

Changelog:
- (u)int(max,ptr) abbreviations removed; use _t suffix now [didn't feel
  like they were contributing enough to be worth it]
- cleaned up nall::integer,natural,real functionality
  - toInteger, toNatural, toReal for parsing strings to numbers
  - fromInteger, fromNatural, fromReal for creating strings from numbers
  - (string,Markup::Node,SQL-based-classes)::(integer,natural,real)
    left unchanged
  - template<typename T> numeral(T value, long padding, char padchar)
    -> string for print() formatting
    - deduces integer,natural,real based on T ... cast the value if you
      want to override
    - there still exists binary,octal,hex,pointer for explicit print()
      formatting
- lstring -> string_vector [but using lstring = string_vector; is
  declared]
  - would be nice to remove the using lstring eventually ... but that'd
    probably require 10,000 lines of changes >_>
- format -> string_format [no using here; format was too ambiguous]
- using integer = Integer<sizeof(int)*8>; and using natural =
  Natural<sizeof(uint)*8>; declared
  - for consistency with boolean. These three are meant for creating
    zero-initialized values implicitly (various uses)
- R65816::io() -> idle() and SPC700::io() -> idle() [more clear; frees
  up struct IO {} io; naming]
- SFC CPU, PPU, SMP use struct IO {} io; over struct (Status,Registers) {}
  (status,registers); now
  - still some CPU::Status status values ... they didn't really fit into
    IO functionality ... will have to think about this more
- SFC CPU, PPU, SMP now use step() exclusively instead of addClocks()
  calling into step()
- SFC CPU joypad1_bits, joypad2_bits were unused; killed them
- SFC PPU CGRAM moved into PPU::Screen; since nothing else uses it
- SFC PPU OAM moved into PPU::Object; since nothing else uses it
  - the raw uint8[544] array is gone. OAM::read() constructs values from
    the OAM::Object[512] table now
  - this avoids having to determine how we want to sub-divide the two
    OAM memory sections
  - this also eliminates the OAM::synchronize() functionality
- probably more I'm forgetting

The FPS fluctuations are driving me insane. This WIP went from 128fps to
137fps. Settled on 133.5fps for the final build. But nothing I changed
should have affected performance at all. This level of fluctuation makes
it damn near impossible to know whether I'm speeding things up or slowing
things down with changes.
2016-07-01 21:50:32 +10:00

138 lines
3.1 KiB
C++

#pragma once
//simple thread library
//primary rationale is that std::thread does not support custom stack sizes
//this is highly critical in certain applications such as threaded web servers
//an added bonus is that it avoids licensing issues on Windows
//win32-pthreads (needed for std::thread) is licensed under the GPL only
#include <nall/platform.hpp>
#include <nall/function.hpp>
#include <nall/intrinsics.hpp>
#if defined(API_POSIX)
#include <pthread.h>
namespace nall {
struct thread {
inline auto join() -> void;
static inline auto create(const function<void (uintptr_t)>& callback, uintptr_t parameter = 0, uint stacksize = 0) -> thread;
static inline auto detach() -> void;
static inline auto exit() -> void;
struct context {
function<auto (uintptr_t) -> void> callback;
uintptr_t parameter = 0;
};
private:
pthread_t handle;
};
inline auto _threadCallback(void* parameter) -> void* {
auto context = (thread::context*)parameter;
context->callback(context->parameter);
delete context;
return nullptr;
}
auto thread::join() -> void {
pthread_join(handle, nullptr);
}
auto thread::create(const function<void (uintptr_t)>& callback, uintptr_t parameter, uint stacksize) -> thread {
thread instance;
auto context = new thread::context;
context->callback = callback;
context->parameter = parameter;
pthread_attr_t attr;
pthread_attr_init(&attr);
if(stacksize) pthread_attr_setstacksize(&attr, max(PTHREAD_STACK_MIN, stacksize));
pthread_create(&instance.handle, &attr, _threadCallback, (void*)context);
return instance;
}
auto thread::detach() -> void {
pthread_detach(pthread_self());
}
auto thread::exit() -> void {
pthread_exit(nullptr);
}
}
#elif defined(API_WINDOWS)
namespace nall {
struct thread {
inline ~thread();
inline auto join() -> void;
static inline auto create(const function<void (uintptr_t)>& callback, uintptr_t parameter = 0, uint stacksize = 0) -> thread;
static inline auto detach() -> void;
static inline auto exit() -> void;
struct context {
function<auto (uintptr_t) -> void> callback;
uintptr_t parameter = 0;
};
private:
HANDLE handle = 0;
};
inline auto WINAPI _threadCallback(void* parameter) -> DWORD {
auto context = (thread::context*)parameter;
context->callback(context->parameter);
delete context;
return 0;
}
thread::~thread() {
if(handle) {
CloseHandle(handle);
handle = 0;
}
}
auto thread::join() -> void {
if(handle) {
WaitForSingleObject(handle, INFINITE);
CloseHandle(handle);
handle = 0;
}
}
auto thread::create(const function<void (uintptr_t)>& callback, uintptr_t parameter, uint stacksize) -> thread {
thread instance;
auto context = new thread::context;
context->callback = callback;
context->parameter = parameter;
instance.handle = CreateThread(nullptr, stacksize, _threadCallback, (void*)context, 0, nullptr);
return instance;
}
auto thread::detach() -> void {
//Windows threads do not use this concept:
//~thread() frees resources via CloseHandle()
//thread continues to run even after handle is closed
}
auto thread::exit() -> void {
ExitThread(0);
}
}
#endif