| |||||
The thETA languageCopyright © Stephen Sykes, 2002. Welcome to thETAthETA stands for 'threaded ETA'. I describe here some extensions to the ETA language that give it fully-fledged multi-threading capability (well, kind of!). What's more, I have added this capability without colouring the purity of the language by increasing the number of significant instruction characters. And even more remarkably, the thETA interpreter is fully backward compatible - it will function perfectly on plain old ETA programs. I have done this by utilising previously illegal instruction usages, such as divide by zero. There are three such instructions, described below:
About parentsEach thread is started by one parent. When a thread dies, its children are passed to its parent. If its parent is dead, then they are passed to its parent's parent, and so on. So a thread always has a parent that can collect it. In my implementation, calling 'O' actually causes all children threads that are dead to be cleared up - but this is really an implementation detail - you shouldn't care that there are loads of dead threads lying around making the place look untidy. Program endA thETA program will not terminate until all its threads are dead. To achieve this, my implementation needs to poll the threads to check their status. It does this once per second (if there are no higher priority threads running) - so there may be a delay of up to one second before the thETA interpreter exits. ExampleHere is a short example program to demonstrate the use of thETA
* Knuth TeX #1 BABY BAT: 50
NURTURES nude: what? 1nternnet? BABY BAT: dec and goto 3 if nz, else goto 5
An east 1nternaet! BABY BAT: fork to line 4, return to 2
Nude hunt waxes bluntly, temptingly; Czech pussy blundered. BABY BAT: tx to 8 if not 9, else return val
* Knuth TeX #2 BABY BAT: 50
NURTURES new hun: the TNT DECnet. BABY BAT: dec and goto 7 if nz, else exit
Unencrypted, scorned, husks. Gunmen ssess1on tense, but -- BABY BAT: wait and print value, goto 6
Burns superbly!
NURTURES new hunt: abject
Sneer! BABY BAT: return val
The program forks 50 threads, and waits for 50 to return one at a time. They each loop for a bit, then return a number from 0 - 49, which then gets added to 48 (ascii for zero) and printed. The exception is the thread for character '9', which waits for user input before returning. This demonstrates the asynchronous nature of the threads - all the others return first. InterptreterThis is a modified version of my Ruby ETA interpreter. The modifications are quite small in size, mostly due to my being able to utilise Ruby's built in thread mechanism. You can download the thETA interpreter here. Note that using Ruby 1.6.4 under Windows I suffered frequent crashes when running multiple threads. I recommend Ruby 1.6.5 or later. thETA builderHere is a modified version of the ETA builder that supports threads. There are three new instructions in thETA builder - forkif, threadreturn and threadcollect. Here is a sample program that shows their usage:
# factorise any number below 23
require 'theta-rb'
def tryit(n,x)
forkif (true) {
forkif(true) { # fork yet another thread just to prove it works
eif (n % x == 0) {
threadreturn(x)
}
eelse {
threadreturn(0)
}
}
threadcollect(1)
threadreturn($threadResults[0]) # the global $threadResults is an EtaArray
} # with the return values in - currently limited
end # to a max of 20 - see theta-rb.rb
eprint "Enter number to be factorised: "
n = EtaInt.new(input_number)
eprint "Forking threads...\n"
tryit(n,2)
tryit(n,3)
tryit(n,5)
tryit(n,7)
tryit(n,11)
tryit(n,13)
tryit(n,17)
tryit(n,19)
eprint "Collecting threads...\n"
threadcollect(8)
8.times {|z|
eif ($threadResults[z] != 0) {
eprint $threadResults[z], "\n"
}
}
eexit
finish
And if that isn't enough for you, try this program, which is a nice demonstration of the concurrency you can achieve. This one seems to work better on a unix system rather than under windows, where oddly the output thread seems to block once you have started to type input - it resumes once you have pressed return.
# continuously prints a number and accepts commands 'u'
# or 'd' to increase or decrease the number
# just typing return exits
require 'theta-rb.rb'
x = EtaInt.new
z = EtaInt.new
forkif(true) {
threadreturn(input)
}
ewhile(true) {
forkif(z == 0) {
eprint x
threadreturn(0)
}
forkif(z != 0) {
threadreturn(input)
}
threadcollect(1)
z.val = $threadResults[0]
eif (z > 0) {
eif (z > ?d) {
x.val = x + 1
}
eelse {
x.val = x - 1
}
eif (z == ?\n) {
eexit
}
z.val = input # chomp newline
}
}
finish
Download the compiled thETA code for this here. AcknowledgementsThe name 'thETA' was coined by Mike Taylor, who also beautified the first thETA example program above. The idea of adding threads to ETA was due to a fine curry at the Elahee Restaurant, 218a Middle Lane, London, N8. Bring your own alcohol.
S.D.Sykes Feb 2002 |