有没有更容易的解决scheme移植到pthread一个Windows手动重置事件,比pthread条件variables+ pthread互斥+标志如果事件设置或取消设置?
.NET或Windows同步基元性能规范
都调用`fprintf(stdout,…)`和`fprintf(stderr,…)`保证与multithreading不交错?
QT在窗口线程中发出信号
线程sorting服务的scheme
在同一进程中创build的所有其他线程之后停止线程
线程是低层次的结构。 不,没有简单的机制; pthread_cond__*在概念上类似于自动重置事件。 要小心, pthread_cond_wait可能有虚假的唤醒,所以不应该在没有某种外部标志的情况下使用,无论情况如何。
但是,建立你自己并不会太难。
#include <pthread.h> #include <stdbool.h> struct mrevent { pthread_mutex_t mutex; pthread_cond_t cond; bool triggered; }; void mrevent_init(struct mrevent *ev) { pthread_mutex_init(&ev->mutex,0); pthread_cond_init(&ev->cond,0); ev->triggered = false; } void mrevent_trigger(struct mrevent *ev) { pthread_mutex_lock(&ev->mutex); ev->triggered = true; pthread_cond_signal(&ev->cond); pthread_mutex_unlock(&ev->mutex); } void mrevent_reset(struct mrevent *ev) { pthread_mutex_lock(&ev->mutex); ev->triggered = false; pthread_mutex_unlock(&ev->mutex); } void mrevent_wait(struct mrevent *ev) { pthread_mutex_lock(&ev->mutex); while (!ev->triggered) pthread_cond_wait(&ev->cond,&ev->mutex); pthread_mutex_unlock(&ev->mutex); }
这可能不适合你的使用,因为你通常会有一个不同的锁来代替ev->mutex ,但这是它通常使用的要点。
您可以使用管道轻松实现手动重置事件:
事件处于触发状态 – >需要从管道读取数据
SetEvent – > write()
ResetEvent – > read()
WaitForMultipleObjects – > poll()(或select())来读取
为了使管道处于非空状态,“SetEvent”操作应该写一些东西(例如任何值的1个字节),所以后面的“等待”操作,即poll()可用于读取的数据不会被阻塞。
“ResetEvent”操作将读取写入的数据以确保管道再次为空。 管道的读端应该是非阻塞的,所以试图重置(读取)已经重置的事件(空管道)将不会阻塞 – fcntl(pipe_out,F_SETFL,O_NONBLOCK)由于可能有超过1个SetEvents ResetEvent,你应该编码它,以便它读取管道中的字节数:
char buf[256]; // 256 is arbitrary while( read(pipe_out,buf,sizeof(buf)) == sizeof(buf));
请注意,等待事件不会从管道中读取,因此“事件”将保持触发状态,直到复位操作。
void LinuxEvent::wait() { pthread_mutex_lock(&mutex); int signalValue = signalCounter; while (!signaled && signalValue == signalCounter) { pthread_cond_wait(&condition,&mutex); } pthread_mutex_unlock(&mutex); } void LinuxEvent::signal() { pthread_mutex_lock(&mutex); signaled = true; signalCounter++; pthread_cond_broadcast(&condition); pthread_mutex_unlock(&mutex); } void LinuxEvent::reset() { pthread_mutex_lock(&mutex); signaled = false; pthread_mutex_unlock(&mutex); }
当调用signal()时,事件进入信号状态,所有等待的线程都会运行。 然后事件将保持信号状态,所有的线程调用wait()都不会等待。 reset()的调用将使事件回到无信号状态。
signalCounter是在那里你快速的信号/复位来唤醒等待线程。
我更喜欢管道方式,因为通常不需要等待一个事件,而是多个对象,例如WaitForMultipleObjects(...) 。 而使用管道可以很容易地用poll(...) , select , pselect和epoll来代替windows的WaitForMultipleObjects调用。
有一个称为Futex (快速用户空间锁定系统调用)的Futex进程同步方法。 有一个函数futex_fd为futexes获取一个或多个文件描述符。 这个文件描述符,连同可能的许多代表真实文件,设备,套接字等的其他文件可以传递给select , poll或epoll 。 不幸的是,它被从内核中删除 。 所以管道技巧仍然是唯一的设施:
int pipefd[2]; char buf[256]; // 256 is arbitrary int r = pipe2(pipefd,O_NONBLOCK); void setEvent() { write(pipefd[1],&buf,1); } void resetEvent() { while( read(pipefd[0],sizeof(buf)) > 0 ) {;} } void waitForEvent(int timeoutMS) { struct pollfd fds[1]; fds[0].fd = pipefd[0]; fds[0].events = POLLRDnorM; poll(fds,1,timeoutMS); } // finalize: close(pipefd[0]); close(pipefd[1]);
我认为Windows事件更类似于信号量。 即自动重置,你会使用二进制信号和sem_timedwait()函数。
我们正在寻找一种类似的解决方案,将一些大量多线程的C ++代码从Windows移植到Linux,最后编写了一个开源的,MIT授权的Linux库Win32事件 。 它应该是您正在寻找的解决方案,并且经过严格的性能和资源消耗审查。
它实现了手动和自动重置事件,以及WaitForSingleObject和WaitForMultipleObject功能。
我们(全面披露:我在NeoSmart Technologies工作)编写了一个名为pevents的开源(MIT许可)库,它在POSIX上实现了WIN32手动和自动重置事件 ,并包含WaitForSingleObject和WaitForMultipleObjects克隆。 从那以后,它就被采用了(它在Linux / Mac上的Steam中使用)并且工作得很好。
虽然我个人建议你在POSIX机器上编码时使用POSIX多线程和信号范例,但是如果你需要的话,pevents可以给你另一个选择。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。