[e-lang] Sending files with E?
Jimmy Wylie Jr.
jwylie at uno.edu
Mon Sep 29 18:08:33 CDT 2008
> The overflow is likely being caused because the 'copy' function is tail
> recursive, but E-on-Java doesn't implement tail call optimisation.
Yeah, I figured that's what was going on.. I should have realized that.
Leftover, Scheme/Haskell habits, I guess.
> You can avoid the stack overflow (I think) by changing the (implicit)
> immediate call ('.') to a send ('<-') instead, e.g.
>
> copy <- run(dispenser, output, avail)
>
> This will have the subsequent evaluation of 'copy' occur in a separate
> turn. Rather than requiring another stack frame to evaluate it
> immediately, it will be evaluated later on. Now sending an N byte file
> requires a stack of some constant size -- i.e. a stack size of O(1).
I implemented the change, this fixed the problem... sort of. If I send a
big enough file, I then get a heap overflow error (OutOfMemory Error - The
program writes about 4kb before overflowing). I think after the number of
available bytes has been returned, I can divide that up into smaller chunks,
and call copy that many times, reusing the same output stream. I'm not
quite sure how to implement this yet, because I wouldn't want to call copy
again until I'm sure the previous copy has finished. Any suggestions?
> You could create the promise before the first invocation of 'copy' and
> pass the promise through to the call to 'copy'. On its last invocation
> (i.e. if 'copy' is not invoking itself again), it simply resolves the
> promise it was passed, to indicate that the transfer is complete.
> Otherwise (on a recursive call), it passes the promise to the recursive
> call without resolving it. Would that work?
I tried this, but it turns out that the promise for the entire copy
resolves before the charVow promises resolve and write to the outputStream.
Instead, I changed the code this way:
def copyHelper(dispenser, output, available, resolver) {
traceline("copying")
var avail := available
traceline("this copy is called with " + available)
if(avail > 0) {
def charVow := dispenser <- read()
when(charVow) -> {
traceline("byte: " + available + " is resolved")
output.write(charVow)
if(available == 1){
traceline("LAST BYTE WRITTEN!!!")
resolver.resolve(1)
}
} catch problem {
println("something went horribly wrong")
traceline(problem)
}
avail := avail - 1
copyHelper <- run(dispenser,output,avail, resolver)
} else {
return
}
}
def copy(dispenser, output, available) {
def [copyPromise, copyResolver] := Ref.promise()
copyHelper(dispenser, output, available, copyResolver)
return copyPromise
}
I figured that the last byte written would be the one associated with the
function call where available == 1. So I added a check for that in the
when-catch, so the promise would resolve after the last byte. Turns out
this worked.
Thanks again for your help,
Jimmy Wylie
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.eros-os.org/pipermail/e-lang/attachments/20080929/d2430338/attachment.html
More information about the e-lang
mailing list