Windows和Linux下通用的线程接口
对于多线程开发,Linux下有pthread线程库,使用起来比较方便,而Windows没有,对于涉及到多线程的跨平台代码开发,会带来不便。这里参考网络上的一些文章,整理了在Windows和Linux下通用的线程接口。经过测试,在Windows和Linux下均可正常使用。
Windows和Linux下对应的线程函数列表如下:
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函数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);// 新线程创建之后主线程如何运行----主线程按顺序继续执行下一行程序std::cout << "main thread!" << std::endl;// 新线程结束时如何处理----新线程先停止,然后作为其清理过程的一部分,等待与另一个线程合并或“连接”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); //进入阻塞(wait),等待激活(signal)std::cout << "counter--(decrement, before): " << counter2 << std::endl;counter2--; //等待signal激活后再执行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)的线程(先执行完signal线程,然后再执行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); //进入阻塞(wait),等待激活(signal)std::cout << "counter--(decrement, before): " << counter3 << std::endl;counter3--; //等待signal激活后再执行 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)的线程(先执行完signal线程,然后再执行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
相关文章:

MySQL 性能调优的10个方法
MYSQL 应该是最流行了 WEB 后端数据库。WEB 开发语言最近发展很快,PHP, Ruby, Python, Java 各有特点,虽然 NOSQL 最近越來越多的被提到,但是相信大部分架构师还是会选择 MYSQL 来做数据存储。MYSQL 如此方便和稳定,以…

他们用卷积神经网络,发现了名画中隐藏的秘密
作者 | 神经小刀来源 |HyperAI超神经( ID: HyperAI)导语:著名的艺术珍品《根特祭坛画》,正在进行浩大的修复工作,以保证现在的人们能感受到这幅伟大的巨制,散发出的灿烂光芒。而随着技术的进步,…

机器学习公开课~~~~mooc
https://class.coursera.org/ntumlone-001/class/index

DLM:微信大规模分布式n-gram语言模型系统
来源 | 微信后台团队Wechat & NUS《A Distributed System for Large-scale n-gram Language Models at Tencent》分布式语言模型,支持大型n-gram LM解码的系统。本文是对原VLDB2019论文的简要翻译。摘要n-gram语言模型广泛用于语言处理,例如自动语音…
Ubuntu14.04 64位机上安装cuda8.0+cudnn5.0操作步骤
查看Ubuntu14.04 64位上显卡信息,执行:lspci | grep -i vga lspci -v -s 01:00.0 nvidia-smi第一条此命令可以显示一些显卡的相关信息;如果想查看某个详细信息,可以执行第二条命令;如果是NVIDIA卡, 可继续执行第三条命…

SQLI DUMB SERIES-5
less5 (1)输入单引号,回显错误,说明存在注入点。输入的Id被一对单引号所包围,可以闭合单引号 (2)输入正常时:?id1 说明没有显示位,因此不能使用联合查询了;可…

javascript RegExp
http://www.w3schools.com/jsref/jsref_obj_regexp.asp声明-------------modifiers:{i,g,m}1. var pattnew RegExp(pattern,modifiers);2. var patt/pattern/modifiers;------------------------例子:var str "Visit W3Schools"; //两…

Ubuntu14.04 64位机上安装OpenCV2.4.13(CUDA8.0)版操作步骤
Ubuntu14.04 64位机上安装CUDA8.0的操作步骤可以参考http://blog.csdn.net/fengbingchun/article/details/53840684,这里是在已经正确安装了CUDA8.0的基础上安装OpenCV2.4.13(CUDA8.0)操作步骤:1. 从http://opencv.org/downloads.html 下载OpenCV2.…

一篇文章能够看懂基础代码之CSS
web页面主要分为三块内容:js:控制用户行为和执行代码行为html元素:控制页面显示哪些控件(例如按钮,输入框,文本等)css:控制如何显示页面上的空间,例如布局,颜…

谷歌NIPS论文Transformer模型解读:只要Attention就够了
作者 | Sherwin Chen译者 | Major,编辑 | 夕颜出品 | AI科技大本营(ID:rgznai100)导读:在 NIPS 2017 上,谷歌的 Vaswani 等人提出了 Transformer 模型。它利用自我注意(self-attention)来计算其…

中国移动与苹果联姻 三星在华霸主地位或遭取代
据国外媒体12月24日报道,在各方的期待下,苹果终于宣布中国移动将于2014年1月17日开始销售支持其网络的iPhone手机。而中国移动也将于12 月25日开始正式接受预定。作为中国以及世界最大的移动运营商,中国移动与苹果的合作,将会帮助…
二维码Data Matrix编码、解码使用举例
二维码Data Matrix的介绍见: http://blog.csdn.net/fengbingchun/article/details/44279967 ,这里简单写了个生成二维码和对二维码进行识别的测试例子,如下:int test_data_matrix_encode() {std::string str "中国_abc_DEF…

PDF文件如何转成markdown格式
百度上根据pdf转makrdown为关键字进行搜索,结果大多数是反过来的转换,即markdown文本转PDF格式。 但是PDF转markdown的解决方案很少。 正好我工作上有这个需求,所以自己实现了一个解决方案。 下图是一个用PDF XChange Editor打开的PDF文件&am…

关于SAP BW提示“Carry out repairs in non-original only
为什么80%的码农都做不了架构师?>>> 这个提示是由于你在生产系统(正式系统)里面修改了一些东西,才提示"Carry out repairs in non-original system only if they are urgent"这个警告,理论上我们…
windows7 64位机上安装配置CUDA7.5(或8.0)+cudnn5.0操作步骤
按照官网文档 http://docs.nvidia.com/cuda/cuda-installation-guide-microsoft-windows/index.html#axzz4TpI4c8vf 进行安装:在windows7上安装cuda8.0/cuda7.5的系统需求:(1)、ACUDA-capable GPU(本机显卡为GeForce GT 640M);(2)、A support…

多重影分身:一套代码如何生成多个小程序?
前言 影分身术,看过火影的都知道,一个本体,多个分身。 大家肯定要问了,那小程序开发跟影分身术也能扯上关系?没错,那自然就是:一套代码,多个小程序啦。 各位先别翻白眼,且…

TensorFlow全家桶的落地开花 | 2019 Google开发者日
作者 | 唐小引写于上海世博中心出品 | GDD 合作伙伴 CSDN(ID:CSDNnews)Android 10 原生支持 5G,Flutter 1.9、Dart 2.5 正式发布这是 Google Developer Days 在中国的第四年,从 2016 年 Google Developers 中国网站正式…

css的background
背景属性——background是css中的核心属性。你应该对它有充分的了解。这篇文章详细讨论了background的所有相关属性,甚至包括background-p_w_upload,还为我们介绍了它在即将到来的CSS3中的样子,还有那些新加入的背景属性。使用CSS2中的背景属…
windows7 64位机上配置支持GPU版(CUDA7.5)的OpenCV2.4.13操作步骤
很久之前在windows7 32位上配置过GPU版的opencv,可参考http://blog.csdn.net/fengbingchun/article/details/9831837Windows7 64位CUDA7.5的配置可以参考:http://blog.csdn.net/fengbingchun/article/details/53892997这里是在CUDA7.5已正确安装后的操作…

值得注意的知识点
ImageView的属性adjustViewBounds www.jianshu.com/p/13de17744… 转载于:https://juejin.im/post/5c8b7742e51d454e02716e44

阿里深度序列匹配模型SDM:如何刻画大型推荐系统的用户行为?
作者 | 石晓文来源 | 小小挖掘机(ID:wAIsjwj)今天给大家介绍的论文是:《SDM: Sequential Deep Matching Model for Online Large-scale Recommender System》论文下载地址:https://arxiv.org/abs/1909.00385v11、背景像…

find ip from hostname or find hostname from ip
1. find ip from hostname ping <hostname> 2.fin hostname from ip nslookup <ip>

Linux下多线程编程中信号量介绍及简单使用
在Linux中有两种方法用于处理线程同步:信号量和互斥量。线程的信号量是一种特殊的变量,它可以被增加或减少,但对其的关键访问被保证是原子操作。如果一个程序中有多个线程试图改变一个信号量的值,系统将保证所有的操作都将依次进行…

Linux环境HBase安装配置及使用
Linux环境HBase安装配置及使用 1. 认识HBase (1) HBase介绍 HBase Hadoop database,Hadoop数据库开源数据库官网:hbase.apache.org/HBase源于Google的BigTableApache HBase™是Hadoop数据库,是一个分布式,可扩展的大数据存储。当…

适合小团队作战,奖金+招聘绿色通道,这一届算法大赛关注下?
大赛背景伴随着5G、物联网与大数据形成的后互联网格局的逐步形成,日益多样化的用户触点、庞杂的行为数据和沉重的业务体量也给我们的数据资产管理带来了不容忽视的挑战。为了建立更加精准的数据挖掘形式和更加智能的机器学习算法,对不断生成的用户行为事…

Linq 集合处理(Union)
关于Union的两种情况 一、简单值类型或者string类型处理方式(集合需要实现IEnumerable接口) #region int类型List<int> ints1 new List<int> { 1, 2, 3, 4, 5, 6 };List<int> ints2 new List<int> { 5, 6, 7, 8, 9, 0 };IEnumerable<int> ints…

卷积神经网络中十大拍案叫绝的操作
作者 | Justin ho来源 | 知乎CNN从2012年的AlexNet发展至今,科学家们发明出各种各样的CNN模型,一个比一个深,一个比一个准确,一个比一个轻量。下面会对近几年一些具有变革性的工作进行简单盘点,从这些充满革新性的工作…
windows7下解决caffe check failed registry.count(type) == 1(0 vs. 1) unknown layer type问题
在Windows7下调用vs2013生成的Caffe静态库时经常会提示Check failed: registry.count(type) 1 (0 vs. 1) Unknown layer type的错误,如下图:这里参考网上资料汇总了几种解决方法:1. 不使用Caffe的静态库,直接将Caffe的sourc…

js 变量提升 和函数提升
2019独角兽企业重金招聘Python工程师标准>>> 创建函数有两种形式,一种是函数声明,另外一种是函数字面量,只有函数声明才有变量提升 console.log(a) // f a() { console.log(a) } console.log(b) //undefinedfunction a() {consol…

.net_ckeditor+ckfinder的图片上传配置
CKEditor和CKFinder的最新版可以到官方网站(http://cksource.com)上下载获得。 把以上两个资源放到网站的根目录: /CKEditor 和 /CKFinder (不区分大小写) 在页面使用 CKEditor: <textarea cols"80" id"prcont…