2026-06-08: Fuzion June Update
Last month brought Fuzion a little closer to providing fearless concurrency by restricting concurrent accesses to mutate effects that a thread-safe. Feeze now shows wake up between threads, helping understand what is happening.
- General
- Base library
-
New library features
-
add
fuzion.runtime.traceto addDTRACE_PROBEs to Fuzion code that can be seen by Linux performance monitoring tools like feeze (#7094, #7115, #7102) -
Added fearless concurrency support by adding thread-awareness to
mutateeffect as follows: A new featuremutate.exclusiveensures that code that modifies mutable fields is protected from races of concurrent modifications by other threads. We can hence create code like# an integer counter that is modified using mutate effect M counter(M type : mutate) is # the current value private val := M.env.new 0 # increment the value by 1 increment => # exclusive to permit concurrent increments M.env.exclusive ()-> val <- val+1 # read the current value read => # exclusive to forbib reordering in case of concurrent increments M.env.exclusive ()-> val.getA normalmutatetype may not be shared between threads, soexclusivedoes not perform any expensive thread synchronization. We can usecounteras follows:# declare and instate our own mutate effect my_mutate : mutate is my_mutate ! ()-> # create counter using my_mutate effect cnt := counter my_mutate for i in 1 .. 10000 do if i %% 7 cnt.increment say "{cnt.read} multiplies of 7 found"However, trying to optimize this code using parallel threads as followsmy_mutate ! ()-> cnt := counter my_mutate threads := array 10 n-> concur.threads.env.spawn ()-> b := n*1000 for i in b+1 .. b+1000 do if i %% 7 cnt.increment threads.for_each t->t.join say "{cnt.read} multiplies of 7 found"will result in an error sincemy_mutateis not thread-safe. We can fix this with a single line-changemy_mutate : concur.blocking_mutate isWhich will use a mutex to make accesses exclusive and hence thread-safe (#7030), (#7067). -
Added
mutate.waitandmutate.exclusive_whento wait for a condition before entering an exclusive section (#7070)This can be used in the previous example to add a feature to
counterthat waits for the counter to reach a given valuen:wait_for(n i32) => M.env.exclusive_when ()->val>=n ()->valThis code blocks until the given conditionval>=nis met and then exclusively returns the value by running the lambda()->val.This can now be used, e.g., by a thread that reports about the current progress
progress := concur.threads.env.spawn ()-> for prev := 0, next next := cnt.wait_for prev+1 while next < 1400 say "found $next"Unlike Java'swait/notify/notifyAll, the notification here happens automatically and wake ups are only done if the condition is actually met. -
Added a thread-safe ring buffer
container.Ring_Bufferusingmutate.exclusiveas part of the mutate changes, removedCircular_Buffer(#7030, #7067 #7057, #7058) -
add
defereffect to add code to be executed when the effect is de-instated (#7041) implement
switch.type.return(#7055)bool: add
as_tritfeature (#7097)time/histogram: make
histogram_mutatepublic for use in other threads (#7127)
-
-
Changed library features
adjust visibility of
handles2to fix flang_dev example (#7103)list: redeffinitetoyesif cycled list is empty (#7092)fix
stateeffect that did not work when instated usinginfix !(#7063)made
array2andarray3equatableandhashable(#7095)Use
less_than_or_equalinstead ofless_or_equal(#7083)-
Use map to
orderabletype instead of comparator for sorting (#7110)fruits := ["kiwi", "apple", "pear", "peach", "banana"] say <| fruits.sort_by (a,b -> a.byte_count <= b.byte_count)we can now usefruits := ["kiwi", "apple", "pear", "peach", "banana"] say <| fruits.sort_by (.byte_count) Sequence: stricter postcondition forcycle(#7105)
-
Removed library features
remove
effect.type.return(#7038)
-
- Other library modules
- Front end
Call.TRUE/FALSE, remove redundant overrides (#7076)fix check-condition failure, due to failure in resolving select-call (#7114)
Fix underline range for interpolated String literals in error msg (#7085)
setFunctionReturnTypein loop only whensuccessBlockis present (#7113)change
checkLegalThisTypeto also check outer for legality (#7080)cleanup
handDownThroughInheritsCalls(#7042)fix calling post-condition of redefined feature (#7052)
normalize SourceFile paths (#7096)
- Monomorphization/DFA
dfa: setField, check that written value matches expected clazz (#7017)
- Middle end
- Runtime System
include/posix:
fzE_thread_create: set default policy and priority (#7086)
- Backends
- Windows
win: implement
fzE_thread_current(#7054)
- Tests
tests: wolfssl, uncomment now working code (#7093)
- Build Infrastructure
- Documentation
Modified Jitter to run on another thread with high priority. (#7040)
- Fuzion Webserver
src/run: adjust how mutate is instated in thread pool (#414)
- Feeze
-
The size of the recorded data was reduce by a factor of approximately 4 by shrinking the size of one recorded event from 64 bytes down to 16 bytes. This permits longer records with the same buffer size (commit #ce21589, commit #52c55d8).
-
Support
SCHED_WAKINGevents and show arrows from the thread that caused the wake up (commit #fa4ff42). This illustrates quite nicely how thread interactions propagate:
-
Support display of user events in Fuzion code added via calls like
fuzion.runtime.trace "Hello"(commit #070101b)
-
Cheers,
--The Fuzion Team.