You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+18-83Lines changed: 18 additions & 83 deletions
Original file line number
Diff line number
Diff line change
@@ -13,7 +13,6 @@ This proposal introduces four (4) logical features:
13
13
-[**Structs**](#structs), or unshared structs, which are fixed-layout objects. They behave like `class` instances, with more restrictions that are beneficial for optimizations and analysis.
14
14
-[**Shared Structs**](#shared-structs), which are further restricted structs that can be shared and accessed in parallel by multiple agents. They enable shared memory multithreading.
15
15
-[**Mutex and Condition**](#mutex-and-condition), which are higher level abstractions for synchronizing access to shared memory.
16
-
-[**Unsafe Blocks**](#unsafe-blocks), which are syntactic guardrails to lexically scope where racy accesses to shared structs are allowed.
17
16
18
17
This proposal is intended to be minimal, but still useful by itself, without follow-up proposals.
19
18
@@ -99,11 +98,9 @@ shared struct SharedBox {
99
98
let sharedBox =newSharedBox();
100
99
let sharedBox2 =newSharedBox();
101
100
102
-
unsafe {
103
-
sharedBox.x=42; // x is declared and rhs is primitive
104
-
sharedBox.x= sharedBox2; // x is declared and rhs is shared
105
-
assertThrows(() => { sharedBox.x= {}; }) // rhs is not a shared struct
106
-
}
101
+
sharedBox.x=42; // x is declared and rhs is primitive
102
+
sharedBox.x= sharedBox2; // x is declared and rhs is shared
103
+
assertThrows(() => { sharedBox.x= {}; }) // rhs is not a shared struct
107
104
108
105
// can programmatically test if a value can be shared
Correct multithreaded programs are difficult to write, because races are subtle and difficult to reason about. To decrease the likelihood of incorrect programs, accesses to shared structs are only allowed when lexically contained with in an `unsafe { }` block. Note that SharedArrayBuffer access remains allowed in all contexts for backwards compatibilty.
380
-
381
-
The `unsafe` keyword is a clear signal of intent that a developer is choosing to work with shared memory multithreaded code. The presence of an `unsafe` block is an indication to code reviewers that special care must be taken during review. It also is acts as a syntactic marker that future tooling (linters, type checkers, etc.) could use to identify data races.
382
-
383
-
An `unsafe {}` block is otherwise treated the same as a normal Block. Its only distinction is that it explicitly labels code within the block as potentially containing non-thread-safe (e.g., "unsafe") code. The general expectation is that any thread safety concerns should be addressed by the developer as control flow exits the unsafe block. For example, you could utilize using to synchronize access to a shared struct via a lock:
Here, when the control enters the `unsafe` block, we allocate a lock against the provided mutex via a `using` declaration. As control exits the `unsafe` block, the lock tracked by using is released.
410
-
411
-
#### Lexically Scoped
412
-
413
-
The `unsafe` keyword is a syntactic marker that applies to lexically scoped reads and writes of the fields of a shared struct instance. Within an `unsafe` block, any lexically scoped accesses are permitted, even if they are nested within another function declared in the same block. This special lexical context shares some surface level similarities with the lexical scoping rules for private names, or the runtime semantics of "use strict".
414
-
415
-
Since `unsafe` is lexically scoped, it does not carry over to the invocation of functions declared outside of an `unsafe` context:
416
-
417
-
```javascript
418
-
functionincrement(ctr) {
419
-
ctr.value++; // error due to illegal read/write of `ctr.value` outside of `unsafe`
420
-
}
421
-
unsafe {
422
-
constctr=newCounter();
423
-
increment(ctr);
424
-
}
425
-
```
426
-
427
-
Thread-safe code may execute `unsafe` code without restriction, and `unsafe` code may do likewise. As `unsafe` already indicates a transition boundary between thread-safe and `unsafe` code, there is no need to declare all calling code `unsafe` as you might need to do for `async`/`await`. The `unsafe` keyword itself does not entail any implicit synchronization or coordination as that would be in opposition to our performance goals. Instead, the onus is on developers to be cognizant of thread safety concerns when they define an `unsafe` block. As such, a developer can choose the coordination mechanism that best suits the needs of their application, be that a `Mutex`, a lock-free concurrent deque, etc.
0 commit comments