本篇文章我们用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. spring security登录认证流程解析

    转 https://blog.csdn.net/qq_37142346/article/details/80032336 1.说明 用户认证流程 认证结果如何在多个请求之间共享 获取认证用户信息.用户 ...

  2. WinRAR的 安装与下载

    一.简介 WinRAR 是一个强大的压缩文件管理工具.它能备份你的数据,减少你的 E-mail 附件的大小,解压缩从 Internet 上下载的 RAR.ZIP 和其他格式的压缩文件,并能创建 RAR ...

  3. Listary 文件搜索工具

    Listary简介 Listary是一款强大的全盘文件搜索.软件启动效率工具,双击Ctrl随时调出搜索框,全盘海量文件毫秒级检索,快速定位打开所需文件.集成右键菜单和诸多自定义动作,适配Windows ...

  4. (原创)【B4A】一步一步入门03:APP名称、图标等信息修改

    一.前言 上篇 (原创)[B4A]一步一步入门02:可视化界面设计器.控件的使用 中我们已经了解了B4A程序的基本框架,现在我们还进一步讲解. 本篇文章会讲解如何修改APP的名称.图标等信息,以让一个 ...

  5. redis未授权访问漏洞——简单记录

    从0复现redis未授权访问漏洞 环境:centos8(ip:10.0.0.3) 安装 redis 工具:kali(10.1.1.136) 1. 介绍 Redis REmote DIctionary ...

  6. jsHtml解码

    //将HTML代码转换为文本 function HTMLDecode(text) { var temp = document.createElement("div"); temp. ...

  7. postgresql序列基本操作

    1.创建序列 CREATE SEQUENCE if not exists test_mergetable_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 99999999 ...

  8. PostgreSQL 实现快速删除一个用户

    一.具体方法 一般情况下直接执行 drop role xxx; 就可以把这个用户删除.但是很多时候会因为用户有依赖而报错. 二.权限依赖 postgres=# create role test wit ...

  9. jquery获得标签元素

    一.根据元素name值获取元素 $("元素[name="name的值"]"); 例子:1.$("a[name="apoint"]& ...

  10. php 安装 自带扩展

    # 进入安装包解压目录 cd /usr/local/src/php-8.0.0/ # 进入扩展目录 cd ext/gd # 编译 phpize # 配置 ./configure --with-php- ...