Concurrency Directives
Concurrency Directives start with pipe (|)
.
Why concurrency ?¶
Concurrency is a powerful paradigm for two main reasons:
-
Performance: It allows unrelated computations to execute simultaneously, optimizing resource utilization.
-
Reliability: Processes can be isolated, preventing failures in one process from propagating to others.
U concurrency model¶
U enables concurrent task at various levels, prioritizing reliability. The levels of concurrency in U are structured as follows:
- User Level: Includes coroutines and lightweight processes such as user-space threads and fibers.
- Host Level: Involves OS threads.
- Hardware Level: Covers interrupts.
Applications relying solely on hardware-level concurrency are typically not considered reliable or portable. They are commonly utilized in specialized environments like embedded systems or high-performance domains such as finance and avionics.
Coroutines¶
Coroutines encode a state as a recursive function managed by the Scheduler.
:key_value_db : {|
# '\|' <=> function to initialize coroutines
\| : {
# '\|/' <=> when Task starts
\|/ {
# 'db' is a map shared by coroutines
:db : [< :name: 'Bob', :age: 20 >]
# Call <main_loop> with <db>
main_loop db
}
}
main_loop : {: db
\|:.. # By default, define all messages: Get, Put
# '\|?' <=> Match message types: Get or Put
\|? :|Get, {: key, sender
sender.|< @:json db[key]
\|^ db # Recurse to <main_loop>
}
\|? :|Put, {: key, value
db[key] := value
sender.|< @:json :|Ok
\|^ db # Recurse to <main_loop>
}
}
}
:key_value_db : {|
\|/ [< :name: 'Bob', :age: 20 >], {|?: db
:-^ Get, :>: key, sender ::> \|< sender, @:json db[key]
:-^ Put, :>: key, value, sender ::> db[key] = value; \|< sender, :|Ok
}
}
Threads¶
Most common concurrency functions are available in the target language or OS:
# Start 10 workers
:w : :|.starts 10, :workers ...
# Or
:w : :|.workpool 10
\< w.:|idle-workers
# Prints a list of idle-workers
Asynchronous Expressions¶
Work in progress...
Interrupts¶
Work in progress...