本文介绍Sofia的同步与多线程接口。

Sofia工具库提供了简单的,不依赖操作系统的同步接口。同步接口包含用于管理 事件、消息、时间和多线程的原语。

克隆对象

通过克隆,可以把进程分为多个任务。

几个任务可以运行在一个线程的上下文中,也可以每个任务运行自己的线程。但是,只有一个任务中的代码,只能由一个线程执行。线程与任务间的关系是1对N的。软件中的多任务,既可以由多线程环境中的多个线程执行;也可以由单线程环境中的单一线程执行。

克隆有利于使用独立线程处理多任务又不造成过多阻塞。当多线程不可用或不需要时,也可以在单线程模式下运行克隆。在单线程模式下进行debug调试是特别有帮助的。

通过 su_clone_start()函数任务创建克隆。每次克隆都有它的根对象(su_root_t),它持有一个上下文指针(su_root_magic_t *)。上下文对象可以不同于父任务的对象。

当任务克隆开始时,调用克隆初始化函数。初始化函数执行所有需要初始化的东西,注册IO事件和定时器,然后返回。如果初始化成功,克隆任务返回运行事件循环并调用事件回调函数,直到其父任务调用 su_clone_wait()才停止,它还会调用清理函数。克隆任务在清理函数返回时被销毁。

公共API包含以下函数:

  • su_clone_start()
  • su_clone_task()
  • su_clone_wait()
  • su_clone_forget()

注意:

每个线程只有一个事件循环,它可以共享给多个克隆任务。因此,克隆任务不能显式运行或设置事件循环,它们仅限于事件回调。克隆任务不能调用su_root_break()、su_root_run() 或 su_root_step()这些函数。

任务与根(root)对象

在Sofia的事件驱动编程模型中,任务是基本的执行单元。

根据模型,程序可以要求事件循环在某个特定事件触发时调用回调函数。这类事件包括:I/O活动、定时器,或其它任务的消息。事件循环通过su_root_run() 或 su_root_step()函数执行。

Root 对象可以访问任务控件。root对象代理在任务中执行的任务代码。通过root,任务代码可以访问它的context对象和线程同步功能,比如说等待对象、定时器,还有消息。

在任务之间发消息时,使用任务引用 su_task_r 描述任务的地址。引用计数器可以保证任务引用的有效性。

公用API包含以下函数:

  • su_root_create() [不要在克隆任务中调用]
  • su_root_destroy()  [不要在克隆任务中调用]
  • su_root_magic()
  • su_root_register()
  • su_root_deregister()
  • su_root_unregister()
  • su_root_threading()
  • su_root_run() [不要在克隆任务中调用]
  • su_root_break() [不要在克隆任务中调用]
  • su_root_step() [不要在克隆任务中调用]
  • su_root_get_max_defer()
  • su_root_set_max_defer()
  • su_root_task()

通过su_clone_start() 函数可以创建新的任务。

注册等待对象

当应用程序希望捕获I/O事件时,它可以使用 su_root_register() 函数创建并注册一个等待对象,这时需要一个回调函数指针和一个指向su_root_t 对象的context指针。当等待对象收到相应事件时,会调用注册的回调函数。

注册成功时, su_root_register()返回一个非负小整数描述注册本身。可以通过su_root_eventmask()函数操作注册,例如:通过socket发送数据时,应用程序可以向掩码是添加SU_WAIT_OUT事件。

可以使用 su_root_deregister() 函数删除之前的注册信息。

定时器对象

用定显示器安排在特定时间或间隔多少时间后执行给定任务。

The default interval is specified when the timer is created. We call timer activation "setting the timer", and deactivation "resetting the timer" (as in SDL). When the given time has arrived or the default interval has elapsed, the timer expires and it is ready for execution.

创建定时器时指定默认时间间隔。 我们把定时器激活称为“设置计时器”,把取消激活称为“重置定时器”(如SDL)。 当给定时间到达或默认间隔过去时,定时器到期触发,执行给定任务。

以下是用于创建、销毁、激活,管理定时器的相关函数:

  • su_timer_create(),
  • su_timer_destroy(),
  • su_timer_set_interval(),
  • su_timer_set_at(),
  • su_timer_set(),
  • su_timer_set_for_ever(),
  • su_timer_run(),
  • su_timer_reset(), and
  • su_timer_root().

注意:

定时器使用poll()唤醒等待线程。在Linux环境下,定时器的精度是由HZ内核参数决定的,它取决于内核编译时的参数设定。内核2.4版本中,默认精度是10毫秒,定时器的最小持续时间间隔是20毫秒。当然,使用RTC可以获得更高的精度,但使用64Hz以上的RTC是一种特权操作。

在Windows环境中,定时器的精度取决于实时时钟定时器。默认条件下,它使用18.78 Hz的精度。使用Windows多媒体库时,时钟精度可以调整为1000 Hz。

使用定时器

调用su_timer_create()函数创建一个定时器:

   timer = su_timer_create(su_root_task(root), 200);

时间间隔的单件是毫秒。

通常,应该定期调用定时器的唤醒函数。这时,使用su_timer_set_for_ever()函数激活定时器。当定时器被激活时,它被赋予了唤醒函数和指向上下文数据的指针:

   su_timer_set_for_ever(timer, timer_wakeup, args);

当指定的时间间隔过去时,root事件循环调用唤醒函数:

   timer_wakeup(root, timer, args);

如果调用回调函数的次数很重要,请使用su_timer_run()。run timer会尝试补偿错过的时间,并在需要时多次调用回调函数。(因为可以调整实时时钟,或者把程序挂起,比如说在调试时,可以连续调用数千次回调函数。)请注意,虽然定时器尝试补偿回调之前和期间发生的延迟,但它不能用作计时信息的确切来源

调用su_timer_reset() ,定时器停止运行。

或者,可以将定时器设置为一次事件调用。设置定时器时,它绑定唤醒函数和上下文相关数据。也可以使用using su_timer_set_at()指定实际持续时间。

 su_timer_set(timer, timer_wakeup, args);

定时器超时触发时,root事件循环会调用唤醒函数:

   timer_wakeup(root, timer, args);

如果不再需要定时器事件,可以重置定时器:

   su_timer_reset(timer);

如果希望定期调用定时器,可以通过su_timer_run()设置ro为持续运行。当持续运行的定时器激活时,不能调用 su_timer_set() 或 su_timer_set_at()进行设置。

如果不再需要定时器,应当销毁定时器对象本身:

   su_timer_destroy(timer);

等待对象

可以使用等待对象信进程发送I/O事件信号。

以下是事件类型:

  • SU_WAIT_IN - 输入数据在socket上可用
  • SU_WAIT_OUT - 数据可以通过socket发送
  • SU_WAIT_ERR - socket错误
  • SU_WAIT_HUP - socket连接关闭
  • SU_WAIT_ACCEPT - 监听中的socket接受一个新的连接尝试

可以通过管道符|,二进制数或操作符将几个事件组合。

可以通过以下几个函数管理等待对象:

  • su_wait_create()
  • su_wait_destroy()
  • su_wait()
  • su_wait_events()
  • su_wait_mask()

注意:

在Unix平台下,,等待对象是个poll结构体。它包含一个文件描述符,一个描述预期事件的掩码,还有一个容纳su_wait()调用之后发生事件的掩码,比如说poll()。

Windows平台下,等待对象是一个HANDLE (Windows 内核实体的描述符)。


变量文档

int su_root_size_hint

包含su_root_t所支持的socket的数量的提示。

提示在su_root是已注册的fd的数量。

Sofia的同步与多线程相关推荐

  1. java多线程采集+线程同步-【多线程数据采集之四】

    前些日子讲解了java数据抓取, 今天就讲解最核心的. java多线程数据抓取. java多线程采集+数据同步+线程同步[多线程数据采集之四] 主要讲解多线程抓取,多线程同步,多线程启动,控制等操作. ...

  2. Linux C :线程操作和线程同步的多线程并发编程

    在这之前可以先看看这边文章了解线程概念,信号量,条件变量,死锁.管程等概念 https://blog.csdn.net/superSmart_Dong/article/details/11666837 ...

  3. 细说C#多线程那些事 - 线程同步和多线程优先级

    上个文章分享了一些多线程的一些基础的知识,今天我们继续学习. 一.Task类 上次我们说了线程池,线程池的QueueUserWorkItem()方法发起一次异步的线程执行很简单 但是该方法最大的问题是 ...

  4. java 什么是线程同步,java多线程同步集合是什么?并发集合是什么?

    java中关于集合的内容也是十分丰富的,而且相关的知识点也是十分多的.多线程集合所涵盖的范围是十分广阔的.今天就来为大家介绍一下,java多线程同步集合是什么以及并发集合是什么?一起来看看吧. 首先我 ...

  5. java 集合读写同步_JAVA多线程学习十六 - 同步集合类的应用

    1.引言 在多线程的环境中,如果想要使用容器类,就需要注意所使用的容器类是否是线程安全的.在最早开始,人们一般都在使用同步容器(Vector,HashTable),其基本的原理,就是针对容器的每一个操 ...

  6. 同步异步多线程这三者关系,你能给面试官一个满意的回答吗?

    前几天一位朋友去面试,面试官问了他同步,异步,多线程之间是什么关系,异步比同步高效在哪?多线程比单线程高效在哪?由于回答的不好,让我帮他捋一下,其实回答这个问题不难,难就难在只对别人说理论,而没有现杀 ...

  7. linux线程同步教程,多线程同步

    1.linux使用多线程同步的方法 1)互斥锁:当线程A锁定了互斥变量时,线程B再去锁定时就会被挂起,直到A解锁. 注意:当线程要不断的去轮询检查某个条件以判断是否可以操作需同步的数据时,可使用条件变 ...

  8. java 高效的多线程同步_java多线程的同步和异步

    java多线程的同步和异步 Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言.Java 技术具有卓越的通用性.高效性.平台移植性和安全性,广泛应用于PC.数据中心.游戏控制台.科学超级计算 ...

  9. java线程同步barrier_Java多线程同步工具类之CyclicBarrier

    一.CyclicBarrier使用 CyclicBarrier从字面上可以直接理解为线程运行的屏障,它可以让一组线程执行到一个共同的屏障点时被阻塞,直到最后一个线程执行到指定位置,你设置的执行线程就会 ...

最新文章

  1. 如何解决 未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0” 提供程序
  2. C#实现发送手机短信
  3. mysql connector net 6.9.3_MySQL Connector/Net 6.9.3 发布 MySQL Connector/Net 6.9.3下载
  4. vscode怎么安装python包_vscode如何安装python
  5. ERROR: Cannot uninstall ‘PyYAML‘. 安装 fvcore
  6. api idea 开发rest_部分介绍使用IDEA的rest client
  7. ECMAscript6入门(1)
  8. PM3嗅探数据采集密码自动提取密码工具
  9. 《Blood Vessel Segmentation in Fundus Images Based on Improved Loss Function》
  10. 在c的基础上关于c#入门的一些个人理解
  11. 2021-2025年中国拜勒病治疗行业市场供需与战略研究报告
  12. GIC 介绍 (二)—gic400 使用
  13. 利用云服务器搭建hadoop集群
  14. 银行储蓄管理系统 课程设计
  15. python 自动化测试基础
  16. OpenGL(十三) 天空盒 的 shader 实现
  17. Debug-PC之开山老祖[转]
  18. 最新、最全和最广泛的人类心脏细胞图谱
  19. 非线性振动 matlab,基于MATLAB的车削细长轴过程非线性振动分析.pdf
  20. 什么是项目管理(PJM)/ 产品导向的团队里PjM如何发展?

热门文章

  1. Math-Model(三)高斯羽烟模型计算气体扩散浓度
  2. 互联网开发模式:持续集成
  3. JavaScript基础教程(正在更新)
  4. 苹果照片传输到电脑怎么传?批量传输的技巧!
  5. 《uni-app》表单组件-Checkbox组件
  6. 隐函数+导数定义思路
  7. 2021-11-05导数定义的应用
  8. 使用SSH客户端远程登录Linux主机(可替代samba、ftp服务)
  9. 上善若水——兼谈我的创建理念
  10. mysql设置约束设置范围_MySql 约束条件