Continuation in web (Seaside clone)

A

Alexey Petrushin

Hello!

IN SHORT (by some example):

There is a web application, and two 'pages' - 'View' and 'Editor'. And
when i press 'Edit' button on the 'View' it should:
- Freeze current execution (callcc {bla-bla})
- Give control to 'Editor'
- User fill data in 'Editor'
- 'Editor' return entered data and control back to 'List'
(continuation.call data)
- Friezed execution resumes

THE PROBLEM:
I implement this the same way as in Seaside, and it seems to should
works, but it throws:
"Caught RuntimeError: continuation called across threads"

Probably, because WebServer runs each request in a new thread. Do you
hawe any idea how this can be solved?

Thanks!

DETAILS:
In pseudo code:

class Editor < Form
def initialize
data = TextField.new self, ''
FormButton.new(self, 'Save') {answer data.text}
end
end

class View < Panel
def initialize editor
view= Label.new self, 'Some initial value ...'
Button.new(self, 'Edit') {view.text = call(editor)}
end
end

class MySuperApp < Panel
def initialize
View.new(self, Editor.new)
end
end
 
A

Alexey Petrushin

Done! :)
I founded an ugly solution (closures instead of continuation). It works,
looks like:

All other components are the same as earlier, i just a little changed
the 'View'.
To complete edition user should 3 times enter something in Wizzard-like
dialogs.

WITH CONTINUATION IT SHOULD LOOKS LIKE:
class View < Panel
def initialize editor
view= Label.new self, 'Value'
Button.new(self, 'Edit') {
first = call(editor)
second = call(editor)
third = call(editor)
view.text = first+second+third
}
end
end

WITH MY UGLY SOLUTION IT LOOKS:
class View < Panel
def initialize editor
view= Label.new self, 'Value'
Button.new(self, 'Edit') {
call(editor) { |v|
first = v
call(editor){ |v|
second = v
call(editor){ |v|
third = v
view.text = first+second+third
}
}
}
}
end
end
 
J

James Britt

Alexey said:
Done! :)
I founded an ugly solution (closures instead of continuation). It works,
looks like:

Have you looked at Michael Neumann's "Wee" Web framework?
 
K

khaines

THE PROBLEM:
I implement this the same way as in Seaside, and it seems to should
works, but it throws:

Just FYI, but there is Borges, http://borges.rubyforge.org/, which was
based on Seaside 2.

However, continuations in Ruby tend to leak RAM, and tend to be slow. You
can get 80% of the love with none of the pain by using techniques not
based on continuations.


Kirk Haines
 
E

Eric Hodel

Just FYI, but there is Borges, http://borges.rubyforge.org/, which
was based on Seaside 2.

However, continuations in Ruby tend to leak RAM, and tend to be
slow. You can get 80% of the love with none of the pain by using
techniques not based on continuations.

Yes, as the author of Borges, try Wee, as mentioned elsewhere. Wee
actually works.
 
A

Alexey Petrushin

As i understood:
- It's better not to use continuation, especially in multi threads.
- There is a way to imitate it, like code sample below:

...
call MessageBox.new("Delete?"){|response|
if response
call MessageBox.new("Are you sure?"){|response2|
delete if response2
}
end
}
...

Thanks for advices! :)
 
A

Alexey Petrushin

Wee and Borges frameworks.

Yes i goggled it about 3 months ago but sadly don't found any
ready-to-show samples or sites running on these frameworks and go
further. :(

Yesterday i investigated it in more details, looks cool, and my solution
looks very close to it, but now i almost finished my prototype :)

Main difference is in HTML builder(renderer?), i use Swing(Java) like
API (i.e. no HTML/HTTP at all, just Labels, Panels, Buttons,
LayoutManagers and so on).
 
M

Michael Neumann

Alexey said:
As i understood:
- It's better not to use continuation, especially in multi threads.
- There is a way to imitate it, like code sample below:

...
call MessageBox.new("Delete?"){|response|
if response
call MessageBox.new("Are you sure?"){|response2|
delete if response2
}
end
}
...

Correct. Wee uses one thread per session (i.e. user) and keeps this
thread alive. This is required at least when using continuations,
because you can't continue a continuation from another thread.

With continuations, you could write it as:

delete if call(MessageBox.new("Delete?")) and
call(MessageBox.new("Are you sure?")

That is a lot clearer!

But, continuations have some downsides (that applies to
Matz' Ruby interpreter):

* You can't marshal them.
* Single-threaded (per session/user).
* They might leak memory.
Thanks for advices! :)

You're welcome!

Regards,

Michael
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top