1// Copyright 2025 International Digital Economy Academy
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15///|
16type Mutex
17
18///|
19extern "c" fn uv_mutex_make() -> type Mutex
Mutex = "moonbit_uv_mutex_make"
20
21///|
22extern "c" fn uv_mutex_init(mutex : type Mutex
Mutex) -> Int
Int = "moonbit_uv_mutex_init"
23
24///|
25pub fn type Mutex
Mutex::() -> Mutex raise Errno
new() -> type Mutex
Mutex raise type! Errno Status
Errno {
26 let Mutex
mutex = () -> Mutex
uv_mutex_make()
27 let Int
status = (mutex : Mutex) -> Int
uv_mutex_init(Mutex
mutex)
28 if Int
status (x : Int, y : Int) -> Bool
!= 0 {
29 raise type! Errno Status
Errno::(errno : Int) -> Errno
of_int(Int
status)
30 }
31 return Mutex
mutex
32}
33
34///|
35extern "c" fn uv_mutex_copy(mutex : type Mutex
Mutex, other : type Mutex
Mutex) = "moonbit_uv_mutex_copy"
36
37///|
38extern "c" fn uv_mutex_lock(mutex : type Mutex
Mutex) = "moonbit_uv_mutex_lock"
39
40///|
41extern "c" fn uv_mutex_trylock(mutex : type Mutex
Mutex) -> Int
Int = "moonbit_uv_mutex_trylock"
42
43///|
44extern "c" fn uv_mutex_unlock(mutex : type Mutex
Mutex) = "moonbit_uv_mutex_unlock"
45
46///|
47pub fn type Mutex
Mutex::(self : Mutex) -> Unit
lock(Mutex
self : type Mutex
Mutex) -> Unit
Unit {
48 (mutex : Mutex) -> Unit
uv_mutex_lock(Mutex
self)
49}
50
51///|
52pub fn type Mutex
Mutex::(self : Mutex) -> Unit raise Errno
trylock(Mutex
self : type Mutex
Mutex) -> Unit
Unit raise type! Errno Status
Errno {
53 let Int
status = (mutex : Mutex) -> Int
uv_mutex_trylock(Mutex
self)
54 if Int
status (self_ : Int, other : Int) -> Bool
< 0 {
55 raise type! Errno Status
Errno::(errno : Int) -> Errno
of_int(Int
status)
56 }
57}
58
59///|
60pub fn type Mutex
Mutex::(self : Mutex) -> Unit
unlock(Mutex
self : type Mutex
Mutex) -> Unit
Unit {
61 (mutex : Mutex) -> Unit
uv_mutex_unlock(Mutex
self)
62}
63
64///|
65/// Shares an object safely between threads.
66///
67/// In MoonBit, the default reference counting (RC) for objects is not atomic,
68/// so it is not safe to share most objects directly between threads.
69///
70/// To enable safe sharing, we use a separate atomic reference counter (ARC)
71/// stored alongside the actual object data. The MoonBit object itself is
72/// managed by non-atomic RC, but the shared payload is managed by ARC.
73///
74/// When you want to share an object:
75/// - The MoonBit object holds a pointer to a heap-allocated block containing
76/// both the ARC and the payload (e.g., a mutex or thread handle).
77/// - Copying the MoonBit object only copies the pointer; the ARC is incremented
78/// atomically (guarded by a mutex if needed).
79/// - When a copy is dropped, the ARC is decremented atomically. When ARC
80/// reaches zero, the payload is freed.
81///
82/// Example: `uv_thread_t` stores an `arc` field and a `uv_mutex_t` object in a
83/// heap-allocated block. All increments/decrements of `arc` are protected by
84/// the mutex to ensure thread safety.
85///
86/// Diagram:
87///
88/// ```plaintext
89/// (thread 0) (thread 1)
90/// +--------+ +--------+
91/// | rc (M) | | rc (M) |
92/// +--------+ +--------+
93/// \ /
94/// \---> +---------+ <---/
95/// | arc (F) |
96/// +---------+
97/// | mutex |
98/// +---------+
99/// | payload |
100/// +----+----+
101/// ```
102///
103/// The `Share` trait provides a `share` method to allow implementor of this
104/// trait to create a new MoonBit object pointing to the same shared payload,
105/// incrementing the ARC safely.
106pub trait trait Share {
share(Self) -> Self
}
Shares an object safely between threads.
In MoonBit, the default reference counting (RC) for objects is not atomic,
so it is not safe to share most objects directly between threads.
To enable safe sharing, we use a separate atomic reference counter (ARC)
stored alongside the actual object data. The MoonBit object itself is
managed by non-atomic RC, but the shared payload is managed by ARC.
When you want to share an object:
- The MoonBit object holds a pointer to a heap-allocated block containing
both the ARC and the payload (e.g., a mutex or thread handle).
- Copying the MoonBit object only copies the pointer; the ARC is incremented
atomically (guarded by a mutex if needed).
- When a copy is dropped, the ARC is decremented atomically. When ARC
reaches zero, the payload is freed.
Example: uv_thread_t stores an arc field and a uv_mutex_t object in a
heap-allocated block. All increments/decrements of arc are protected by
the mutex to ensure thread safety.
Diagram:
(thread 0) (thread 1)
+--------+ +--------+
| rc (M) | | rc (M) |
+--------+ +--------+
\ /
\---> +---------+ <---/
| arc (F) |
+---------+
| mutex |
+---------+
| payload |
+----+----+
The Share trait provides a share method to allow implementor of this
trait to create a new MoonBit object pointing to the same shared payload,
incrementing the ARC safely.
Share {
107 (Self) -> Self
share(type parameter Self
Self) -> type parameter Self
Self
108}
109
110///|
111pub impl trait Share {
share(Self) -> Self
}
Shares an object safely between threads.
In MoonBit, the default reference counting (RC) for objects is not atomic,
so it is not safe to share most objects directly between threads.
To enable safe sharing, we use a separate atomic reference counter (ARC)
stored alongside the actual object data. The MoonBit object itself is
managed by non-atomic RC, but the shared payload is managed by ARC.
When you want to share an object:
- The MoonBit object holds a pointer to a heap-allocated block containing
both the ARC and the payload (e.g., a mutex or thread handle).
- Copying the MoonBit object only copies the pointer; the ARC is incremented
atomically (guarded by a mutex if needed).
- When a copy is dropped, the ARC is decremented atomically. When ARC
reaches zero, the payload is freed.
Example: uv_thread_t stores an arc field and a uv_mutex_t object in a
heap-allocated block. All increments/decrements of arc are protected by
the mutex to ensure thread safety.
Diagram:
(thread 0) (thread 1)
+--------+ +--------+
| rc (M) | | rc (M) |
+--------+ +--------+
\ /
\---> +---------+ <---/
| arc (F) |
+---------+
| mutex |
+---------+
| payload |
+----+----+
The Share trait provides a share method to allow implementor of this
trait to create a new MoonBit object pointing to the same shared payload,
incrementing the ARC safely.
Share for type Mutex
Mutex with (self : Mutex) -> Mutex
share(Mutex
self : type Mutex
Mutex) -> type Mutex
Mutex {
112 let Mutex
other = () -> Mutex
uv_mutex_make()
113 (mutex : Mutex, other : Mutex) -> Unit
uv_mutex_copy(Mutex
self, Mutex
other)
114 return Mutex
other
115}
116