1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#ifndef _THREADING_H_
#define _THREADING_H_
#include <string>
#ifdef WIN32
#include <windows.h> // HANDLE & DWORD
#else
#include <pthread.h>
#endif
#ifdef __APPLE__
#include <libkern/OSAtomic.h> // OSAtomicIncrement64
#endif
#include "System/Platform/Win/win32.h"
#include <boost/cstdint.hpp>
namespace Threading {
/**
* Generic types & functions to handle OS native threads
*/
#ifdef WIN32
typedef DWORD NativeThreadId;
typedef HANDLE NativeThreadHandle;
#else
typedef pthread_t NativeThreadId;
typedef pthread_t NativeThreadHandle;
#endif
NativeThreadHandle GetCurrentThread();
NativeThreadId GetCurrentThreadId();
inline bool NativeThreadIdsEqual(const NativeThreadId thID1, const NativeThreadId thID2);
/**
* Sets the affinity of the current thread
*
* Interpret <cores_bitmask> as a bit-mask indicating on which of the available system CPU's (which
* are numbered logically from 1 to N) we want to run.
* Note: that this approach will fail when N > 32.
*/
boost::uint32_t SetAffinity(boost::uint32_t cores_bitmask, bool hard = true);
unsigned GetAvailableCores();
/**
* Used to detect the main-thread which runs SDL, GL, Input, Sim, ...
*/
void SetMainThread();
bool IsMainThread();
bool IsMainThread(NativeThreadId threadID);
/**
* GML Functions
*/
void SetSimThread(bool set);
bool IsSimThread();
void SetBatchThread(bool set);
bool IsBatchThread();
/**
* Give the current thread a name (posix-only)
*/
void SetThreadName(std::string newname);
/**
* Used to raise errors in the main-thread issued by worker-threads
*/
struct Error {
Error() : flags(0) {}
Error(const std::string& _caption, const std::string& _message, const unsigned int _flags) : caption(_caption), message(_message), flags(_flags) {}
std::string caption;
std::string message;
unsigned int flags;
};
void SetThreadError(const Error& err);
Error* GetThreadError();
/**
* A 64bit atomic counter
*/
struct AtomicCounterInt64;
};
//
// Inlined Definitions
//
namespace Threading {
bool NativeThreadIdsEqual(const NativeThreadId thID1, const NativeThreadId thID2)
{
#ifdef WIN32
return (thID1 == thID2);
#else
return pthread_equal(thID1, thID2);
#endif
}
struct AtomicCounterInt64 {
public:
AtomicCounterInt64(boost::int64_t start = 0) : num(start) {}
boost::int64_t operator++() {
#ifdef _MSC_VER
return InterlockedIncrement64(&num);
#elif defined(__APPLE__)
return OSAtomicIncrement64(&num);
#else // assuming GCC (__sync_fetch_and_add is a builtin)
return __sync_fetch_and_add(&num, boost::int64_t(1));
#endif
}
private:
#ifdef _MSC_VER
volatile __declspec(align(8)) boost::int64_t num;
#else
volatile __attribute__ ((aligned (8))) boost::int64_t num;
#endif
};
}
#endif // _THREADING_H_
|