diff options
author | chai <chaifix@163.com> | 2018-08-07 21:53:55 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2018-08-07 21:53:55 +0800 |
commit | 926584873cd9a83458ac482c02902f4eedb1e9d3 (patch) | |
tree | 2ed019c5b8e6f391ae7a0268a200b51b7ffe293e /Thread/WindowsBased |
Diffstat (limited to 'Thread/WindowsBased')
-rw-r--r-- | Thread/WindowsBased/example/test.cpp | 11 | ||||
-rw-r--r-- | Thread/WindowsBased/thread.h | 342 |
2 files changed, 353 insertions, 0 deletions
diff --git a/Thread/WindowsBased/example/test.cpp b/Thread/WindowsBased/example/test.cpp new file mode 100644 index 0000000..b7b7279 --- /dev/null +++ b/Thread/WindowsBased/example/test.cpp @@ -0,0 +1,11 @@ +#include "../cpp-utils-master/ui/ui/ui.h" + +using namespace ui; + +int ui_main() +{ + window w(256, 256); + w << "Hello World!"; + w.waitkey(); + return 0; +} diff --git a/Thread/WindowsBased/thread.h b/Thread/WindowsBased/thread.h new file mode 100644 index 0000000..e8bb30d --- /dev/null +++ b/Thread/WindowsBased/thread.h @@ -0,0 +1,342 @@ +// mt - thread library to create C++ experiments -*- C++ -*- +// Copyright (C) 2010, 2012 David Capello +// +// Distributed under the terms of the New BSD License, +// see LICENSE.md for more details. + +#ifndef MT_THREAD_HEADER_FILE_INCLUDED +#define MT_THREAD_HEADER_FILE_INCLUDED + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 // From Windows 2000 +#endif + +#include <windows.h> + +#include <cassert> +#include <string> +#include <exception> + +namespace mt { + + ////////////////////////////////////////////////////////////////////// + // lock_guard class + + template<class Mutex> + class lock_guard { + public: + typedef Mutex mutex_type; + + explicit lock_guard(mutex_type& mutex) : m_mutex(mutex) { + m_mutex.lock(); + } + + ~lock_guard() { + m_mutex.unlock(); + } + + void lock() { + m_mutex.lock(); + } + + void unlock() { + m_mutex.unlock(); + } + + private: + mutex_type& m_mutex; + + // Non-copyable + lock_guard(const lock_guard&); + lock_guard& operator=(const lock_guard&); + }; + + ////////////////////////////////////////////////////////////////////// + // mutex class + + class mutex { + public: + mutex() { + InitializeCriticalSection(&m_cs); + } + + ~mutex() { + DeleteCriticalSection(&m_cs); + } + + void lock() { + EnterCriticalSection(&m_cs); + } + + bool try_lock() { + return TryEnterCriticalSection(&m_cs) ? true: false; + } + + void unlock() { + LeaveCriticalSection(&m_cs); + } + + private: + CRITICAL_SECTION m_cs; + + // Non-copyable + mutex(const mutex&); + mutex& operator=(const mutex&); + }; + + ////////////////////////////////////////////////////////////////////// + // condition_variable class + + class condition_variable { + public: + condition_variable() { + m_waiting_queue = + CreateSemaphore(NULL, // Security attributes + 0, // Initial count + 1000, // Maximum number of waiters (TODO) + NULL); // Unnamed semaphore + m_waiters = 0; + } + + ~condition_variable() { + // Here we could call notify_all, but, if a condition variable + // is destroyed, "there shall be no thread blocked on *this" + // (see 30.5.1 C++ working draft n3035) + assert(m_waiters == 0); + + CloseHandle(m_waiting_queue); + } + + void wait(lock_guard<mutex>& external_monitor) { + { + lock_guard<mutex> lock(m_monitor); + + assert(m_waiters >= 0); + + ++m_waiters; + external_monitor.unlock(); + } + ::WaitForSingleObject(m_waiting_queue, INFINITE); + external_monitor.lock(); + } + + void notify_one() { + lock_guard<mutex> lock(m_monitor); + + assert(m_waiters >= 0); + + // If there are one or more waiters... + if (m_waiters > 0) { + // Increment semaphore count to unlock a waiting thread + ReleaseSemaphore(m_waiting_queue, 1, NULL); + --m_waiters; + } + } + + void notify_all() { + lock_guard<mutex> lock(m_monitor); + + assert(m_waiters >= 0); + + // If there are one or more waiters... + if (m_waiters > 0) { + // Increment the semaphore to the number of waiting threads + ReleaseSemaphore(m_waiting_queue, m_waiters, NULL); + m_waiters = 0; + } + } + + private: + mutex m_monitor; // To avoid running two condition_variable member function at the same time + HANDLE m_waiting_queue; // Queue of waiting threads + LONG m_waiters; // Number of waiters in the queue + + // Non-copyable + condition_variable(const condition_variable&); + condition_variable& operator=(const condition_variable&); + }; + + ////////////////////////////////////////////////////////////////////// + // ultra-simplistic thread class implementation based on C++0x + + class thread { + public: + class details; + class id { + friend class thread; + friend class details; + + DWORD m_native_id; + id(DWORD id) : m_native_id(id) { } + public: + id() : m_native_id(0) { } + bool operator==(const id& y) const { return m_native_id == y.m_native_id; } + bool operator!=(const id& y) const { return m_native_id != y.m_native_id; } + bool operator< (const id& y) const { return m_native_id < y.m_native_id; } + bool operator<=(const id& y) const { return m_native_id <= y.m_native_id; } + bool operator> (const id& y) const { return m_native_id > y.m_native_id; } + bool operator>=(const id& y) const { return m_native_id >= y.m_native_id; } + + // TODO should we replace this with support for iostreams? + DWORD get_native_id() { return m_native_id; } + }; + + typedef HANDLE native_handle_type; + + private: + + template<class Callable> + struct f_wrapper0 { + Callable f; + f_wrapper0(const Callable& f) : f(f) { } + void operator()() { f(); } + }; + + template<class Callable, class A> + struct f_wrapper1 { + Callable f; + A a; + f_wrapper1(const Callable& f, A a) : f(f), a(a) { } + void operator()() { f(a); } + }; + + template<class Callable, class A, class B> + struct f_wrapper2 { + Callable f; + A a; + B b; + f_wrapper2(const Callable& f, A a, B b) : f(f), a(a), b(b) { } + void operator()() { f(a, b); } + }; + + template<class T> + static DWORD WINAPI thread_proxy(LPVOID data) { + T* t = (T*)data; + (*t)(); + delete t; + return 0; + } + + native_handle_type m_native_handle; + id m_id; + + public: + + // Create an instance to represent the current thread + thread() + : m_native_handle(NULL) + , m_id() { + } + + // Create a new thread without arguments + template<class Callable> + thread(const Callable& f) { + m_native_handle = + CreateThread(NULL, 0, + thread_proxy<f_wrapper0<Callable> >, + (LPVOID)new f_wrapper0<Callable>(f), + CREATE_SUSPENDED, &m_id.m_native_id); + ResumeThread(m_native_handle); + } + + // Create a new thread with one argument + template<class Callable, class A> + thread(const Callable& f, A a) { + m_native_handle = + CreateThread(NULL, 0, + thread_proxy<f_wrapper1<Callable, A> >, + (LPVOID)new f_wrapper1<Callable, A>(f, a), + CREATE_SUSPENDED, &m_id.m_native_id); + ResumeThread(m_native_handle); + } + + // Create a new thread with two arguments + template<class Callable, class A, class B> + thread(const Callable& f, A a, B b) { + m_native_handle = + CreateThread(NULL, 0, + thread_proxy<f_wrapper2<Callable, A, B> >, + (LPVOID)new f_wrapper2<Callable, A, B>(f, a, b), + CREATE_SUSPENDED, &m_id.m_native_id); + ResumeThread(m_native_handle); + } + + ~thread() { + if (joinable()) + detach(); + } + + bool joinable() const { + return + m_native_handle != NULL && + m_id.m_native_id != ::GetCurrentThreadId(); + } + + void join() { + if (joinable()) { + ::WaitForSingleObject(m_native_handle, INFINITE); + detach(); + } + } + + void detach() { + ::CloseHandle(m_native_handle); + + m_native_handle = NULL; + m_id = id(); + } + + id get_id() const { + return m_id; + } + + native_handle_type native_handle() { + return m_native_handle; + } + + class details { + public: + static id get_current_thread_id() { + return id(::GetCurrentThreadId()); + } + }; + + }; + + ////////////////////////////////////////////////////////////////////// + // this_thread namespace + + namespace this_thread { + + inline thread::id get_id() { + return thread::details::get_current_thread_id(); + } + + inline void yield() { + ::Sleep(0); + } + + // Simplified API (here we do not implement duration/time_point C++0x classes + inline void sleep_for(int milliseconds) { + ::Sleep(milliseconds); + } + + } // namespace this_thread + + ////////////////////////////////////////////////////////////////////// + // thread_guard class + + class thread_guard { + public: + explicit thread_guard(thread& t) : m_thread(t) { } + ~thread_guard() { + if (m_thread.joinable()) + m_thread.join(); + } + private: + thread& m_thread; + }; + +} // namespace mt + +#endif // MT_THREAD_HEADER_FILE_INCLUDED |