Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

重学js —— 规范中的Agents阅读 #52

Open
lizhongzhen11 opened this issue Oct 30, 2019 · 0 comments
Open

重学js —— 规范中的Agents阅读 #52

lizhongzhen11 opened this issue Oct 30, 2019 · 0 comments
Labels
js基础 Good for newcomers 重学js 重学js系列 规范+MDN

Comments

@lizhongzhen11
Copy link
Owner

lizhongzhen11 commented Oct 30, 2019

Agents

主要是对规范翻译。

代理包括一组ECMAScript执行上下文,一个执行上下文栈,一个运行时执行上下文,一组命名任务队列,一个 代理记录 和一个执行线程。除执行线程外,代理的组成部分完全属于该代理。

代理程序的执行线程独立于其他代理程序,在代理程序的执行上下文上执行代理程序任务队列中的任务。除非共享线程中没有一个代理具有[[CanBlock]]属性为 true 的代理记录,否则执行线程可以被多个代理使用。

例如,某些Web浏览器跨浏览器窗口的多个不相关的选项卡共享一个执行线程。

当代理的执行线程执行代理任务队列中的任务时,该代理是这些任务中代码的 周围代理。这些代码使用周围的代理访问该代理内保存的规范级别执行对象:运行时执行上下文执行上下文栈,命名的任务队列以及代理记录的字段。

下表列出代理记录的字段:

原子操作是指,对内存的一系列的读写操作必须保证不被打断来保证最终结果的正确性。可以去wiki上搜,不能翻墙的见百度

字段名 意义
[[LittleEndian]] Boolean类型 使用算法GetValueFromBufferSetValueInBuffer为其计算默认值。选择取决于实现,并且应该是对实现最有效的选择。一旦观察到该值,就无法更改。
[[CanBlock]] Boolean类型 确定代理是否可以阻止。
[[Signifier]] 任何全局唯一值 用于表示该代理在代理群内的唯一标识。
[[IsLockFree1]] Boolean类型 如果对单字节值的原子操作是无锁的,则为 true,否则为 false
[[IsLockFree2]] Boolean类型 如果对2字节值的原子操作是无锁的,则为 true,否则为 false
[[IsLockFree8]] Boolean类型 如果对8字节值的原子操作是无锁的,则为 true,否则为 false
[[CandidateExecution]] 一个candidate execution记录 内存模型

一旦代理群中的任何代理观察到[[Signifier]][[IsLockFree1]][[IsLockFree2]]的值,它们就无法更改。

[[IsLockFree1]][[IsLockFree2]]的值不一定由硬件确定,但也可能反映了ES实现选择,这些选择会随着时间的推移以及ECMAScript实现之间的变化而变化。

没有[[IsLockFree4]]属性:4字节原子操作始终是无锁的。

实际上,如果用任何类型的锁来实现原子操作,则该操作不是无锁的。无锁并不意味着无等待:完成无锁原子操作可能需要多少机器步骤没有上限。

大小为n的原子访问是无锁的,并不意味着有关大小为n的非原子访问的(感知)原子性,特别是,非原子访问仍可以作为几个单独的内存访问的序列来执行。详见ReadSharedMemoryWriteSharedMemory

代理是一种规范机制,不需要与ECMAScript实现的任何特定工件相对应。

Agent Clusters(代理集群)

代理程序集群是 通过对共享内存进行操作而通信的最大代理程序集。

不同代理中的程序可能通过未指定的方式共享内存。 至少,可以在集群中的代理之间共享SharedArrayBuffer对象的后备内存。

可能有一些代理可以通过消息传递进行通信,而这些消息不能共享内存。 它们永远不在同一个代理集群中。

每个代理都完全属于一个代理集群。

集群中的代理不必在某个特定时间点都处于活动状态。如果代理A创建了代理B,之后,A终止,B又创建代理C,如果A可以与B共享一些内存并且B也可以与C共享一些内存,则A,B,C三个代理程序在同一个集群中。

同一个集群内的所有代理程序在各自 代理记录 内必须具有 相同[[LittleEndian]]值。

注意:如果一个代理集群内不同的代理程序有不同的[[LittleEndian]]值,则很难将共享内存用于多字节数据。

集群内的所有代理在各自的 代理记录 中必须有 相同[[IsLockFree1]] 值;[[IsLockFree2]]属性和它类似。

集群内的所有代理在各自的 代理记录 中必须有 不同[[Signifier]]值。

在代理不知情或不合作的情况下,嵌入可能会使其无效(停止前进)或激活(继续前进)。如果嵌入这样做,则一定不能使集群中的某些代理处于活动状态,而集群中的其他代理会被无限期停用。

前述限制的目的是避免由于另一个代理已被停用而导致代理死锁或饥饿的情况。例如,如果一个HTML共享工作进程的生命周期独立于任何窗口中的文档,则允许它与此类独立文档的专用工作进程共享内存,并且文档及其专用工作线程将被停用,而专用工作线程持有一个锁(例如,文档将被推入其窗口的历史记录中),然后,共享工作进程尝试获取锁,然后将阻塞共享工作进程,直到再次激活专用工作进程(如果有的话)。与此同时,试图从其他窗口访问共享工作进程的其他工作进程将会失败。

这一限制的含义是,嵌入中不属于同一 挂起/唤醒 集合的代理之间将无法共享内存。

嵌入可以在没有任何代理的集群的其他代理事先知道或合作的情况下终止代理。如果某个代理不是通过其自身或集群中其他代理的编程动作而是通过集群外部的力量终止的,那么嵌入必须选择两种策略之一:

  • 要么终止集群中的所有代理,
  • 提供可靠的API,允许集群中的代理进行协调,以便至少还有一个集群成员能够检测到终止,终止数据包含足够的信息来标识已终止的代理。

此类终止的示例包括:操作系统或用户终止在不同进程中运行的代理;当每个代理程序资源记帐指示该代理程序失控时,嵌入本身将终止与其他代理程序一起在进程中运行的代理程序。

在集群中的任何代理对任何ECMAScript代码进行任何运算之前,将集群中所有代理的 代理记录 的[[CandidateExecution]]字段设置为初始候选执行。初始候选执行是一个空的候选执行,它的[[EventsRecords]]字段是一个List,对于每个代理,该列表包含一个 代理事件记录,该代理事件记录的[[AgentSignifier]]字段是该代理的标识符,并且其[[EventList]][[AgentSynchronizesWith]]字段为空列表。

代理群集中的所有代理在其代理记录[[CandidateExecution]]字段中共享相同的候选执行候选执行是一种被内存模型使用的规范机制。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
js基础 Good for newcomers 重学js 重学js系列 规范+MDN
Projects
None yet
Development

No branches or pull requests

1 participant