C语言异步编程

        回调函数在异步编程中有着重要的作用,在接口编程应用广泛,实战中经常会注册一个回调函数来接收其他程序返回的数据,这样做的好处是调用者无需主动去获取被调用者的数据,仅仅需要回调,让被调用者去传送数据,这样就形成了回调,这是回调最常见的应用。

假设A是视频流数据,每隔一段时间会将数据传送给B,B有两种接收方式:

  1.  A将视频数据存储好,提供接口,B根据自己的需求去调用,无需考虑时间,主动权在B。
  2.  A利用回调机制,实现回调函数,当数据来临时通知B来取数据,B注册回调函数接收数据,这样主动权在A。

        很显然第一种取数据的方式,由于B不知道数据何时来临比较低效,而第二种取数据方式A通知B来取数据,效率比较高,间接的实现了中断取数。

        这里就用到了回调,B注册一个函数,将函数地址传给A,A中调用该地址获取到B注册的函数时,我们就称这个函数为回调函数。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
 
// A的实现,一般会隐藏
typedef void (*CallbackPtr)(int); //函数指针定义
 
typedef struct parameter{
    int a ;
    CallbackPtr callback;
}parameter; 
 
// 创建实例
parameter ParaData;
 
void* callback_thread(void *p1)//此处用的是一个线程
{
    //do something
    // 循环改变p->a的值为为0 2 3 4 5 6 7 8 9 ,每隔3秒改变一次
    parameter* p = (parameter*)p1 ;
    while(1)
    {
        sleep(3);//延时3秒执行callback函数
        p->callback(p->a);//函数指针执行函数,这个函数来自于应用层B
        p->a = (p->a + 1) % 10;
    }
}
 
void startup_app_A()
{
    // 初始化为0
    ParaData.a = 0;
    CallbackPtr init_call_back;
    ParaData.callback = init_call_back;
     //创建线程
    pthread_t thing1;
    pthread_create(&thing1,NULL,callback_thread,(void *) &ParaData);
}
 
// 给B的接口,接收注册函数
extern void SetCallBackFun(CallbackPtr callback)
{
    printf("SetCallBackFun print! \n");
    ParaData.callback = callback;
}
 
 
// //-----------------------应用者B-------------------------------
void fCallBack(int a)       // 应用者增加的函数,此函数会在A中被执行
{
    //do something
    printf("B得到A的数据 = %d\n",a);
}
 
 
int main(void)
{
    // 启动A
    startup_app_A();
 
    SetCallBackFun(fCallBack);
    
    // 主函数
    while (1)
    {
        // std::cout << "main function" << std::endl;
        printf("main function\n");
        sleep(2);
    }
 
    return 0;
}

运行结果:

分析结果,可以看出A提供的数据会回调B,B会每隔一定的时间收到数据,完成回调,对于一般的编程会将A的操作封装起来,只提供以下接口和函数指针类型:

typedef void (*CallbackPtr)(int);
extern void SetCallBackFun(CallbackPtr callback);

这样B可以每次注册回调函数获取A传来的数据,如下: 

void fCallBack(int a)       // 应用者增加的函数,此函数会在A中被执行
{
    //do something
    printf("B得到A的数据 = %d\n",a);
}

主函数中调用: 

SetCallBackFun(fCallBack);

这样就完成了一个C语言回调的异步编程。

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C语言中,异步FIFO模型被广泛用于数据通信和多线程编程。该模型指的是生成数据和消费数据的过程是异步进行的,数据通过一个FIFO缓冲区传输,保证数据的有序传输和实时性。 实现一个异步FIFO模型可以通过C语言的多线程编程实现。具体实现步骤如下: 1. 创建FIFO缓冲区,可以通过C语言中的队列数据结构实现。 2. 创建生成数据的线程和消费数据的线程,在两个线程中分别实现产生数据和消费数据的功能,并将两个线程和FIFO缓冲区进行绑定。 3. 然后,当数据生成线程产生数据并将数据写入缓冲区时,通知数据消费线程进行数据读取和处理;当数据处理完毕后,数据消费线程通知数据生成线程可以再次产生数据。 下面是一个简单的异步FIFO模型的C语言代码: ``` #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; int in = 0; //生产数据的索引 int out = 0; //消费数据的索引 sem_t empty; //空闲空间信号量 sem_t full; //数据占用信号量 //产生数据的线程 void *producer(void *arg) { int i; for (i = 0; i < 100; i++) { sem_wait(&empty); //等待空闲空间 buffer[in] = rand() % 1000; printf("produce data: %d\n", buffer[in]); in = (in + 1) % BUFFER_SIZE; sem_post(&full); //通知消费者数据已生成 } return NULL; } //处理数据的线程 void *consumer(void *arg) { int i, data; for (i = 0; i < 100; i++) { sem_wait(&full); //等待数据 data = buffer[out]; printf("consume data: %d\n", data); out = (out + 1) % BUFFER_SIZE; sem_post(&empty); //通知生产者有空闲空间 } return NULL; } int main() { pthread_t tid1, tid2; sem_init(&empty, 0, BUFFER_SIZE); //初始化信号量 sem_init(&full, 0, 0); pthread_create(&tid1, NULL, producer, NULL); //创建线程 pthread_create(&tid2, NULL, consumer, NULL); pthread_join(tid1, NULL); //等待线程结束 pthread_join(tid2, NULL); sem_destroy(&empty); //销毁信号量 sem_destroy(&full); return 0; } ``` 上述代码中,通过两个线程实现了数据的异步传输。生产线程不断生成数据并将其写入缓冲区,当缓冲区已满时则等待,当缓冲区有空闲时通知消费线程进行数据读取;消费线程不断从缓冲区中读取数据并进行处理,当缓冲区为空时等待,当缓冲区有数据时通知生产线程可以再次进行数据生成。通过这种方式,可以保证数据传输的顺序和实时性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会C语言的男孩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值