Windows和Linux下通用的线程接口
生活随笔
收集整理的這篇文章主要介紹了
Windows和Linux下通用的线程接口
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
對(duì)于多線程開發(fā),Linux下有pthread線程庫,使用起來比較方便,而Windows沒有,對(duì)于涉及到多線程的跨平臺(tái)代碼開發(fā),會(huì)帶來不便。這里參考網(wǎng)絡(luò)上的一些文章,整理了在Windows和Linux下通用的線程接口。經(jīng)過測試,在Windows和Linux下均可正常使用。
Windows和Linux下對(duì)應(yīng)的線程函數(shù)列表如下:
Windows和Linux線程通用接口如下:
#ifndef FBC_MESSY_TEST_THREAD_HPP_
#define FBC_MESSY_TEST_THREAD_HPP_/* reference:http://locklessinc.com/articles/pthreads_on_windows/http://locklessinc.com/downloads/winpthreads.hhttp://www.jmhartsoftware.com/Pthreads_Emulation.htmlhttps://sourceforge.net/p/log4c/log4c/ci/a4d3e19b3e55c1d5d66a5dc09a2603d9dcfcff52/tree/src/sd/sd_xplatform.hhttps://git.libav.org/?p=libav.git;a=blob;f=compat/w32pthreads.h;h=2fe2a5ab979ff676d1e7dba4a360306dde29a0f0;hb=HEADhttps://github.com/krux/zookeeper-pkg/blob/master/src/c/src/winport.chttps://my.oschina.net/mjRao/blog/359870
*/#ifdef _MSC_VER#include <windows.h>
#include <sys/timeb.h>
#include <process.h>typedef HANDLE pthread_mutex_t;
typedef int pthread_condattr_t;
typedef HANDLE pthread_t;
typedef DWORD pthread_attr_t;#define pthread_create(thrp, attr, func, arg) \(((*(thrp) = CreateThread(NULL, 0, \(LPTHREAD_START_ROUTINE)(func), (arg), 0, NULL)) == NULL) ? -1 : 0)
#define pthread_join(thr, statusp) \((WaitForSingleObject((thr), INFINITE) == WAIT_OBJECT_0) && \((statusp == NULL) ? 0 : \(GetExitCodeThread((thr), (LPDWORD)(statusp)) ? 0 : -1)))#define PTHREAD_MUTEX_INITIALIZER {(void*)-1,-1,0,0,0,0}
#define pthread_mutex_lock(pobject) WaitForSingleObject(*pobject,INFINITE)
#define pthread_mutex_unlock(pobject) ReleaseMutex(*pobject)
#define pthread_mutex_init(pobject,pattr) (*pobject=CreateMutex(NULL,FALSE,NULL))
#define pthread_mutex_destroy(pobject) CloseHandle(*pobject)/* Windows doesn't have this, so declare it ourselves. */
typedef struct timespec {/* long long in windows is the same as long in unix for 64bit */long long tv_sec;long long tv_nsec;
} timespec;typedef struct {int waiters_count_;// Number of waiting threads.CRITICAL_SECTION waiters_count_lock_;// Serialize access to <waiters_count_>.HANDLE sema_;// Semaphore used to queue up threads waiting for the condition to// become signaled. HANDLE waiters_done_;// An auto-reset event used by the broadcast/signal thread to wait// for all the waiting thread(s) to wake up and be released from the// semaphore. size_t was_broadcast_;// Keeps track of whether we were broadcasting or signaling. This// allows us to optimize the code if we're just signaling.
} pthread_cond_t;static unsigned long long _pthread_time_in_ms(void)
{struct __timeb64 tb;_ftime64(&tb);return tb.time * 1000 + tb.millitm;
}static unsigned long long _pthread_time_in_ms_from_timespec(const struct timespec *ts)
{unsigned long long t = ts->tv_sec * 1000;t += ts->tv_nsec / 1000000;return t;
}static unsigned long long _pthread_rel_time_in_ms(const struct timespec *ts)
{unsigned long long t1 = _pthread_time_in_ms_from_timespec(ts);unsigned long long t2 = _pthread_time_in_ms();/* Prevent underflow */if (t1 < t2) return 0;return t1 - t2;
}static int pthread_cond_init(pthread_cond_t *cv, const pthread_condattr_t * ignore)
{cv->waiters_count_ = 0;cv->was_broadcast_ = 0;cv->sema_ = CreateSemaphore(NULL, // no security0, // initially 00x7fffffff, // max countNULL); // unnamed if (cv->sema_ == NULL)return GetLastError();InitializeCriticalSection(&cv->waiters_count_lock_);cv->waiters_done_ = CreateEvent(NULL, // no securityFALSE, // auto-resetFALSE, // non-signaled initiallyNULL); // unnamedreturn (cv->waiters_done_ == NULL) ? GetLastError() : 0;
}static int pthread_cond_destroy(pthread_cond_t *cond)
{CloseHandle(cond->sema_);DeleteCriticalSection(&cond->waiters_count_lock_);return (CloseHandle(cond->waiters_done_) == 0) ? GetLastError() : 0;
}static int pthread_cond_signal(pthread_cond_t *cv)
{int have_waiters;EnterCriticalSection(&(cv->waiters_count_lock_));have_waiters = cv->waiters_count_ > 0;LeaveCriticalSection(&cv->waiters_count_lock_);// If there aren't any waiters, then this is a no-op. if (have_waiters){return (ReleaseSemaphore(cv->sema_, 1, 0) == 0) ? GetLastError() : 0;}elsereturn 0;
}static int pthread_cond_broadcast(pthread_cond_t *cv)
{// This is needed to ensure that <waiters_count_> and <was_broadcast_> are// consistent relative to each other.int have_waiters = 0;EnterCriticalSection(&cv->waiters_count_lock_);if (cv->waiters_count_ > 0) {// We are broadcasting, even if there is just one waiter...// Record that we are broadcasting, which helps optimize// <pthread_cond_wait> for the non-broadcast case.cv->was_broadcast_ = 1;have_waiters = 1;}if (have_waiters) {// Wake up all the waiters atomically.ReleaseSemaphore(cv->sema_, cv->waiters_count_, 0);LeaveCriticalSection(&cv->waiters_count_lock_);// Wait for all the awakened threads to acquire the counting// semaphore. WaitForSingleObject(cv->waiters_done_, INFINITE);// This assignment is okay, even without the <waiters_count_lock_> held // because no other waiter threads can wake up to access it.cv->was_broadcast_ = 0;}elseLeaveCriticalSection(&cv->waiters_count_lock_);return 0;
}static int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *external_mutex)
{int last_waiter;// Avoid race conditions.EnterCriticalSection(&cv->waiters_count_lock_);cv->waiters_count_++;LeaveCriticalSection(&cv->waiters_count_lock_);// This call atomically releases the mutex and waits on the// semaphore until <pthread_cond_signal> or <pthread_cond_broadcast>// are called by another thread.SignalObjectAndWait(*external_mutex, cv->sema_, INFINITE, FALSE);// Reacquire lock to avoid race conditions.EnterCriticalSection(&cv->waiters_count_lock_);// We're no longer waiting...cv->waiters_count_--;// Check to see if we're the last waiter after <pthread_cond_broadcast>.last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0;LeaveCriticalSection(&cv->waiters_count_lock_);// If we're the last waiter thread during this particular broadcast// then let all the other threads proceed.if (last_waiter)// This call atomically signals the <waiters_done_> event and waits until// it can acquire the <external_mutex>. This is required to ensure fairness. SignalObjectAndWait(cv->waiters_done_, *external_mutex, INFINITE, FALSE);else// Always regain the external mutex since that's the guarantee we// give to our callers. WaitForSingleObject(*external_mutex, INFINITE);return 0;
}#else // linux#include <pthread.h>#endif // _MSC_VER#endif // FBC_MESSY_TEST_THREAD_HPP_
測試代碼如下:
#include "test_thread.hpp"
#include <iostream>
#include "thread.hpp"// test code reference: http://blog.csdn.net/fengbingchun/article/details/48579725void* run1(void* para)
{std::cout << "start new thread!" << std::endl;//sleep(5);//suspend 5 s,在正式的代碼中,一般不要用sleep函數(shù)int* iptr = (int*)((void**)para)[0];float* fptr = (float*)((void**)para)[1];char* str = (char*)((void**)para)[2];std::cout << *iptr << " " << *fptr << " " << str << std::endl;std::cout << "end new thread!" << std::endl;return ((void *)0);
}int test_create_thread()
{pthread_t pid;//thread handleint ival = 1;float fval = 10.0f;char buf[] = "func";void* para[3] = { &ival, &fval, buf };pthread_create(&pid, NULL, run1, para);// 新線程創(chuàng)建之后主線程如何運(yùn)行----主線程按順序繼續(xù)執(zhí)行下一行程序std::cout << "main thread!" << std::endl;// 新線程結(jié)束時(shí)如何處理----新線程先停止,然后作為其清理過程的一部分,等待與另一個(gè)線程合并或“連接”pthread_join(pid, NULL);return 0;
}/
pthread_t tid[2];
int counter = 0;
pthread_mutex_t lock;void* run2(void* arg)
{pthread_mutex_lock(&lock);unsigned long i = 0;counter += 1;std::cout << "Job " << counter << " started!" << std::endl;for (i = 0; i<(0xFFFFFFFF); i++);std::cout << "Job " << counter << " finished!" << std::endl;pthread_mutex_unlock(&lock);return NULL;
}int test_thread_mutex()
{int i = 0, err = -1;pthread_mutex_init(&lock, NULL);while (i < 2) {pthread_create(&(tid[i]), NULL, &run2, NULL);i++;}pthread_join(tid[0], NULL);pthread_join(tid[1], NULL);pthread_mutex_destroy(&lock);return 0;
}/
pthread_mutex_t count_lock1;
pthread_cond_t count_nonzero1;
unsigned count1 = 0;void* decrement_count1(void* arg)
{pthread_mutex_lock(&count_lock1);std::cout << "decrement_count get count_lock" << std::endl;while (count1 == 0) {std::cout << "decrement_count count == 0" << std::endl;std::cout << "decrement_count before cond_wait" << std::endl;pthread_cond_wait(&count_nonzero1, &count_lock1);std::cout << "decrement_count after cond_wait" << std::endl;}count1 = count1 + 1;pthread_mutex_unlock(&count_lock1);return NULL;
}void* increment_count1(void* arg)
{pthread_mutex_lock(&count_lock1);std::cout << "increment_count get count_lock" << std::endl;if (count1 == 0) {std::cout << "increment_count before cond_signal" << std::endl;pthread_cond_signal(&count_nonzero1);std::cout << "increment_count after cond_signal" << std::endl;}count1 = count1 + 1;pthread_mutex_unlock(&count_lock1);return NULL;
}int test_thread_cond1()
{pthread_t tid1, tid2;pthread_mutex_init(&count_lock1, NULL);pthread_cond_init(&count_nonzero1, NULL);pthread_create(&tid1, NULL, decrement_count1, NULL);Sleep(2000); // == linux sleep(2)pthread_create(&tid2, NULL, increment_count1, NULL);Sleep(2000);pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_mutex_destroy(&count_lock1);pthread_cond_destroy(&count_nonzero1);return 0;
}pthread_mutex_t counter_lock2;
pthread_cond_t counter_nonzero2;
int counter2 = 0;void* decrement_counter2(void* argv)
{std::cout << "counter(decrement): " << counter2 << std::endl;pthread_mutex_lock(&counter_lock2);while (counter2 == 0)pthread_cond_wait(&counter_nonzero2, &counter_lock2); //進(jìn)入阻塞(wait),等待激活(signal)std::cout << "counter--(decrement, before): " << counter2 << std::endl;counter2--; //等待signal激活后再執(zhí)行std::cout << "counter--(decrement, after): " << counter2 << std::endl;pthread_mutex_unlock(&counter_lock2);return NULL;
}void* increment_counter2(void* argv)
{std::cout << "counter(increment): " << counter2 << std::endl;pthread_mutex_lock(&counter_lock2);if (counter2 == 0)pthread_cond_signal(&counter_nonzero2); //激活(signal)阻塞(wait)的線程(先執(zhí)行完signal線程,然后再執(zhí)行wait線程) std::cout << "counter++(increment, before): " << counter2 << std::endl;counter2++;std::cout << "counter++(increment, after): " << counter2 << std::endl;pthread_mutex_unlock(&counter_lock2);return NULL;
}int test_thread_cond2()
{std::cout << "counter: " << counter2 << std::endl;pthread_mutex_init(&counter_lock2, NULL);pthread_cond_init(&counter_nonzero2, NULL);pthread_t thd1, thd2;pthread_create(&thd1, NULL, decrement_counter2, NULL);pthread_create(&thd2, NULL, increment_counter2, NULL);int counter2 = 0;while (counter2 != 10) {std::cout << "counter(main): " << counter2 << std::endl;Sleep(1);counter2++;}pthread_join(thd1, NULL);pthread_join(thd2, NULL);pthread_mutex_destroy(&counter_lock2);pthread_cond_destroy(&counter_nonzero2);return 0;
}///
pthread_mutex_t counter_lock3_1, counter_lock3_2;
pthread_cond_t counter_nonzero3_1, counter_nonzero3_2;
int counter3 = 0;void* decrement_increment_counter3(void* argv)
{std::cout << "start counter: " << counter3 << std::endl;pthread_mutex_lock(&counter_lock3_1);std::cout << "counter(decrement): " << counter3 << std::endl;while (counter3 == 1)pthread_cond_wait(&counter_nonzero3_1, &counter_lock3_1); //進(jìn)入阻塞(wait),等待激活(signal)std::cout << "counter--(decrement, before): " << counter3 << std::endl;counter3--; //等待signal激活后再執(zhí)行 std::cout << "counter--(decrement, after): " << counter3 << std::endl;pthread_mutex_unlock(&counter_lock3_1);pthread_mutex_lock(&counter_lock3_2);std::cout << "counter(increment): " << counter3 << std::endl;if (counter3 == 0)pthread_cond_signal(&counter_nonzero3_2); //激活(signal)阻塞(wait)的線程(先執(zhí)行完signal線程,然后再執(zhí)行wait線程) std::cout << "counter++(increment, before): " << counter3 << std::endl;counter3++;std::cout << "counter++(increment, after): " << counter3 << std::endl;pthread_mutex_unlock(&counter_lock3_2);return NULL;
}int test_thread_cond3()
{std::cout << "counter: " << counter3 << std::endl;pthread_mutex_init(&counter_lock3_1, NULL);pthread_mutex_init(&counter_lock3_2, NULL);pthread_cond_init(&counter_nonzero3_1, NULL);pthread_cond_init(&counter_nonzero3_2, NULL);pthread_t thd;pthread_create(&thd, NULL, decrement_increment_counter3, NULL);counter3 = 0;while (counter3 != 10) {std::cout << "counter(main): " << counter3 << std::endl;Sleep(1000);counter3++;}pthread_join(thd, NULL);pthread_mutex_destroy(&counter_lock3_1);pthread_mutex_destroy(&counter_lock3_2);pthread_cond_destroy(&counter_nonzero3_1);pthread_cond_destroy(&counter_nonzero3_2);return 0;
}
GitHub: https://github.com/fengbingchun/Messy_Test
總結(jié)
以上是生活随笔為你收集整理的Windows和Linux下通用的线程接口的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Dlib库中实现正脸人脸关键点(land
- 下一篇: Ubuntu14.04 64位机上安装c