NeonNeon supports concurrent programming via processes (lightweight threads). Since Neon runs on platforms without true multitasking (like TI-EZ80), it simulates concurrency by interleaving processes.
parallel OperatorLaunch a function in a new process using parallel.
promise = parallel functionName(arg1, arg2, ...)
function slowTask(n) do
# Simulate a slow computation
total = 0
for (i, 0, n) do
total += i
end
return (total)
end
# Launch two tasks in parallel
promise1 = parallel slowTask(1000)
promise2 = parallel slowTask(2000)
# At this point, both tasks are running in the background
# The promises are of type "Promise"
# Wait for results (passive waiting)
await(promise1 != None and promise2 != None)
# Now the promises have resolved to their return values
print(promise1) # → 499500 (sum of 0..999)
print(promise2) # → 1999000 (sum of 0..1999)
"Promise".None, the Promise becomes None.function double(x) do
return (x * 2)
end
p1 = parallel double(5) # Promise
p2 = p1 # Another reference to the same Promise
await(p1 != None)
print(p1) # → 10
print(p2) # → 10 (also updated)
awaitwhile (not condition) do pass end.await(condition) to yield control to other processes.function worker(id) do
print("Worker " + str(id) + " started")
# Simulate work
for (i, 0, 100000) do
pass
end
print("Worker " + str(id) + " finished")
return (id * 10)
end
# Launch workers
p1 = parallel worker(1)
p2 = parallel worker(2)
# Passively wait for both to finish
await(p1 != None and p2 != None)
print("Both workers done!")
print("Results: " + str(p1) + ", " + str(p2))
counter = 0
function incrementCounter() do
local(counter) # Makes counter local to this process
counter += 1
print("Counter in process: " + str(counter))
end
# Launch 3 processes
parallel incrementCounter()
parallel incrementCounter()
parallel incrementCounter()
# Wait for all to finish
await(True) # Simple way to yield (not ideal, but works here)
# Global counter remains unchanged
print("Global counter: " + str(counter)) # → 0
Prevent race conditions by making a block of code atomic (uninterruptible).
atomic
# Code that must run without interruption
end
Not thread-safe function:
function consumer(data) do
while (len(data) > 0) do
# Here, data[0] is possibly no longer accessible since another thread could have consumed this item
consume(data[0])
data.remove(0)
end
end
thread-safe function using atomic blocks:
function consumer(data) do
while (len(data) > 0) do
atomic
if (len(data) > 0) then
item = data[0]
data.remove(0)
end
end
consume(item)
end
end
neon_interp_yield internally.ATOMIC_TIME (default: 1500).setAtomicTime(n) to change how often processes switch.setAtomicTime(100) # Switch processes every 100 yield calls