本篇文章我们用Go实现一个自定义事件注册并等待唤醒的机制,其中涉及到的链表操作可以参考上一篇文章。文章参考自:https://github.com/brewlin/net-protocol

1.自定义唤醒事件

type EventMask uint16

const (
EventIn EventMask = 0x01
EventPri EventMask = 0x02
EventOut EventMask = 0x04
EventErr EventMask = 0x08
EventHUp EventMask = 0x10
EventNVal EventMask = 0x20
)

2.等待对象

type Entry struct {
Context interface{}
Callback EntryCallback
mask EventMask
ilist.Entry
}

3.等待对象被唤醒后的回调

type EntryCallback interface {
Callback(e *Entry)
}

4.EntryCallback接口的实现

Callback向等待对象的channel发送值以唤醒channel上的等待协程。

type channelCallback struct{}

func (*channelCallback) Callback(e *Entry) {
ch := e.Context.(chan struct{})
select {
case ch <- struct{}{}:
default:
}
}

5.初始化等待对象

这里的channel将会用于阻塞未被唤醒时的协程。

func NewChannelEntry(c chan struct{}) (Entry, chan struct{}) {
if c == nil {
c = make(chan struct{}, 1)
} return Entry{Context: c, Callback: &channelCallback{}}, c
}

6.等待队列

type Queue struct {
list ilist.List
mu sync.RWMutex
}

7.事件注册和事件注销

// EventRegister 注册等待对象
func (q *Queue) EventRegister(e *Entry, mask EventMask) {
q.mu.Lock()
e.mask = mask
q.list.PushBack(e)
q.mu.Unlock()
} // EventUnregister 注销等待对象
func (q *Queue) EventUnregister(e *Entry) {
q.mu.Lock()
q.list.Remove(e)
q.mu.Unlock()
}

8.事件唤醒

根据事件类型,通过回调函数向channel发送值以唤醒等待队列中的所有相关等待对象。

func (q *Queue) Notify(mask EventMask) {
q.mu.RLock()
for it := q.list.Front(); it != nil; it = it.Next() {
e := it.(*Entry)
if mask&e.mask != 0 {
e.Callback.Callback(e)
}
}
q.mu.RUnlock()
}

9.其他方法

// Events 返回已注册的事件类型
func (q *Queue) Events() EventMask {
ret := EventMask(0) q.mu.RLock()
for it := q.list.Front(); it != nil; it = it.Next() {
e := it.(*Entry)
ret |= e.mask
}
q.mu.RUnlock() return ret
} // IsEmpty 等待队列是否为空
func (q *Queue) IsEmpty() bool {
q.mu.Lock()
defer q.mu.Unlock() return q.list.Front() == nil
}

10.使用示例

func main() {
var wq waiter.Queue waitEntry, notifyCh := waiter.NewChannelEntry(nil)
wq.EventRegister(&waitEntry, waiter.EventIn)
defer wq.EventUnregister(&waitEntry) go func() {
for {
time.Sleep(time.Second)
wq.Notify(waiter.EventIn)
}
}() for {
<-notifyCh
fmt.Println("waked")
}
}

Go组件库总结之事件注册唤醒的更多相关文章

  1. 属性.native用于解决第三方el组件库@click事件无效

    描述 有时发现用一些第三方的组件库时,例如一个封装好的button按钮<el-butten>,绑定点击事件却没有任何作用,这时便需要加 .native 原因: v-on 是对 Vue 的事 ...

  2. vue 复习篇. 注册全局组件,和 组件库

    初篇 ============================================================== 1. 编写loading组件(components/Loading/ ...

  3. 前端笔记之Vue(四)UI组件库&Vuex&虚拟服务器初识

    一.日历组件 new Date()的月份是从0开始的. 下面表达式是:2018年6月1日 new Date(2018, 5, 1); 下面表达式是:2018年5月1日 new Date(2018, 4 ...

  4. 如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源

    1.前言 关于微信内部正在使用的网络层封装库Mars开源的消息,1个多月前就已满天飞(参见<微信Mars:微信内部正在使用的网络层封装库,即将开源>),不过微信团队没有失约,微信Mars ...

  5. 【转】如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源

    网上看到关于微信官方的跨平台跨业务的终端基础组件Mars的介绍文章,转载这这里.源代码: https://github.com/Tencent/mars作者:男人链接:https://zhuanlan ...

  6. vue统计组件库和ui框架

    UI组件 element ★13489 - 饿了么出品的Vue2的web UI工具套件 Vux ★8133 - 基于Vue和WeUI的组件库 iview ★6634 - 基于 Vuejs 的开源 UI ...

  7. Blazor组件提交全记录: FullScreen 全屏按钮/全屏服务 (BootstrapBlazor - Bootstrap 风格的 Blazor UI 组件库)

    Blazor 简介 Blazor 是一个使用 .NET 生成的交互式客户端 Web UI 的框架.和前端同学所熟知的 Vue.React.Angular 有巨大差异. 其最大的特色是使用 C# 代码( ...

  8. Vue3 企业级优雅实战 - 组件库框架 - 1 搭建 pnpm monorepo

    前两篇文章分享了基于 vite3 vue3 的组件库基础工程 vue3-component-library-archetype 和用于快速创建该工程的工具 yyg-cli,但在中大型的企业级项目中,通 ...

  9. Vue3 企业级优雅实战 - 组件库框架 - 10 实现组件库 cli - 下

    上文创建了一堆 utils.component-info,并实现了新组件模块相关目录和文件的创建.本文继续实现后面的内容. 1 组件样式文件并导入 在 src/service 目录中创建 init-s ...

  10. 2015.5.2-2015.5.8 Tip jQuery ,前端组件库,inline-block元素间距等

    有忙于它事,故延迟了,但在坚持! 1.Tip jQuery   2.给span加display: inline-block; 怎样能对齐? 解决方法:vertical-align: bottom:   ...

随机推荐

  1. Thymeleaf中判断Security权限 - SpringBoot

    参考:https://blog.csdn.net/perfect_red/article/details/110821582

  2. 对List集合进行分页

    1 简要说明 有时候,我们有一个list集合,需要对它进行分页处理 下面的根据类MyPageUtilVo就可以做到 它自带泛型,适合各种集合 可以设置每页的大小(默认为10) 根据页码(从1开始)就可 ...

  3. 如何查看库函数实现的某些函数(strlen,strcmp,strcpy等)

    我们拿strlen()作为举例(编译环境为:VS2022) strlen()引用的头文件为 string.h,如下进行操作 ps:打开strlen.c文件 便可以看到库函数对于strlen()的实现, ...

  4. SpringBoot 整合Seccurity、权限管理

    Spring Boot 整合Spring Seccurity 1.创建maven工程 <?xml version="1.0" encoding="UTF-8&quo ...

  5. 安装kali2021.1系统

    基本安装 下载地址:Downloads | Kali Linux 去官网下载,会得到kali2021.1的镜像和哈希值 打开VMware软件,新建虚拟机........................ ...

  6. 题解 Trie 但是你要最小化它的节点数量

    名字瞎取的 Description 给定 \(n\) 个字符串 \(s\),可以对 \(s_i\) 的字符打乱,将这些字符串加入一个 trie 里面求节点数量最小值. \(n\le 16, \sum ...

  7. 「Python实用秘技13」Python中临时文件的妙用

    本文完整示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/PythonPracticalSkills 这是我的系列文章「Python实用秘技」的第12 ...

  8. Python3 时间戳格式化和减法运算

    import datetime import time # 获取当前时间(2023-02-16 16:41:36) now_date = datetime.datetime.now().strftim ...

  9. virtualenvwrapper使用命令

    virtualenvwrapper使用命令 创建虚拟环境:mkvirtualenv + test1 查看虚拟环境:lsvirtuslenv 删除虚拟环境:rmvirtualenv + test1 退出 ...

  10. python容易被忽略的问题

    1.int()强制转换浮点数 在int()的强制转换浮点数时候,不管是正数还是负数,只取整数部分. print(int(6.235)) # 6 print(int(-6.235)) # -6 注意:这 ...