c++实现的一个邮箱,用于线程间通信
C++ implementation of a mailbox for inter-thread communication
我想知道是否有人以前使用POSIX库实现了用于线程间通信的邮箱类。作为参考,我看起来类似于SystemVerilog中使用的邮箱:http://www.asic-world.com/systemverilog/sema_mail_events2.html
编辑:
我尝试使用STL队列、pthread条件和互斥锁访问邮箱。它尝试复制链接中描述的SystemVerilog邮箱的行为:
#include <cerrno>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <fcntl.h>
#include <pthread.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;
class Mailbox{
private:
pthread_cond_t msg_available; // Message in the mailbox?
pthread_mutex_t queue_mutex; // Mutex for queue control
queue<messageT> messages; // Messages
public:
// Constructor
Mailbox(void){
msg_available = PTHREAD_COND_INITIALIZER;
queue_mutex = PTHREAD_MUTEX_INITIALIZER;
}
// Destructor
~Mailbox(void){
// Nothing to do here
}
// Put a single message into the mailbox
void put(messageT msg){
// Lock down queue
if(pthread_mutex_lock(queue_mutex)){
fprintf(stderr, "Queue Mutex Lock Errorn");
exit(EXIT_FAILURE);
}
// Push message into mailbox
messages.push(msg);
// Signal there is a message in the mailbox
if(pthread_cond_signal(&msg_available)){
fprintf(stderr, "cond error");
exit(EXIT_FAILURE);
}
// Unlock queue
if(pthread_mutex_unlock(queue_mutex)){
fprintf(stderr, "Queue Mutex Unlock Errorn");
exit(EXIT_FAILURE);
}
}
// Try to put a single message into the mailbox
int try_put(messageT msg){
// Try to lock down queue
if(pthread_mutex_trylock(queue_mutex) == 0){
// Push message into mailbox
messages.push(msg);
// Signal there is a message in the mailbox
if(pthread_cond_signal(&msg_available)){
fprintf(stderr, "cond error");
exit(EXIT_FAILURE);
}
// Unlock queue
if(pthread_mutex_unlock(queue_mutex)){
fprintf(stderr, "Queue Mutex Unlock Errorn");
exit(EXIT_FAILURE);
}
return 1;
}
// Otherwise, say mailbox is unavailable
else
return 0;
}
// Get single message from a mailbox
void get(mesageT *msg){
// Lock down queue
if(pthread_mutex_lock(queue_mutex)){
fprintf(stderr, "Queue Mutex Lock Errorn");
exit(EXIT_FAILURE);
}
// Wait for a message to come in
while(messages.empty()){
// Release hold of the lock until another thread
// signals that a message has been placed
if(pthread_cond_wait(&msg_available,&queue_mutex)){
fprintf(stderr, "cond_wait error");
exit(EXIT_FAILURE);
}
}
// Pop of least recent message
*msg = messages.front();
messages.pop();
// Unlock queue
if(pthread_mutex_unlock(queue_mutex)){
fprintf(stderr, "Queue Mutex Unlock Errorn");
exit(EXIT_FAILURE);
}
}
// Try to get single message from a mailbox
int try_get(mesageT *msg){
int mailbox_ready = 1; // Mailbox ready
// Lock down queue
if(pthread_mutex_lock(queue_mutex)){
fprintf(stderr, "Queue Mutex Lock Errorn");
exit(EXIT_FAILURE);
}
// Indicate if mailbox is empty
if(messages.empty())
mailbox_ready = 0
// Otherwise, grab the message
else {
// Pop of least recent message
*msg = messages.front();
messages.pop();
}
// Unlock queue
if(pthread_mutex_unlock(queue_mutex)){
fprintf(stderr, "Queue Mutex Unlock Errorn");
exit(EXIT_FAILURE);
}
return mailbox_ready;
}
// Peek at single message from a mailbox
void peek(mesageT *msg){
// Lock down queue
if(pthread_mutex_lock(queue_mutex)){
fprintf(stderr, "Queue Mutex Lock Errorn");
exit(EXIT_FAILURE);
}
// Wait for a message to come in
while(messages.empty()){
// Release hold of the lock until another thread
// signals that a message has been placed
if(pthread_cond_wait(&msg_available,&queue_mutex)){
fprintf(stderr, "cond_wait error");
exit(EXIT_FAILURE);
}
}
// Peek at most recent message
*msg = messages.front();
// Unlock queue
if(pthread_mutex_unlock(queue_mutex)){
fprintf(stderr, "Queue Mutex Unlock Errorn");
exit(EXIT_FAILURE);
}
}
// Try to peek at single message from a mailbox
int try_peek(mesageT *msg){
int mailbox_ready = 1; // Mailbox ready
// Lock down queue
if(pthread_mutex_lock(queue_mutex)){
fprintf(stderr, "Queue Mutex Lock Errorn");
exit(EXIT_FAILURE);
}
if(messages.empty()) // Indicate if mailbox is empty
mailbox_ready = 0
else // Otherwise, grab the message
*msg = messages.front();
// Unlock queue
if(pthread_mutex_unlock(queue_mutex)){
fprintf(stderr, "Queue Mutex Unlock Errorn");
exit(EXIT_FAILURE);
}
return mailbox_ready;
}
}
一个简单的、受信号量保护的队列就足够了。
如果你希望能够在"邮箱"中放置不同类型的数据,那么使用一个通用的基本结构,它可以很容易地扩展并包含一个单一的整数,说明它是哪种结构,然后在需要使用它时将其类型转换为正确的结构(取决于嵌入的类型)。
如果线程都在同一个进程中,你应该使用pthread_mutex
和pthread_condition_variable
, 而不是 semaphore
。Unix信号量允许进程间同步,但它们在进程内的效率较低,并且具有比互斥锁和条件变量更难推理的语义。
下面是C或c++中使用互斥体和条件变量的一些实现:
- 在c++中实现有界缓冲区是正确的吗?
- http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html c++ 11线程安全队列
相关文章:
- 用于矢量处理的多个线程
- 如何在Qt中合并/追加/添加两个用于线程的模型?
- 循环中的线程 Runnin 用于对 c++ 中的数字求和
- 用于线程间通信的 Windows 套接字
- 用于在C++中计算用户数据的线程
- QTcpSocket 或 QSslSocket 是否会自动创建用于读取/写入的线程?
- STD ::原子与静态变量用于线程同步
- COPY分配被禁用于C 11中的线程
- 多个boost io_service在单独的线程上用于多个网卡
- 来自 boost 的 udp 服务器不适用于多线程,但仅在主线程上工作
- 同步线程安全的API,用于暴露缓存数据
- C 两个线程一个用于输入,一个用于输出
- 标准::atomic_应该如何...<std::shared_ptr>用于线程安全类的复制和移动操作?
- c++线程池:std::函数的替代品,用于将函数/lambdas传递给线程
- 使用mt19937_64生成随机数,用于多线程蒙特卡罗模拟
- stl或boost中是否存在用于线程间通信的线程安全结构,其行为类似于队列
- 用于线程"Wait for Alert/Event"的标准库版本
- Pthread_create用于线程化客户端发送和接收函数
- c++实现的一个邮箱,用于线程间通信
- SetWindowsHookEx 不适用于线程 ID