2021SC@SDUSC Ebiten(八) hooks代码详解

2021SC@SDUSC Ebiten(八) hooks代码详解,第1张

2021SC@SDUSC 

Go语言的简单2D游戏库-Ebiten     

目录

概述

代码

 主要函数

func  AppendHookOnBeforeUpdate

func RunBeforeUpdateHooks

func OnSuspendAudio

func SuspendAudio

func ResumeAudio

golang中sync.RWMutex和sync.Mutex

Mutex:互斥锁

示例代码:

RWMutex:读写锁,RWMutex 基于 Mutex 实现

Lock() 和 Unlock():

RLock() 和 RUnlock():


概述

这部分代码解决的问题主要是通过钩子函数来封装一些音频组件,然后通过传入钩子函数来实现音频的恢复和暂停,通过引入sync包来实现对共享资源的上锁和解锁。

代码
package hooks

import (
	"sync"
)

var m sync.Mutex

var onBeforeUpdateHooks = []func() error{}

// AppendHookOnBeforeUpdate appends a hook function that is run before the main update function
// every frame.
func AppendHookOnBeforeUpdate(f func() error) {
	m.Lock()
	onBeforeUpdateHooks = append(onBeforeUpdateHooks, f)
	m.Unlock()
}

func RunBeforeUpdateHooks() error {
	m.Lock()
	defer m.Unlock()

	for _, f := range onBeforeUpdateHooks {
		if err := f(); err != nil {
			return err
		}
	}
	return nil
}

var (
	audioSuspended bool
	onSuspendAudio func() error
	onResumeAudio  func() error
)

func OnSuspendAudio(f func() error) {
	m.Lock()
	onSuspendAudio = f
	m.Unlock()
}

func OnResumeAudio(f func() error) {
	m.Lock()
	onResumeAudio = f
	m.Unlock()
}

func SuspendAudio() error {
	m.Lock()
	defer m.Unlock()
	if audioSuspended {
		return nil
	}
	audioSuspended = true
	if onSuspendAudio != nil {
		return onSuspendAudio()
	}
	return nil
}

func ResumeAudio() error {
	m.Lock()
	defer m.Unlock()
	if !audioSuspended {
		return nil
	}
	audioSuspended = false
	if onResumeAudio != nil {
		return onResumeAudio()
	}
	return nil
}
 主要函数 func  AppendHookOnBeforeUpdate

AppendHookOnBeforeUpdate添加一个钩子函数,该钩子函数在每帧主更新函数之前运行。在访问存储钩子函数的数组之前,对该资源进行上锁,等成功添加传进来的钩子函数后,再对该资源进行解锁

func RunBeforeUpdateHooks

运行钩子函数 通过使用defer 使函数在执行return语句之前执行m.Unlock()实现对资源的解锁

func OnSuspendAudio

 将传入的封装有要暂停音频的钩子函数存到onSuspendAudio

func SuspendAudio

在上锁之后,如果audioSuspended此时为true,说明已经执行过暂停音频函数了,不能再执行,返回nil。

若audioSuspended为false,则将其设为true,告诉别人我执行过暂停音频函数了,然后若onSuspendAudio不为空,则返回函数onSuspendAudio()

func ResumeAudio

恢复音频,与暂停音频类似,若audioSuspended为true,说明执行过暂停音频函数,可以继续执行函数ResumeAudio,并将audioSuspended设为false,告诉别人可以再次执行暂停音频函数。

golang中sync.RWMutex和sync.Mutex Mutex:互斥锁
type Mutex struct {
    // 包含隐藏或非导出字段
}

Mutex是一个互斥锁,可以创建为其他结构体的字段;零值为解锁状态。Mutex类型的锁和线程无关,可以由不同的线程加锁和解锁。

1、在一个 goroutine 获得 Mutex 后,其他 goroutine 只能等到这个 goroutine 释放该 Mutex
2、使用Lock()加锁后,便不能再次对其进行加锁,直到利用Unlock()解锁对其解锁后,才能再次加锁.
3、适用于读写不确定场景,即读写次数没有明显的区别,并且只允许只有一个读或者写的场景,所以该锁叶叫做全局锁
4、在同一个 goroutine 中的 Mutex 解锁之前再次进行加锁,会导致死锁

func (m *Mutex) Lock()
//Lock方法锁住m,如果m已经加锁,则阻塞直到m解锁。
func (m *Mutex) Unlock()
//Unlock方法解锁m,如果m未加锁会导致运行时错误。
//锁和线程无关,可以由不同的线程加锁和解锁。
示例代码:

加锁和解锁:

package main

import (
	"fmt"
	"sync"
)

func main() {
	var L *sync.Mutex //互斥锁
	L = new(sync.Mutex)
	L.Lock()         //加锁
	defer L.Unlock() //解锁
	fmt.Println("hello")
}
//结果:hello

在解锁之前加锁会导致死锁:

package main

import (
	"fmt"
	"sync"
)

func main() {
	var L *sync.Mutex //互斥锁
	L = new(sync.Mutex)
	L.Lock() //加锁
	//defer L.Unlock() //解锁
	fmt.Println("hello")
	L.Lock()//再次加锁
}
//结果:
//hello
//fatal error: all goroutines are asleep - deadlock!

RWMutex:读写锁,RWMutex 基于 Mutex 实现
type RWMutex struct {
    // 包含隐藏或非导出字段
}

RWMutex是读写互斥锁。该锁可以被同时多个读取者持有或唯一个写入者持有。RWMutex可以创建为其他结构体的字段;零值为解锁状态。RWMutex类型的锁也和线程无关,可以由不同的线程加读取锁/写入和解读取锁/写入锁。

1、可以加多个读锁或者一个写锁
2、写锁权限高于读锁,有写锁时优先进行写锁定
3、读锁占用的情况下会阻止写,不会阻止读,多个 goroutine 可以同时获取读锁
4、写锁会阻止其他 goroutine(无论读和写)进来,整个锁由该 goroutine 独占

func (rw *RWMutex) Lock()
//Lock方法将rw锁定为写入状态,禁止其他线程读取或者写入。
func (rw *RWMutex) Unlock()
//Unlock方法解除rw的写入锁状态,如果m未加写入锁会导致运行时错误。

Lock() 和 Unlock():

Lock() 加写锁,Unlock() 解写锁

package main

import (
	"fmt"
	"sync"
)

func main() {
	var L *sync.RWMutex //读写锁
	L = new(sync.RWMutex)
	L.Lock() //加锁
	fmt.Println("hello")
	L.Unlock() //解锁
}

func (rw *RWMutex) RLock()
//RLock方法将rw锁定为读取状态,禁止其他线程写入,但不禁止读取。
func (rw *RWMutex) RUnlock()
//Runlock方法解除rw的读取锁状态,如果m未加读取锁会导致运行时错误。

RLock() 和 RUnlock():

1.RLock() 加读锁,RUnlock() 解读锁。
2.RLock() 加读锁时,如果存在写锁,则无法加读锁;当只有读锁或者没有锁时,可以加读锁,读锁可以加载多个。
3.在没有读锁的情况下调用 RUnlock() 会导致 panic 错误。
4.当RUnlock多于RLock时,会报错,进入死锁

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/langs/995112.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存