13 linux windows multithreading pthreads
如果设置或取消设置事件,是否有更简单的解决方案将窗口手动重置事件移植到pthread,而不是pthread条件变量+ pthread互斥+标记?
eph*_*ent 18
Pthreads是低级构造.不,没有一个更简单的机制; 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);
}
Run Code Online (Sandbox Code Playgroud)
这可能不适合您的使用,因为您通常会使用不同的锁来代替ev->mutex
,但这是它通常使用的方法的要点.
小智 7
您可以使用管道轻松实现手动重置事件:
事件处于触发状态 - >有一些东西要从管道中读取
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));
Run Code Online (Sandbox Code Playgroud)
请注意,等待事件不会从管道中读取,因此"事件"将保持在触发状态,直到重置操作.
小智 5
我更喜欢管道方法,因为通常不需要等待的事件,而是多个对象,例如WaitForMultipleObjects(...)
.并使用管道一个可以很容易地更换窗户WaitForMultipleObjects
调用与poll(...)
,select
,pselect
,和epoll
.
有一种称为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], &buf, 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]);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
15459 次 |
最近记录: |