event 注册和注销

ESP32——事件监听 由于ESP32使用了FreeRTOS实时操作系统,所以避免不了事件,任务的使用。使用事件组件库可以申明其他组件可以向其注册处理程序的事件,代码将在事件发生时执行。这允许松耦合的组件将所需的行为附加到其他组件的状态更改。 阅读详情

本节我们依旧来分析event的操作, 接着上节没有讲完的关于event的注册和注销两个功能的实现.

event 注册

依旧来看一个event 注册函数的原型

int event_add(struct event *ev, const struct timeval *tv);

相比event_set函数event_add真的很干净.

参数

  • ev : 将要注册的event事件. 其实实际注册的是ev->ev_base.
  • tv : 设置超时时间. 如果tv != NULL则会同时注册定时事件, 将ev添加到timer堆上.

函数源码event.c

函数真的很长, 不慌, 我们慢慢的分析(基本在注释中).

// 设置事件的定时. 实质 : 注册事件
// 1. 如果设置定时, 则先在小根堆上申请一个注册的空间
// 2. 如果事件已经处于定时队列, 则将其从定时队列中移除
// 3. 如果事件已经在就绪队列中, 则将其从就绪队列中移除
// 4. 重新设置定时时间, 并将其插入到定时队列中
int
event_add(struct event *ev, const struct timeval *tv)
{
	struct event_base *base = ev->ev_base;	// 指向要注册的 ev_base
	const struct eventop *evsel = base->evsel;
	void *evbase = base->evbase;	// base 所使用的IO成员
	int res = 0;

	event_debug((
		 "event_add: event: %p, %s%s%scall %p",
		 ev,
		 ev->ev_events & EV_READ ? "EV_READ " : " ",
		 ev->ev_events & EV_WRITE ? "EV_WRITE " : " ",
		 tv ? "EV_TIMEOUT " : " ",
		 ev->ev_callback));

	assert(!(ev->ev_flags & ~EVLIST_ALL));

	/*
	 * prepare for timeout insertion further below, if we get a
	 * failure on any step, we should not change any state.
	 */
	// 如果设置了定时, 则现在先在小根堆上分配一个空位留给定时事件, 保证注册定时事件时不会失败
	if (tv != NULL && !(ev->ev_flags & EVLIST_TIMEOUT)) {
		if (min_heap_reserve(&base->timeheap,
			1 + min_heap_size(&base->timeheap)) == -1)
			return (-1);  /* ENOMEM == errno */
	}
  
	// 该事件是处于读/写/信号并且没有处于就绪队列中
	if ((ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)) &&
	    !(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) {
		// 添加处理函数. 信号也是在这里被添加的, 都是统一的添加接口
		res = evsel->add(evbase, ev);
		if (res != -1)
			// 将设置的事件插入到注册链表中
			event_queue_insert(base, ev, EVLIST_INSERTED);
	}

	/* 
	 * we should change the timout state only if the previous event
	 * addition succeeded.
	 */
	// 设置了超时时间
	if (res != -1 && tv != NULL) {
		struct timeval now;

		/* 
		 * we already reserved memory above for the case where we
		 * are not replacing an exisiting timeout.
		 */
		// 如果已经在定时队列中, 就先将其移除再重新进行插入
		if (ev->ev_flags & EVLIST_TIMEOUT)
			event_queue_remove(base, ev, EVLIST_TIMEOUT);

		/* Check if it is active due to a timeout.  Rescheduling
		 * this timeout before the callback can be executed
		 * removes it from the active list. */
		// 检查当前事件是已经处于激活状态而且是设置了定时事件的话,
		// 就将其从就绪队列中删除
		// 注意 : 上面是从定时队列中移除, 这里是从就绪队列中移除
		if ((ev->ev_flags & EVLIST_ACTIVE) &&
		    (ev->ev_res & EV_TIMEOUT)) {
			/* See if we are just active executing this
			 * event in a loop
			 */
			if (ev->ev_ncalls && ev->ev_pncalls) {
				/* Abort loop */
				*ev->ev_pncalls = 0;
			}
			
			event_queue_remove(base, ev, EVLIST_ACTIVE);
		}

		// 计算定时器所定的时间
		gettime(base, &now);
		evutil_timeradd(&now, tv, &ev->ev_timeout);

		event_debug((
			 "event_add: timeout in %ld seconds, call %p",
			 tv->tv_sec, ev->ev_callback));

		// 重新插入定时队列中
		event_queue_insert(base, ev, EVLIST_TIMEOUT);
	}

	return (res);
}

从29行可以看出来libevent的精妙之处 : 如果申请到空间, 则下面的操作就能够正常执行, 如果不能就直接退出, 这里保证了定时的注册是一个原子操作.

现在来分析event_add的执行过程 :

  1. 如果设置了定时, 则在小根堆上分配一个空间, 以便之后的注册.
  2. 如果事件已经设置了I/O或者信号标志, 并且事件并没有被初始化或者没有在就绪队列中, 则将事件插入到就绪队列中(就是有可能该事件并没有被初始化也可以调用注册函数哦).
  3. 如果设置了定时, 现在判断它是否已经在定时队列或者在就绪队列中了,如果是, 则从队列中删除在重新设置定时并且插入到定时队列中.(就是可能事件之前已经设置了定时时间, 但是可能不满意可以反悔重新设置定时时间的)

相信整个函数的流程清楚了, 但是其中一些出现过几次的函数(event_queue_insert和event_queue_remove)知道功能但还想看一下实现吧. 不急不急, 我们一个个来分析.

event_queue_insert函数

将处理事件插入到指定队列中.

// 将处理事件插入到指定队列中
void
event_queue_insert(struct event_base *base, struct event *ev, int queue)
{
	// 如果事件已经在该队列中, 则什么也不做
	if (ev->ev_flags & queue) {
		/* Double insertion is possible for active events */
		if (queue & EVLIST_ACTIVE)
			return;

		event_errx(1, "%s: %p(fd %d) already on queue %x", __func__,
			   ev, ev->ev_fd, queue);
	}

	// 注册次数 + 1
	if (~ev->ev_flags & EVLIST_INTERNAL)
		base->event_count++;

	// 设置该标志位, 表示该事件已经被插入到该队列中
	ev->ev_flags |= queue;
	switch (queue) {
	case EVLIST_INSERTED:
		TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
		break;
	case EVLIST_ACTIVE:
		base->event_count_active++; // 队列的就绪个数 + 1
		TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],
		    ev,ev_active_next);
		break;
	case EVLIST_TIMEOUT: {
		min_heap_push(&base->timeheap, ev);
		break;
	}
	default:
		event_errx(1, "%s: unknown queue %x", __func__, queue);
	}
}

其实理解还是很容易的.

  1. 如果事件已经被注册了则什么也不做的返回
  2. 如果事件并没有被初始化, 则将base的注册数 +1
  3. 将事件加入到指定队列中. (TAILQ_INSERT_TAIL 之后分析源码.)
event_queue_remove函数

将事件从指定队列中移除.

// 将事件从指定队列中移除
void
event_queue_remove(struct event_base *base, struct event *ev, int queue)
{
	if (!(ev->ev_flags & queue))
		event_errx(1, "%s: %p(fd %d) not on queue %x", __func__,
			   ev, ev->ev_fd, queue);

	// 注册次数 - 1
	if (~ev->ev_flags & EVLIST_INTERNAL)
		base->event_count--;

	// 重设标志位, 表示事件已经从该队列中被移除
	ev->ev_flags &= ~queue;
	switch (queue) {
	case EVLIST_INSERTED:
		TAILQ_REMOVE(&base->eventqueue, ev, ev_next);
		break;
	case EVLIST_ACTIVE:
		base->event_count_active--; // 队列的就绪个数 - 1
		TAILQ_REMOVE(base->activequeues[ev->ev_pri],
		    ev, ev_active_next);
		break;
	case EVLIST_TIMEOUT:
		min_heap_erase(&base->timeheap, ev);
		break;
	default:
		event_errx(1, "%s: unknown queue %x", __func__, queue);
	}
}

过程与上面一样.

  1. 如果事件并没有在指定队列上则报错
  2. base上的注册次数 -1
  3. 重新设置ev事件的flags标志. 并从指定队列中删除注册事件.

event 的注销

event 注销其实就很简单了. 从所有队列中删除指定事件.

// 从所有队列中删除指定事件
int
event_del(struct event *ev)
{
	struct event_base *base;
	const struct eventop *evsel;
	void *evbase;

	event_debug(("event_del: %p, callback %p",
		 ev, ev->ev_callback));

	/* An event without a base has not been added */
	if (ev->ev_base == NULL)
		return (-1);
	// ev注册的event_base和eventop指针
	base = ev->ev_base;
	evsel = base->evsel;
	evbase = base->evbase;

	assert(!(ev->ev_flags & ~EVLIST_ALL));

	/* See if we are just active executing this event in a loop */
	// 将事件的回调次数设为0
	if (ev->ev_ncalls && ev->ev_pncalls) {
		/* Abort loop */
		*ev->ev_pncalls = 0;
	}

	// 事件从每一个队列中进行删除
	if (ev->ev_flags & EVLIST_TIMEOUT)
		event_queue_remove(base, ev, EVLIST_TIMEOUT);

	if (ev->ev_flags & EVLIST_ACTIVE)
		event_queue_remove(base, ev, EVLIST_ACTIVE);

	if (ev->ev_flags & EVLIST_INSERTED) {
		event_queue_remove(base, ev, EVLIST_INSERTED);
		return (evsel->del(evbase, ev));    // 同时取消监听
	}

	return (0);
}
  1. 如果事件已经就绪, 则将就绪调用回调函数的次数设置为 0
  2. 从事件所在的链表中删除, 一个事件以可能同时处在多个事件队列上.
  3. 如果事件处于EVLIST_INSERTED状态的话, 最后还应该将它的监听也删除. 如: 从epoll的监听中删除, 从绑定的信号中删除.

总结

篇幅可能有点长, 但是大多都是代码, 所以慢慢分析的话难度也不大. 其实最重要的就是搞清楚event和event_base每个成员对应的哪个功能, 其他都是判断事件状态, 加入某个队列或从某个队列中删除. 接下来我们分析event重要的主循环.

C#event EventHandler事件触发 在定义委托时,前面加上event关键字,可以保证该委托不能在外部被随意触发,两者异同: 注册 注销 内部触发 外部触发 delegate += -= Invoke Invoke event delegate += -= Invoke 不允许 所以,event关键字有助于提高类的封装性,物理隔绝代码耦合,... 阅读详情

相关推荐

Unity插件EasyButton中委托事件的注册和调用

//消息传递Message //时间委托delegate&&event Easy Button事件监听的两种方式 (1).Message ①SeedMessage 向游戏物体发消息,遍历所有脚本中查找符合的定义的方法 然后调用 ②SeedMessageUpwards 向上父类遍历 ③BroadcastMessage 向下子类遍历 (2).Event 调用注册上的方法,是固定

lliaoguipeng13的专栏 3096

Libevent源码分析-----超时event的处理

Libevent允许创建一个超时event,使用evtimer_new宏。

luotuo44的专栏 9974

CKEditor5富文本编辑器 - 视频引入、预览及自定义toolbar

文章目录定义遇到的问题视频部分引入媒体url失败原因解决方法:自定义视频provider视频预览及页面不显示视频问题解决方案:H5 \标签如何移除toolbar中的部分插件 一个小后端很少接触前端框架,只能在知识的海洋中漂泊。。。 定义 <script src="https://cdn.ckeditor.com/ckeditor5/16.0.0/classic/ckeditor.js"&gt...

huhui806的博客 8198

Libevent--Timeout

超时事件,在libevent中或许收到了更多的关照,这里使用了两种数据来处理,第一个就是小根堆,第二个就是不同相对超时时间的队列common_timeout。 1.为什么要使用两种不同的数据结构呢? 用于超时管理的min_heap,在执行主循环的过程中,它每次都会去检查min_heap的堆顶event是否超时,如果超时的话就进行相应的处理并且从min_heap中移除这个event,然后调整整个堆,直到堆顶event未超时则停止检查。这样每次删除堆顶超时的event时间复杂度只需要O...

qq_41983709的博客 775

开题报告该怎么写

考研即将来临,而一般很多大学都会选择在考研结束之后开始安排选题和开题报考(考研之前一般都不谈,老师也很人性化的,不愿意耽误你的复习) 但无论怎么推迟,我们最终都需要去面对并完成这些任务。 现在我就要教大家该如何写一个完整的开题报告! 准备模板。不同的学校有不同的格式,一般情况你的导师会给你们一个学校的标准格式,这个不用太费心。有了模板我们就可以按照模板的“线索”一步一步填充完成即可! 一般大致格式可谓: 研究背景/论文的目的、背景和意义 我们需要写明选择该题目的...

wuyueweifeng的博客 1095

Langfuse落地教程:从Docker部署到项目接入,掌控LLM调用链路

大模型应用开发中,调用链路的透明度直接决定调试效率与成本控制。可观测性技术通过记录每次请求的输入、输出、模型参数与Token消耗,帮助开发者快速定位问题。Langfuse作为开源LLM可观测性平台,将Trace、Prompt版本管理、评分等能力集成于一体,支持Docker Compose自托管部署,并提供Python/JS SDK与REST API。借助部署后的控制台,团队能够直观追踪RAG检索、Agent工具调用等复杂流程中的每一步耗时与资源占用,实现从黑盒调用到全链路可视化的转变。无论是本地调试、线上排

weixin_29698641的博客 308

libevent总结(中)

五、事件处理框架       libevent的事件处理框架是一个反应堆模型,而反应堆模型的核心就是IO复用。拿epoll来说,反应堆模型有两个核心数据结构,一个是epoll维护的内核事件表,一个是保存激活事件的事件队列。当然,值的注意的是,如果是单线程或者单进程,反应堆模型一定是IO复用+异步IO,否则无法保证及时响应。下面,将分析事件注册和事件删除的具体细节。 1.event_base

like的专栏 7840

几何修复_ANSYS流体分析:几何前处理

建模及几何处理工具非常多,选择起来让人眼花缭乱。对于仿真而言,高效的对几何进行清理及生成符合仿真要求的几何至关重要。ANSYS SpaceClaim Direct Modeler是基于直接建模思想的新一代3D高效率建模和几何编辑修补软件。SCDM提供了当今最快速、最富有创意的直接建模解决方案。由于它的直接建模能力即使对于导入的其它3D模型(如catia、proe、solid works创建的几何)...

weixin_35778830的博客 2416

x集成测试状态迁移

昨天改完后集成测试一下,不经意直接程序出现异常,apt一下 tcp        0      0 *:7777                  *:*                     LISTEN      32686/PC_*** tcp        0      0 linux:7777              linux:38318             EST

cschengvdn的专栏 791

【基金量化研究系列】基金绩效归因模型——Brinson多期归因模型

文章目录1. 引言2. Brinson单期归因模型2.1 模型框架2.2 公式推导3. Brinson多期归因模型3.1 模型框架3.2 公式推导4. Brinson模型的应用场景4.1 基金组合归因4.2 基金经理能力刻画4.3 大类资产配置应用5. 模型的实现与实证案例研究写在最后 1. 引言 在 2. Brinson单期归因模型 2.1 模型框架 wp wb rp 组合收益:wp rp 择股收益:wb rp rb 择时收益:wp rb 基准收益:wb rb 2.2 公式推

Mikey_Sun的博客 1万+

手把手教你用vivado2018.3为复旦微JFMQL15T打IP补丁(含环境变量配置技巧)

本文详细介绍了在Vivado 2018.3环境中为复旦微JFMQL15T开发板打IP补丁的全流程,包括环境变量配置、IP缓存管理等关键步骤。通过实战验证的解决方案,帮助工程师快速搭建开发环境,解决国产芯片开发中的常见问题,提升开发效率。

weixin_30374009的博客 725

event_add

支持Libevent运转的就是一个大循环,这个主循环体现在event_base_loop(Event.c/1533)函数里,该函数的执行流程如下: 图1 event_base_loop主循环         上图的简单描述就是:         (1)校正系统当前时间。         (2)将当前时间与存放时间的最小堆中的时间依次进行比较,将所有时间小于当前时间的定时器事件从堆中取

tycoon的专栏 1618

BIM Revit教程(六)尝试安装 Revit 时显示“Autodesk Revit 已安装。”

在安装Revit或RevitLT时,若系统提示“AutodeskRevit版本已安装”,通常是由于旧版本残留文件未完全清除所致。解决方案包括:1.通过控制面板或Windows设置卸载旧版本Revit,确保所有相关组件被移除;2.使用Autodesk卸载工具(AdskUninstallHelper)进一步清理;3.谨慎操作注册表,删除与Revit相关的残留项;4.确保系统有至少30GB的可用磁盘空间;5.完成上述步骤后,重新尝试安装Revit。此外,文章还提到了一个免费功能商店,供用户寻找提效工具,并鼓励粉丝

ZOZO_888的博客 2129

(七)注册/注销event事件

前言在本小节中,我们将看到event是如何注册到event_base上的,以及如何注销,如何激活等操作,最后还会梳理一下事件的状态是如何变化的。event_addint event_add(struct event *ev, const struct timeval *tv) { struct event_base *base = ev->ev_base; const struct

Move_now的博客 1762

DCMM评估报告模板样例

这篇DCMM评估报告对某数据管理公司2020年的数据管理能力进行了全面分析。报告显示,该公司在数据战略方面取得初步进展,但在数据治理和数据架构方面仍存在明显不足,包括缺乏有效治理流程、数据质量监控不足,以及数据标准化和转换灵活性不足等问题。评估报告提出了针对性改进建议,包括完善数据战略、建立治理流程、加强质量监控和提升数据转换灵活性等,为提升数据管理成熟度提供了重要指导。

cdfunlove的博客 166

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Event事件的注册和注销

通过+/-来注册和注销定义的Event。 如下通过匿名Event举例: EventHandler _testHandler = null; //注册 TestClickEvent += _testHandler = { o,e } => { ........ } //注销 TestClickEvent -= _testHandler ;

tianyu0910的专栏 703

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Unity Event注册与注销

参考https://www.cnblogs.com/horse/archive/2010/02/19/1669333.html 因为程序一直处在运行中,所以主窗体对象一直驻留内存中并保持着自身的状态(它没有的disposed),所以,每次子窗体创建时,主窗体都会注册它的OnRequestUserList事件,同样的,该子窗体在加载时,自身也会把主窗体的OnUserListCreated事件注册...

yaoyutian的博客 1692

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

委托的注册及注销+观察者模式

所以取消public,封闭它,我们可以自己书写两个方法,供外部注册与注销,委托调用在子方法里调用,这样封装委托变量可以使它更安全,这个就叫做事件。一系列对象来监听另外一个对象的行为,被监听者一旦触发事件/发布消息,则被所有监听者收到,然后执行自己的行为。就是使用委托/事件,让一系列对象把他们的行为来注册到我的委托中去。委托变量如果公开出去,很不安全,外部可以随意调用。小花想在打铃时去打羽毛球。小明想在打铃的时候去买东西吃,2.只能自己去调用自己的委托。小红想在打铃时开始练习,小张想在打铃时去打水,

m0_74236534的博客 593

event 初始化

在前面我们对整个libevent重要的核心(event和event_base)结构做了分析, 处于茫然你现在跟着再来看一下event的初始化过程, 以及事件的注册/注销过程. event 初始化 event的成员有很多, 所以我们需要对event初始化操作做一个简单的封装才行, 不然用户怎么可能不会记错记混这些参数呢. event初始化函数是 event_set. void event_set(s...

啦啦啦 836

abp.event.on与abp.event.off使用

apb的全局事件 var eventName = "app.createOrEditFieldModalSaved"; var reloadPage = function () { dt.ajax.reload(); }; abp.event.on(e...

weixin_30577801的博客 465

libusb使用详解三(USB设备的枚举和Hotplug)

介绍libusb API枚举USB设备和处理Hotplug事件的接口函数

c12f20的专栏 1628

虚幻4 Event、CustomEvent、EventDispatcher

经常接触到这些概念,今天做个总结,不涉及具体的细节,参数啊,调用啊,绑定啊等等,只是概念的区别。学术浅薄,各位一块探讨指正哈。 Event是虚幻内置的事件,这个事件什么时候被调用由引擎决定,如常见的Event HitEvent Begin PlayEvent Actor Begin OverlapEvent Actor End OverlapCustomEvents自定义事件,可以自定义事件执行的

Dream World 3093

6. Libevent 剖析

集成信号处理。本节总结如何将Signal集成到事件主循环的框架中。

qq_48056300的博客 637

ASP.NET Boilerplate 客户端事件总线(abp.event)完全指南:发布/订阅模型的注册、触发与源码剖析

ASP.NET Boilerplate 在前端 JavaScript 层内置了一个轻量的**全局事件总线 `abp.event`**,以经典的发布/订阅(Pub/Sub)模式让页面各模块之间解耦通信。本文以 [Event-Bus.md](https://link.gitcode.com/i/ffeaeb5cfb5a3bf390b38851d927fb49) 为核心骨架,结合仓库内 [abp.js]

gitblog_00648的博客 591

linux的input子系统上报函数input_event的底层原理

前言 最近在学习input子系统驱动的编写的时候,用imx6ull开发板上的按键作为输入设备进行注册。实现过程中没什么问题,但是在面试的时候被问到了input_event函数实现的底层原理,所以总结了一下,作为笔记,供大家参考吧。 一、如何使用input子系统? 在使用 input 子系统的时候我们只需要注册一个 input 设备即可, input_dev 结构体表示 input设备,此结构体定义在 include/linux/input.h 文件中 步骤大致分为以下几步: 在编写 input 设备驱动

junhua的博客 4718

深入理解事件(Event)

前言 在前一篇文章中讲到了Event 发布与订阅(一) 里面用到了事件来实现一些发布与订阅,当时对事件及其委托理解的还不是太深入,可能在使用上有点捉急。这篇来好好讲讲事件,以及通过一些小DEMO来加深理解。可以说是让我重新理解了事件。 事件(Event) 事件: 定义了事件成员的类型允许类型(或类型的实例)通知其他对象发生特定的事情。例如:Button类提供了Click事件。应用程序中...

dienen0325的博客 609
上一篇: event 初始化
下一篇: evnet 主循环
Function_18
博客等级 码龄10年 193粉丝 239原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值