环形队列

代码片段

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>

#define MAX_MSG_SIZE 256
#define QUEUE_EMPTY -1
#define QUEUE_FULL -2

// 消息结构体
typedef struct {
    long mtype;           // 消息类型,Linux 消息队列中用于区分消息
    char mtext[MAX_MSG_SIZE]; // 消息内容
} Message;

// 基于环形队列的消息队列结构体
typedef struct {
    Message *messages;    // 存储消息的环形缓冲区
    int front;            // 队头指针
    int rear;             // 队尾指针
    int capacity;         // 队列容量
    int size;             // 当前消息数量
} MessageQueue;

// 创建消息队列
MessageQueue* msg_queue_create(int capacity) {
    if (capacity <= 0) {
        fprintf(stderr, "Error: Capacity must be positive\n");
        return NULL;
    }

    MessageQueue *mq = (MessageQueue*)malloc(sizeof(MessageQueue));
    if (!mq) {
        perror("Memory allocation failed for message queue");
        return NULL;
    }

    mq->messages = (Message*)malloc(sizeof(Message) * capacity);
    if (!mq->messages) {
        perror("Memory allocation failed for messages");
        free(mq);
        return NULL;
    }

    mq->front = 0;
    mq->rear = 0;
    mq->capacity = capacity;
    mq->size = 0;

    printf("Message queue created with capacity %d\n", capacity);
    return mq;
}

// 检查消息队列是否为空
bool msg_queue_is_empty(MessageQueue *mq) {
    return mq->size == 0;
}

// 检查消息队列是否已满
bool msg_queue_is_full(MessageQueue *mq) {
    return mq->size == mq->capacity;
}

// 发送消息(入队)
int msg_send(MessageQueue *mq, long msg_type, const char *msg_text) {
    if (msg_queue_is_full(mq)) {
        printf("Message queue is full. Cannot send message.\n");
        return QUEUE_FULL;
    }

    if (strlen(msg_text) >= MAX_MSG_SIZE) {
        fprintf(stderr, "Error: Message text too long (max %d characters)\n", MAX_MSG_SIZE - 1);
        return -3;
    }

    // 构造消息
    Message msg;
    msg.mtype = msg_type;
    strncpy(msg.mtext, msg_text, MAX_MSG_SIZE - 1);
    msg.mtext[MAX_MSG_SIZE - 1] = '\0';

    // 存入环形缓冲区
    mq->messages[mq->rear] = msg;
    mq->rear = (mq->rear + 1) % mq->capacity;
    mq->size++;

    printf("Message sent: [type=%ld] %s\n", msg.mtype, msg.mtext);
    return 0;
}

// 接收消息(出队),按先进先出顺序,忽略消息类型(简化版)
int msg_receive(MessageQueue *mq, long *msg_type, char *msg_text, int max_len) {
    if (msg_queue_is_empty(mq)) {
        printf("Message queue is empty. Cannot receive message.\n");
        return QUEUE_EMPTY;
    }

    // 从队头取出消息
    Message msg = mq->messages[mq->front];
    mq->front = (mq->front + 1) % mq->capacity;
    mq->size--;

    if (msg_type) {
        *msg_type = msg.mtype;
    }

    if (msg_text) {
        strncpy(msg_text, msg.mtext, max_len - 1);
        msg_text[max_len - 1] = '\0';
    }

    printf("Message received: [type=%ld] %s\n", msg.mtype, msg.mtext);
    return 0;
}

// 获取消息队列当前消息数量
int msg_queue_size(MessageQueue *mq) {
    return mq->size;
}

// 销毁消息队列
void msg_queue_destroy(MessageQueue *mq) {
    if (mq) {
        free(mq->messages);
        free(mq);
        printf("Message queue destroyed\n");
    }
}

// 打印消息队列状态
void msg_queue_print_status(MessageQueue *mq) {
    printf("Message Queue Status: ");
    if (msg_queue_is_empty(mq)) {
        printf("Empty\n");
    } else if (msg_queue_is_full(mq)) {
        printf("Full\n");
    } else {
        printf("Partially filled\n");
    }
    printf("  Capacity: %d, Current size: %d\n", mq->capacity, mq->size);
    printf("  Front index: %d, Rear index: %d\n", mq->front, mq->rear);

    if (!msg_queue_is_empty(mq)) {
        printf("  Messages in queue (from front to rear):\n");
        int index = mq->front;
        for (int i = 0; i < mq->size; i++) {
            printf("    [%d] type=%ld, text='%s'\n",
                   i, mq->messages[index].mtype, mq->messages[index].mtext);
            index = (index + 1) % mq->capacity;
        }
    }
}

// 测试函数
int main() {
    printf("=== Message Queue Based on Circular Queue ===\n\n");

    // 1. 创建消息队列,容量为5
    MessageQueue *mq = msg_queue_create(5);
    if (!mq) {
        fprintf(stderr, "Failed to create message queue\n");
        return 1;
    }

    msg_queue_print_status(mq);
    printf("\n");

    // 2. 发送几条消息
    printf("--- Sending messages ---\n");
    msg_send(mq, 1, "Hello, this is the first message");
    msg_send(mq, 2, "Second message with higher priority");
    msg_send(mq, 1, "Another message of type 1");
    msg_send(mq, 3, "Test message number three");
    msg_send(mq, 2, "Final message before queue is full");

    msg_queue_print_status(mq);
    printf("\n");

    // 3. 尝试发送消息到已满队列
    printf("--- Attempt to send to full queue ---\n");
    int result = msg_send(mq, 4, "This should fail");
    if (result == QUEUE_FULL) {
        printf("Expected: queue is full, send failed.\n");
    }

    msg_queue_print_status(mq);
    printf("\n");

    // 4. 接收几条消息
    printf("--- Receiving messages ---\n");
    long received_type;
    char received_text[MAX_MSG_SIZE];

    for (int i = 0; i < 3; i++) {
        if (msg_receive(mq, &received_type, received_text, MAX_MSG_SIZE) == 0) {
            printf("  Received: type=%ld, text='%s'\n", received_type, received_text);
        }
    }

    msg_queue_print_status(mq);
    printf("\n");

    // 5. 再发送几条消息,测试环形特性
    printf("--- Sending more messages (testing circular behavior) ---\n");
    msg_send(mq, 4, "New message after some dequeues");
    msg_send(mq, 5, "Another new message");

    msg_queue_print_status(mq);
    printf("\n");

    // 6. 接收剩余的所有消息
    printf("--- Receiving all remaining messages ---\n");
    while (!msg_queue_is_empty(mq)) {
        msg_receive(mq, &received_type, received_text, MAX_MSG_SIZE);
    }

    msg_queue_print_status(mq);
    printf("\n");

    // 7. 尝试从空队列接收
    printf("--- Attempt to receive from empty queue ---\n");
    result = msg_receive(mq, NULL, NULL, 0);
    if (result == QUEUE_EMPTY) {
        printf("Expected: queue is empty, receive failed.\n");
    }

    // 8. 清理
    msg_queue_destroy(mq);

    return 0;
}

看法

  1. 有一点是front和rear会一直递增。

    溢出时间计算

    以32位有符号int为例:

    最大值:2,147,483,647

    假设每秒处理10,000次操作:

    达到最大值需要:2,147,483,647 / 10,000 ≈ 214,748 秒 ≈ 2,486 天 ≈ 6.8年

    对于大多数应用,在可预见的生命周期内不会溢出。

  2. 常用的数据结构之一,好用不必多言。

  3. AI生成的,理解起来很舒服,有种知识进入大脑的感觉。

posted @ 2025-12-10 16:08  杨旭0324  阅读(21)  评论(0)    收藏  举报