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