shared API

包 Luna-Flow/luna_thread/shared 以 @shared 导入,包含本模块其他所有包都使用的词汇:后端目标、执行模式、顺序保证、执行策略及其验证、各后端声明的能力、原生状态码,以及镜像 C 请求结构体的整数编码记录。它可以在所有目标上构建。

本包的枚举类型在包外是只读的:可以对其构造器做模式匹配,但请用下面的函数构建值。

目标、模式与顺序

BackendTarget

执行计划或工作流的运行时。

pub enum BackendTarget {
  Native
  JavaScript
} derive(Eq, @debug.Debug)

ExecutionMode

提交是否阻塞到完成为止。

pub enum ExecutionMode {
  Synchronous
  Asynchronous
} derive(Eq, @debug.Debug)

OrderingGuarantee

结果是否必须保持输入的顺序。

pub enum OrderingGuarantee {
  PreserveInputOrder
  RelaxedOrder
} derive(Eq, @debug.Debug)

native_target、javascript_target、synchronous_mode、asynchronous_mode、preserve_input_order 和 relaxed_order

返回 Native、JavaScript、Synchronous、Asynchronous、PreserveInputOrder 和 RelaxedOrder。

pub fn native_target() -> BackendTarget
pub fn javascript_target() -> BackendTarget
pub fn synchronous_mode() -> ExecutionMode
pub fn asynchronous_mode() -> ExecutionMode
pub fn preserve_input_order() -> OrderingGuarantee
pub fn relaxed_order() -> OrderingGuarantee

backend_label

返回 "native" 或 "javascript"。

pub fn backend_label(BackendTarget) -> String
test "targets" {
  inspect(@shared.backend_label(@shared.javascript_target()), content="javascript")
  assert_true(@shared.relaxed_order() is @shared.RelaxedOrder)
}

执行策略

ExecutionPolicy

计划或工作流应如何运行:后端、模式、工作线程数、块大小和顺序。

pub struct ExecutionPolicy {
  backend : BackendTarget
  mode : ExecutionMode
  worker_count : Int
  chunk_size : Int
  ordering : OrderingGuarantee
} derive(Eq, @debug.Debug)

PolicyIssue 和 PolicyError

策略超出 v1 子集的一个原因,以及携带第一个此类原因的错误。

pub enum PolicyIssue {
  WorkerCountMustBePositive(Int)
  ChunkSizeMustBePositive(Int)
  UnsupportedBackendForV1(BackendTarget)
  UnsupportedModeForV1(ExecutionMode)
} derive(Eq, @debug.Debug)

pub struct PolicyError {
  issue : PolicyIssue
} derive(Eq, @debug.Debug)

make_execution_policy

构建一个策略,并把第一个问题作为 PolicyError 返回。

pub fn make_execution_policy(backend? : BackendTarget, mode? : ExecutionMode, worker_count? : Int, chunk_size? : Int, ordering? : OrderingGuarantee) -> Result[ExecutionPolicy, PolicyError]

默认值依次为 Native、Synchronous、1、1 和 PreserveInputOrder。检查顺序为 worker_count > 0、chunk_size > 0、backend == Native、mode == Synchronous;顺序本身不检查。

ExecutionPolicy::new

像 make_execution_policy 那样构建策略,并在它会返回错误时中止。

pub fn ExecutionPolicy::new(backend? : BackendTarget, mode? : ExecutionMode, worker_count? : Int, chunk_size? : Int, ordering? : OrderingGuarantee) -> Self

native_policy 和 javascript_policy

返回默认的原生策略,以及为 JavaScript 后端做同样尝试的结果。

pub fn native_policy() -> ExecutionPolicy
pub fn javascript_policy() -> ExecutionPolicy

native_policy() 就是 make_execution_policy().unwrap()。javascript_policy() 是 make_execution_policy(backend=JavaScript).unwrap(),由于 JavaScript 后端被拒绝,它在 v1 中会中止。

validate_policy

按上述检查的顺序返回已有策略的所有问题。

pub fn validate_policy(ExecutionPolicy) -> Array[PolicyIssue]

用上面的函数构建的策略总能通过检查;validate_policy 用于存放在工作流中的策略,@workflow.validate 会重新检查它。

is_parallel

当策略要求不止一个工作线程时返回 true。

pub fn is_parallel(ExecutionPolicy) -> Bool
test "policies" {
  let policy = @shared.make_execution_policy(worker_count=4, chunk_size=8).unwrap()
  assert_true(@shared.is_parallel(policy))
  assert_eq(@shared.validate_policy(policy).length(), 0)
  let rejected = @shared.make_execution_policy(backend=@shared.javascript_target())
  debug_inspect(
    rejected,
    content="Err({ issue: UnsupportedBackendForV1(JavaScript) })",
  )
  assert_false(@shared.is_parallel(@shared.native_policy()))
}

运行时能力

RuntimeCapabilities

后端声明的特性。

pub struct RuntimeCapabilities {
  backend : BackendTarget
  supports_parallelism : Bool
  supports_async : Bool
  supports_zero_copy_buffers : Bool
} derive(Eq, @debug.Debug)

RuntimeCapabilities::for_backend

返回后端声明的能力表。

pub fn RuntimeCapabilities::for_backend(BackendTarget) -> Self
后端并行异步零拷贝缓冲区
Nativetruefalsefalse
JavaScripttruetruetrue

该表是固定的声明,而不是对运行中系统的探测。JavaScript 一行描述的是规范所规划的后端;JavaScript 后端目前什么也不执行。

原生状态码

NativeStatus

C 运行时的状态码 0 到 7。

pub enum NativeStatus {
  Ok
  InvalidArgument
  UnsupportedBackend
  UnsupportedMode
  UnsupportedValueType
  UnsupportedReductionKernel
  Overflow
  NullPointer
} derive(Eq, @debug.Debug)

native_status_code 和 native_status_from_code

在 NativeStatus 与其 C 编码之间转换。

pub fn native_status_code(NativeStatus) -> Int
pub fn native_status_from_code(Int) -> NativeStatus

native_status_code 按声明顺序把构造器编号为 0 到 7。native_status_from_code 在 0 到 7 上是它的逆,并把其他所有编码(包括工作流状态码 8 到 14)映射为 InvalidArgument。

test "status codes" {
  assert_true(@shared.native_status_from_code(6) is @shared.Overflow)
  assert_true(@shared.native_status_from_code(14) is @shared.InvalidArgument)
  for code in 0..<8 {
    let status = @shared.native_status_from_code(code)
    assert_eq(@shared.native_status_code(status), code)
  }
}

整数编码的原生记录

这些记录逐字段镜像 C 结构体 luna_thread_buffer、luna_thread_map_request、luna_thread_reduce_request 和 luna_thread_scan_request,枚举以 Int 编码表示。本模块中没有包使用它们;backend/native 使用自己的带类型记录。它们不检查地保存参数。

NativeBuffer

一个以 Int 表示的指针和一个长度。

pub struct NativeBuffer {
  ptr : Int
  length : Int
} derive(Eq, @debug.Debug)
pub fn NativeBuffer::new(Int, Int) -> Self
pub fn NativeBuffer::ptr(Self) -> Int
pub fn NativeBuffer::length(Self) -> Int

NativeMapRequest

输入和输出缓冲区、元素数、值类型编码、工作线程数和块大小。

pub struct NativeMapRequest {
  input : NativeBuffer
  output : NativeBuffer
  element_count : Int
  value_type : Int
  worker_count : Int
  chunk_size : Int
} derive(Eq, @debug.Debug)
pub fn NativeMapRequest::new(NativeBuffer, NativeBuffer, Int, Int, Int, Int) -> Self
pub fn NativeMapRequest::input(Self) -> NativeBuffer
pub fn NativeMapRequest::output(Self) -> NativeBuffer
pub fn NativeMapRequest::element_count(Self) -> Int
pub fn NativeMapRequest::value_type(Self) -> Int
pub fn NativeMapRequest::worker_count(Self) -> Int
pub fn NativeMapRequest::chunk_size(Self) -> Int

构造函数按声明顺序接受各字段。

NativeReduceRequest 和 NativeScanRequest

字段与 NativeMapRequest 相同,另外在值类型之后多一个归约内核编码。

pub struct NativeReduceRequest {
  input : NativeBuffer
  output : NativeBuffer
  element_count : Int
  value_type : Int
  reduction_kernel : Int
  worker_count : Int
  chunk_size : Int
} derive(Eq, @debug.Debug)
pub fn NativeReduceRequest::new(NativeBuffer, NativeBuffer, Int, Int, Int, Int, Int) -> Self
pub fn NativeReduceRequest::input(Self) -> NativeBuffer
pub fn NativeReduceRequest::output(Self) -> NativeBuffer
pub fn NativeReduceRequest::element_count(Self) -> Int
pub fn NativeReduceRequest::value_type(Self) -> Int
pub fn NativeReduceRequest::reduction_kernel(Self) -> Int
pub fn NativeReduceRequest::worker_count(Self) -> Int
pub fn NativeReduceRequest::chunk_size(Self) -> Int

pub struct NativeScanRequest {
  input : NativeBuffer
  output : NativeBuffer
  element_count : Int
  value_type : Int
  reduction_kernel : Int
  worker_count : Int
  chunk_size : Int
} derive(Eq, @debug.Debug)
pub fn NativeScanRequest::new(NativeBuffer, NativeBuffer, Int, Int, Int, Int, Int) -> Self
pub fn NativeScanRequest::input(Self) -> NativeBuffer
pub fn NativeScanRequest::output(Self) -> NativeBuffer
pub fn NativeScanRequest::element_count(Self) -> Int
pub fn NativeScanRequest::value_type(Self) -> Int
pub fn NativeScanRequest::reduction_kernel(Self) -> Int
pub fn NativeScanRequest::worker_count(Self) -> Int
pub fn NativeScanRequest::chunk_size(Self) -> Int
test "native records" {
  let buffer = @shared.NativeBuffer::new(0, 4)
  let request = @shared.NativeReduceRequest::new(buffer, buffer, 4, 0, 1, 2, 2)
  assert_eq(request.reduction_kernel(), 1)
  assert_eq(request.input().length(), 4)
}

相等性与包信息

T::equal

结构相等,作为方法提升到本包的每个类型上:BackendTarget、ExecutionMode、ExecutionPolicy、NativeBuffer、NativeMapRequest、NativeReduceRequest、NativeScanRequest、NativeStatus、OrderingGuarantee、PolicyError、PolicyIssue 和 RuntimeCapabilities。请使用 == 和 !=。

pub fn ExecutionPolicy::equal(Self, Self) -> Bool

package_name

返回 "shared"。

pub fn package_name() -> String