用 C 实现一个简化版 MessageQueue

Android 的 MessageQueue 很复杂(native poll/epoll、barrier、idle handler...)

但它的核心思想非常简单

✅ 一个队列存消息

✅ 一个循环不断取消息执行

✅ 线程安全(加锁/条件变量)

我们用 C 写一个可跑的简化版

  • 支持 post(msg)

  • 支持 loop() 阻塞取消息

  • 支持 quit() 退出

1)数据结构:消息节点 + 队列

cpp 复制代码
typedef struct Message {
    int what;
    void (*callback)(int what); // 收到消息后执行的回调
    struct Message* next;
} Message;

typedef struct {
    Message* head;
    Message* tail;
    int quit;
    pthread_mutex_t mutex;
    pthread_cond_t  cond;
} MessageQueue;

2)队列初始化 / 销毁

cpp 复制代码
void mq_init(MessageQueue* q){
    q->head = q->tail = NULL;
    q->quit = 0;
    pthread_mutex_init(&q->mutex, NULL);
    pthread_cond_init(&q->cond, NULL);
}

void mq_destroy(MessageQueue* q){
    pthread_mutex_lock(&q->mutex);
    Message* cur = q->head;
    while(cur){
        Message* next = cur->next;
        free(cur);
        cur = next;
    }
    q->head = q->tail = NULL;
    pthread_mutex_unlock(&q->mutex);

    pthread_mutex_destroy(&q->mutex);
    pthread_cond_destroy(&q->cond);
}

3)post:入队 + 唤醒 loop

cpp 复制代码
void mq_post(MessageQueue* q, int what, void (*cb)(int)){
    Message* m = (Message*)malloc(sizeof(Message));
    m->what = what;
    m->callback = cb;
    m->next = NULL;

    pthread_mutex_lock(&q->mutex);

    if(q->tail == NULL){
        q->head = q->tail = m;
    }else{
        q->tail->next = m;
        q->tail = m;
    }

    pthread_cond_signal(&q->cond); // 通知消费者
    pthread_mutex_unlock(&q->mutex);
}

4)next:阻塞取消息(队列空就等)

cpp 复制代码
Message* mq_next(MessageQueue* q){
    pthread_mutex_lock(&q->mutex);

    while(!q->quit && q->head == NULL){
        pthread_cond_wait(&q->cond, &q->mutex);
    }

    if(q->quit){
        pthread_mutex_unlock(&q->mutex);
        return NULL;
    }

    Message* m = q->head;
    q->head = m->next;
    if(q->head == NULL) q->tail = NULL;

    pthread_mutex_unlock(&q->mutex);
    return m;
}

5)loop:像 Looper 一样执行消息

cpp 复制代码
void mq_loop(MessageQueue* q){
    while(1){
        Message* m = mq_next(q);
        if(m == NULL) break;

        if(m->callback){
            m->callback(m->what);
        }
        free(m);
    }
}

6)quit:让 loop 退出

cpp 复制代码
void mq_quit(MessageQueue* q){
    pthread_mutex_lock(&q->mutex);
    q->quit = 1;
    pthread_cond_broadcast(&q->cond);
    pthread_mutex_unlock(&q->mutex);
}

7)完整可运行 Demo(Linux / macOS)

编译:gcc mq.c -o mq -lpthread

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

typedef struct Message {
    int what;
    void (*callback)(int what);
    struct Message* next;
} Message;

typedef struct {
    Message* head;
    Message* tail;
    int quit;
    pthread_mutex_t mutex;
    pthread_cond_t  cond;
} MessageQueue;

void mq_init(MessageQueue* q){
    q->head = q->tail = NULL;
    q->quit = 0;
    pthread_mutex_init(&q->mutex, NULL);
    pthread_cond_init(&q->cond, NULL);
}

void mq_post(MessageQueue* q, int what, void (*cb)(int)){
    Message* m = (Message*)malloc(sizeof(Message));
    m->what = what;
    m->callback = cb;
    m->next = NULL;

    pthread_mutex_lock(&q->mutex);
    if(q->tail == NULL){
        q->head = q->tail = m;
    }else{
        q->tail->next = m;
        q->tail = m;
    }
    pthread_cond_signal(&q->cond);
    pthread_mutex_unlock(&q->mutex);
}

Message* mq_next(MessageQueue* q){
    pthread_mutex_lock(&q->mutex);
    while(!q->quit && q->head == NULL){
        pthread_cond_wait(&q->cond, &q->mutex);
    }
    if(q->quit){
        pthread_mutex_unlock(&q->mutex);
        return NULL;
    }
    Message* m = q->head;
    q->head = m->next;
    if(q->head == NULL) q->tail = NULL;
    pthread_mutex_unlock(&q->mutex);
    return m;
}

void mq_quit(MessageQueue* q){
    pthread_mutex_lock(&q->mutex);
    q->quit = 1;
    pthread_cond_broadcast(&q->cond);
    pthread_mutex_unlock(&q->mutex);
}

void mq_loop(MessageQueue* q){
    while(1){
        Message* m = mq_next(q);
        if(m == NULL) break;
        if(m->callback) m->callback(m->what);
        free(m);
    }
}

void mq_destroy(MessageQueue* q){
    pthread_mutex_lock(&q->mutex);
    Message* cur = q->head;
    while(cur){
        Message* next = cur->next;
        free(cur);
        cur = next;
    }
    q->head = q->tail = NULL;
    pthread_mutex_unlock(&q->mutex);

    pthread_mutex_destroy(&q->mutex);
    pthread_cond_destroy(&q->cond);
}

void on_msg(int what){
    printf("handle msg what=%d (thread=%lu)\n", what, (unsigned long)pthread_self());
}

typedef struct {
    MessageQueue* q;
} ProducerArg;

void* producer(void* arg){
    ProducerArg* pa = (ProducerArg*)arg;
    for(int i=1;i<=5;i++){
        mq_post(pa->q, i, on_msg);
        usleep(200 * 1000);
    }
    mq_quit(pa->q);
    return NULL;
}

int main(){
    MessageQueue q;
    mq_init(&q);

    pthread_t t;
    ProducerArg pa = { .q = &q };
    pthread_create(&t, NULL, producer, &pa);

    mq_loop(&q);

    pthread_join(t, NULL);
    mq_destroy(&q);
    return 0;
}

8)这跟 Android MessageQueue 的对应关系

  • mq_postenqueueMessage
  • mq_nextnext()
  • mq_loopLooper.loop()
  • cond_wait ≈ "没有消息就阻塞等待"
  • quitLooper.quit()
相关推荐
喜欢喝果茶.11 小时前
QOverload<参数列表>::of(&函数名)信号槽
开发语言·qt
亓才孓11 小时前
[Class类的应用]反射的理解
开发语言·python
努力学编程呀(๑•ี_เ•ี๑)11 小时前
【在 IntelliJ IDEA 中切换项目 JDK 版本】
java·开发语言·intellij-idea
坚果派·白晓明11 小时前
在鸿蒙设备上快速验证由lycium工具快速交叉编译的C/C++三方库
c语言·c++·harmonyos·鸿蒙·编程语言·openharmony·三方库
island131411 小时前
CANN GE(图引擎)深度解析:计算图优化管线、内存静态规划与异构任务的 Stream 调度机制
开发语言·人工智能·深度学习·神经网络
坚持就完事了11 小时前
Java中的集合
java·开发语言
魔芋红茶11 小时前
Python 项目版本控制
开发语言·python
云小逸11 小时前
【nmap源码解析】Nmap OS识别核心模块深度解析:osscan2.cc源码剖析(1)
开发语言·网络·学习·nmap
冰暮流星11 小时前
javascript之二重循环练习
开发语言·javascript·数据库
风指引着方向11 小时前
自定义算子开发入门:基于 CANN op-plugin 的扩展实践
开发语言