Re: Sending files with E?

"Jimmy Wylie Jr." <[email protected]>
Newsgroups gmane.comp.lang.e.general
Message-ID <[email protected]>
> 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

_______________________________________________
e-lang mailing list
[email protected]
http://www.eros-os.org/mailman/listinfo/e-lang
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.