# thread.table 库模块帮助文档

<details>  <summary>用法说明</summary>  <p>

线程共享表用于读写多线程共享值，以简化 thread.get,thread.set 的操作。
线程共享表本质上只是线程共享数据代理对象，自身并不存储这些线程共享数据。

线程共享表（thread.table ）基本规则：

- 每次读取共享表的成员都会在当前线程复制一个新的副本。
- 写入直接表的直接成员才会写入线程共享资源。
- 不要将普通表直接覆盖替换线程共享表自身，应当存为子表
- 线程共享表的子表并非也是共享表，修改子表的成员并不能更新父级线程共享表。
- 线程共享表的下标操作符被重载为读写共享资源，不会与共享表的同名方法、属性发生冲突。
- 线程共享表的成员操作符虽然也能读写共享资源，但要避免覆盖同名的共享表方法与属性。
- 获取共享数组长度应当用线程共享表对象的 len 函数而不是 # 操作符。

使用 thread.table 的示例 aardio 代码：

```aardio

//注意先导入 thread.table 库再创建 thread.table 对象。
var thrdTable = thread.table()

//用下标读写键值，键名与对象的属性、函数名同名不会冲突。
thrdTable["b"] = 34; 
thrdTable["c"]= 56; 

//可以读写普通表，但子表并不是线程共享表。
thrdTable["d"] = {}; 

//每次读取 thrdTable.d 都会得到新的副本
var localData = thrdTable["d"];

//修改 localData 不会自动会同步到线程共享资源。
localData.tab = { name = "name" }

//下面这样只是修改子表的临时副本，子表不是线程共享表
thrdTable.d.tab = { name = "name" }

//只有修改线程共享表的直接成员，才会自动同步到线程共享资源
thrdTable["d"] = localData;

//注意 # 操作符不适合用于线程共享表
var len = #thrdTable

//应当用 len 函数或 length 属性获取共享数组长度
len = thrdTable.len(); // 也可以用 thrdTable.

//线程共享表可作为线程函数的参数直接传入其他线程函数。
thread.invoke( 
	function(tab){
		var localData = thrdTable["d"]; 
	},thrdTable
)
```

</p></details>

## thread 成员列表 <a id="thread" href="#thread">&#x23;</a>

### thread.table(shareName,clear) <a id="thread.table" href="#thread.table">&#x23;</a>
创建多线程共享表，返回对象可作为参数传入其他线程函数。  
可选使用参数 @1 指定线程共享变量名，  
省略参数 @shareName 则自动分配线程共享变量名。  

thread.var 以及 thread.table 分配的线程共享变量名上限为  
:0x3FFFFFFFFFFFFC0000000000000 个。  
应及时调用线程共享表的 release 函数释放对象与空闲的共享变量名  

可选用参数 @2 指定是否要重新初始化并创建新的共享表。  
如果未指定共享表名称，则总是重新初始化共享表  

[返回对象:threadTableObject](#threadTableObject)

## thread.table 成员列表 <a id="thread.table" href="#thread.table">&#x23;</a>

多线程共享表。  
这是标准库模块，需要导入才能用。  
线程共享表用于读写多线程共享值，以简化 thread.get,thread.set 的操作。  
注意线程共享表本质上只是线程共享数据代理对象，自身并不存储这些线程共享数据。  
- 每次读取共享表的成员都会在当前线程复制一个新的副本。  
- 写入直接表的直接成员才会写入线程共享资源。  
- 不要将普通表直接覆盖替换线程共享表自身，应当存为子表  
- 线程共享表的子表并非也是共享表，修改子表的成员并不能更新父级线程共享表。  
- 线程共享表的下标操作符被重载为读写共享资源，不会与共享表的同名方法、属性发生冲突。  
- 线程共享表的成员操作符虽然也能读写共享资源，但要避免覆盖同名的共享表方法与属性。  
- 获取共享数组长度应当用线程共享表对象的 len 函数而不是 # 操作符。

### thread.table.array(shareName,clear) <a id="thread.table.array" href="#thread.table.array">&#x23;</a>
创建多线程共享数组，返回对象可作为参数传入其他线程函数。  
可选使用参数 @1 指定线程共享变量名，  
省略参数  @shareName 则自动分配线程共享变量名。  

thread.var 以及 thread.table 分配的线程共享变量名上限为  
:0x3FFFFFFFFFFFFC0000000000000 个。  
应及时调用线程共享表的 release 函数释放对象与空闲的共享变量名  

可选用参数 @2 指定是否要重新初始化并创建新的共享表。  
如果未指定共享表名称，则总是重新初始化共享表  

[返回对象:threadTableObject](#threadTableObject)

### thread.table.cache(shareName,kv,clear) <a id="thread.table.cache" href="#thread.table.cache">&#x23;</a>
创建多线程共享的缓存表。  
参数 @shareName 指定共享名。  
参数 @kv 指定缓存键值选项，用法请参考 _weak 元属性说明。  
可选用 @clear 指定是否清除旧变量，默认保留。

## threadTableObject 成员列表 <a id="threadTableObject" href="#threadTableObject">&#x23;</a>

### threadTableObject.* <a id="threadTableObject.any" href="#threadTableObject.any">&#x23;</a>
使用索引下标 [] 可读写共享表全部键值。  
使用成员属性操作符 . 则先访问对象的函数成员。  

不要拿普通表直接覆盖线程共享表本身，应存为共享表里的成员表。  

因为每次读取共享表的成员都会在当前线程复制一个新的副本。  
所以要修改线程共享表里面的子表，必须先读取到当前线程的本地变量。

### threadTableObject.add(字段名,数值) <a id="threadTableObject.add" href="#threadTableObject.add">&#x23;</a>
修改共享表中参数 @1 指定名字的字段值。  
旧的字段值必须为 null 或数值。  
如果旧值为 null 则直接赋值为参数@2。  
如果旧值为数值则增加参数 @2 指定的数值。

### threadTableObject.append() <a id="threadTableObject.append" href="#threadTableObject.append">&#x23;</a>
追加一个或多个数组到线程共享表,  
此函数内部使用table.append实现,规则相同,  
但无返回值

### threadTableObject.assign <a id="threadTableObject.assign" href="#threadTableObject.assign">&#x23;</a>
覆盖式混入表,  
支持覆盖已存在的值,不支持递归混入成员表,  
此函数不复制元表。  

与 table.assign 不同的是线程共享表的 assign 方法不会返回任何值。

### threadTableObject.assign(任意多个混入对象...) <a id="threadTableObject.assign" href="#threadTableObject.assign">&#x23;</a>
参数 @1 为空则创建新表。  
使用后面的对象混入前面的对象(浅拷贝),并返回该对象  
该函数仅修改第一个参数(混入目标) ,覆盖已存在的键值  
此函数不会覆盖已存在的只读成员  

遇到任何参数为 null 则停止合并返回。

### threadTableObject.clear() <a id="threadTableObject.clear" href="#threadTableObject.clear">&#x23;</a>
清空共享表中的所有值

### threadTableObject.concat(arg1...) <a id="threadTableObject.concat" href="#threadTableObject.concat">&#x23;</a>
拼接多个 table 对象，参数用法请与 table.concat 相同

### threadTableObject.count() <a id="threadTableObject.count" href="#threadTableObject.count">&#x23;</a>
获取 table 成员总数

### threadTableObject.each <a id="threadTableObject.each" href="#threadTableObject.each">&#x23;</a>

```aardio
for k,v in threadTableObject.each() {
	/*遍历表对象，k 为当前键，v 为当前值*/
}
```

### threadTableObject.get((key) <a id="threadTableObject.get(" href="#threadTableObject.get(">&#x23;</a>
读取线程共享表的指定键值。  
参数 @key 指定键，必须遵守线程传参规则。

### threadTableObject.getByPath <a id="threadTableObject.getByPath" href="#threadTableObject.getByPath">&#x23;</a>
按指定的`表路径`查找深层嵌套成员的值。  
找不到`表路径`的任何部分返回 null 而非报错。。  
此函数会内部调用 table.get 实现。

### threadTableObject.getByPath(path) <a id="threadTableObject.getByPath" href="#threadTableObject.getByPath">&#x23;</a>
根据参数 @path 指定的`表路径`在线程共享表内查找值。  

参数 @path 使用与 table.get,table.set 相同的语法：  
- 使用成员操作符 `.` 分隔上下级路径。  
- 使用下标 `[]` 包含的表达式表示元素的键，空`[]`（仅限 `path` 参数内）表示数组最后一个元素。  
- 上述路径可以任意组合，嵌套路径从左到右逐层深入。  
找不到指定路径中的任何部分时返回 null，不会报错，也不会创建指定路径的对路。

### threadTableObject.insert(要插入的值 ) <a id="threadTableObject.insert" href="#threadTableObject.insert">&#x23;</a>
插入元素到 table 头部，参数用法请与 table.insert 相同

### threadTableObject.insert(要插入的值,要插入的位置 ) <a id="threadTableObject.insert" href="#threadTableObject.insert">&#x23;</a>
插入元素到指定位置，参数用法请与 table.insert 相同

### threadTableObject.left(len) <a id="threadTableObject.left" href="#threadTableObject.left">&#x23;</a>
返回 table 对象左侧开始返回指定个数的元素。  
参数用法请与 table.left 相同

### threadTableObject.len() <a id="threadTableObject.len" href="#threadTableObject.len">&#x23;</a>
返回 table 对象的数组元素长度，不含数组成员则返回 0。  
length 属性也可以返回数组长度，但表不是数组类型时返回 null。  

&num; 操作符仅用于计算表对象自身存储的数组成员，  
但线程共享仅仅是共享表的代理表，并不存储真正的共享数据。

### threadTableObject.lenByPath(path) <a id="threadTableObject.lenByPath" href="#threadTableObject.lenByPath">&#x23;</a>
根据参数 @path 指定的`表路径`在线程共享表内查找成员并返回其数组长度。  
路径语法请参考 table.get 函数说明。

### threadTableObject.length <a id="threadTableObject.length" href="#threadTableObject.length">&#x23;</a>
数组返回数组长度，表不含数组成员且不是数组类型时返回 null。  
可使用 thread.table.array 创建数组类型的线程共享表。  

&num; 操作符仅用于计算表对象自身存储的数组成员，  
但线程共享仅仅是共享表的代理表，并不存储真正的共享数据。

### threadTableObject.name <a id="threadTableObject.name" href="#threadTableObject.name">&#x23;</a>
共享表名字，不要改动

### threadTableObject.next( key ) <a id="threadTableObject.next" href="#threadTableObject.next">&#x23;</a>
迭代获取table的下一个键值对元素

### threadTableObject.next() <a id="threadTableObject.next" href="#threadTableObject.next">&#x23;</a>
获取table的第一个键值对元素

### threadTableObject.pop() <a id="threadTableObject.pop" href="#threadTableObject.pop">&#x23;</a>
在顺序数组尾部弹出一个或多个元素并作为返回值。  
参数用法请与 table.pop 相同

### threadTableObject.push() <a id="threadTableObject.push" href="#threadTableObject.push">&#x23;</a>
在顺序数组尾部压入一个或多个元素,返回数组大小。  
参数用法请与 table.push 相同

### threadTableObject.push(v1,v2,v3,...) <a id="threadTableObject.push" href="#threadTableObject.push">&#x23;</a>
在顺序数组尾部压入多个元素,返回数组大小。  
参数用法请与 table.push 相同

### threadTableObject.range() <a id="threadTableObject.range" href="#threadTableObject.range">&#x23;</a>
返回table数组的最小索引,最大索引。  
例如 `var min,max=tab.range()`

### threadTableObject.release() <a id="threadTableObject.release" href="#threadTableObject.release">&#x23;</a>
释放线程共享表，释放后不应当再使用

### threadTableObject.remove( ) <a id="threadTableObject.remove" href="#threadTableObject.remove">&#x23;</a>
在 table 头部移除元素，参数用法请与 table.insert 相同

### threadTableObject.remove(位置) <a id="threadTableObject.remove" href="#threadTableObject.remove">&#x23;</a>
在表中指定位置移除元素，参数用法请与 table.insert 相同

### threadTableObject.reverse() <a id="threadTableObject.reverse" href="#threadTableObject.reverse">&#x23;</a>
table 数组倒序排列。

### threadTableObject.right(len <a id="threadTableObject.right" href="#threadTableObject.right">&#x23;</a>
返回 table 对象右侧开始返回指定个数的元素。  
参数用法请与 table.right 相同

### threadTableObject.set(key,value) <a id="threadTableObject.set" href="#threadTableObject.set">&#x23;</a>
设置线程共享表的指定键值。  
参数 @key 指定键，参数 @value 指定值，所有参数都必须遵守线程传参规则。

### threadTableObject.setByPath <a id="threadTableObject.setByPath" href="#threadTableObject.setByPath">&#x23;</a>
按指定的`表路径`设置深层嵌套成员的值。  
`表路径`中不存在的父级路径会自动添加新的表对象。  
此函数会内部调用 table.set 实现。

### threadTableObject.setByPath(path,value) <a id="threadTableObject.setByPath" href="#threadTableObject.setByPath">&#x23;</a>

```aardio
在参线程共享表内对参数 @path 指定`表路径`的成员赋值。  

参数 @path 使用与 table.get,table.set 相同的语法：  
- 使用成员操作符 `.` 分隔上下级路径。  
- 使用下标 `[]` 包含的表达式表示元素的键，空`[]`（仅限 `path` 参数内）表示在数组尾部增加新对象。  
- 上述路径可以任意组合，嵌套路径从左到右逐层深入，遇到不存在的父级路径会自动创建表对象。
```

### threadTableObject.shift(移除数目) <a id="threadTableObject.shift" href="#threadTableObject.shift">&#x23;</a>
自数组头部移除并返回指定个数成员,参数 @1 默认为 1 。  
此函数用法请与 table.shift 相同。

### threadTableObject.slice(开始位置,结束位置) <a id="threadTableObject.slice" href="#threadTableObject.slice">&#x23;</a>
从指定位置截取并返回新数组,  
开始位置可选,默认为1  
结束位置可选,默认为数组长度,返回值包含结束位置元素,  
如果位置参数为负数,则自右侧反向计算

### threadTableObject.sort( comProc) <a id="threadTableObject.sort" href="#threadTableObject.sort">&#x23;</a>
排序,comProc 指定用于比较元素大小的函数（必须是纯函数、在共享线程内执行）。  
参数用法请与 table.sort 相同

### threadTableObject.sort() <a id="threadTableObject.sort" href="#threadTableObject.sort">&#x23;</a>
排序。  
参数用法请与 table.sort 相同

### threadTableObject.splice(位置,删除长度,要插入的一个或多个元素) <a id="threadTableObject.splice" href="#threadTableObject.splice">&#x23;</a>
在线程共享表指定位置删除指定长度元素，替换为不定个数的插入元素。  
如果删除了元素,该函数返回包含删除元素的数组

### threadTableObject.tostring() <a id="threadTableObject.tostring" href="#threadTableObject.tostring">&#x23;</a>
返回调用 table.tostring 序列化线程共享表数据获得的字符串。

### threadTableObject.unpack() <a id="threadTableObject.unpack" href="#threadTableObject.unpack">&#x23;</a>
返回表中所有的元素。  
例如 `a,b,c,d,e = tab.unpack()`

### threadTableObject.unshift(要插入的一个或多个元素) <a id="threadTableObject.unshift" href="#threadTableObject.unshift">&#x23;</a>
插入一个或多个元素到数组头部,返回数组长度。  
参数用法请与 table.unshift 相同
