Ruby/Python Continuations: Turning a block callback into a read()-method?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Robert

    #1

    Ruby/Python Continuations: Turning a block callback into a read()-method?

    After failing on a yield/iterator-continuation problem in Python (see
    below) I tried the Ruby (1.8.2) language first time on that construct:
    The example tries to convert a block callback interface
    (Net::FTP.retrb inary) into a read()-like iterator function in order to
    virtualize the existing FTP class as kind of file system. 4 bytes max
    per read in this first simple test below. But it fails on the second
    continuation with ThreadError after this second continuation really
    executing!? Any ideas how to make this work/correct?

    (The question is not about the specific FTP example as it - e.g. about a
    rewrite of FTP/retrbinary or use of OS tricks, real threads with polling
    etc... - but about the continuation language trick to get the execution
    flow right in order to turn any callback interface into an "enslaved
    callable iterator". Python can do such things in simple situations with
    yield-generator functions/iter.next()... But Python obviously fails by a
    hair when there is a function-context barrier for "yield". Ruby's
    block-yield-mechanism seems to not at all have the power of real
    generator-continuation as in Python, but in principle only to be that
    what a normal callback would be in Python. Yet "callcc" seemes to be
    promising - I thought so far :-( )

    === Ruby callcc Pattern : execution fails with ThreadError!? ===========
    require 'net/ftp'
    module Net

    class FTPFile
    def initialize(ftp, path)
    @ftp = ftp
    @path=path
    @flag=true
    @iter=nil
    end
    def read
    if @iter
    puts "@iter.call "
    @iter.call
    else
    puts "RETR "+@path
    @ftp.retrbinary ("RETR "+@path,4) do |block|
    print "CALLBACK ",block,"\n "
    callcc{|@iter| @flag=true}
    if @flag
    @flag=false
    return block
    end
    end
    end
    end
    end

    end

    ftp = Net::FTP.new("l ocalhost",'user ','pass')
    ff = Net::FTPFile.ne w(ftp,'data.txt ')
    puts ff.read()
    puts ff.read()

    === Output/Error ====

    vs:~/test$ ruby ftpfile.rb
    RETR data.txt
    CALLBACK robe
    robe
    @iter.call
    CALLBACK rt

    /usr/lib/ruby/1.8/monitor.rb:259: in `mon_check_owne r': current thread
    not owner (ThreadError)
    from /usr/lib/ruby/1.8/monitor.rb:211: in `mon_exit'
    from /usr/lib/ruby/1.8/monitor.rb:231: in `synchronize'
    from /usr/lib/ruby/1.8/net/ftp.rb:399:in `retrbinary'
    from ftpfile.rb:17:i n `read'
    from ftpfile.rb:33
    vs:~/test$

    === Python Pattern : I cannot write down the idea because of a barrier ===

    #### I tried a pattern like:
    ....
    def open(self,ftppa th,mode='rb'):
    class FTPFile:
    ...
    def iter_retr()
    ...
    def callback(blk):
    how-to-yield-from-here-as-iter_retr blk???
    self.ftp.retrbi nary("RETR %s" % self.relpath,ca llback)
    def read(self, bytes=-1):
    ...
    self.buf+=self. iter.next()
    ...
    ...
    ....

    =====


    Robert

Working...