package Continuity; use strict; our $VERSION = '0.3'; =head1 NAME Continuity - Continuation-based web-programming framework =head1 SYNOPSIS #!/usr/bin/perl use strict; use Continuity; package Addnums; use base 'Continuity::Application'; # -------------------------- # This is the important bit. # -------------------------- sub main { my $self = shift; my $a = $self->getNum('Enter first number: '); my $b = $self->getNum('Enter second number: '); $self->disp(" Total of $a + $b is: " . ($a + $b)); # Run again! $self->main(); } sub getNum { my ($self, $msg) = @_; my $f = $self->disp(qq{ $msg
}); return $f->{'num'}; } package main; my $c = new Continuity( appname => 'Addnums', print_html_header => 1, print_form => 1, ); $c->go(); =head1 DESCRIPTION This is an alternative to existing web-programming frameworks. The purpose of a web-programming framework or toolkit is to speed and ease the development of web-based applications. They tend to aid in management of state and of control flow, often throwing in bonus hooks to common DB interfaces and templating systems. Continuity is such a framework, meant to be minimalist in nature. What sets this apart from the other frameworks is a single high-level programming abstraction which allows you to pretend your program is being continuously executing, rather than being re-started between each page display. =head1 METHODS =over =cut use CGI; use CGI::Session::ID::MD5; use Continuity::Suspension; use Continuity::Manager; my %defaults = ( print_header => 1, print_html_header => 0, print_form => 0, ); =item $c = new Continuity(appname => 'Myapp') Creates a new Continuity object, ready to manage your application's instances. =cut sub new { my $class = shift; my (@parms) = @_; my $self = { %defaults, @parms }; bless $self; return $self; } =item $c->print_headers; Prints a generic content/type and HTML header =cut sub print_headers { my ($self) = @_; if($self->{print_header}) { # Print the header print $self->{q}->header(); $self->{printed_header} = 1; } if($self->{print_html_header}) { print qq( Continuity Application - $self->{appname} ); } if($self->{print_form}) { print qq(
); } } =item $c->go; Execute (or continue executing) an application =cut sub go { my ($self) = @_; # Set up the Query and Session my $query = new CGI; $self->{q} = $query; my $cookie = $query->cookie('sid'); my $manager; my $suspender = new Continuity::Suspender; if($cookie) { $manager = $suspender->get($cookie); } else { $manager = new Continuity::Manager; $cookie = $suspender->insert($manager); } $query->cookie('sid', $cookie); # Grab the current PageID from the query, and set up the next PageID my $curpid = $query->param('pid'); my $nextpid = CGI::Session::ID::MD5::generate_id(); $self->{nextpid} = $nextpid; my $app; if($curpid) { # We were given a PID, lets pick up there $app = $manager->{$curpid}->{continuation}; if(!$app) { # Couldn't continue, so start over $app = $self->{appname}->new(); } } else { # No PID, start from the beginning $curpid = '0'; $app = $self->{appname}->new(); } $app->{query} = $query; $app->{curpid} = $curpid; $app->{nextpid} = $nextpid; $app->{on_destroy} = sub { $_->insert($manager) }; # Magical Contize catch-up $app->resume(); $self->print_headers(); # And last but not least, start the application! $app->main(); } =item $c->save; Save the suspended application =cut sub save { my $self = shift; if ($self->{s}) { $self->{s}->param($self->{newpid}, { 'page' => $self->{app}, 'timestamp' => time }); $self->{s}->flush(); } } =back =head1 BUGS/LIMITATIONS This module uses the L module to use fake continuations, and thus comes with all the limitations therein. =head1 SEE ALSO L, L =head1 AUTHOR Brock Wilcox http://thelackthereof.org/ =head1 COPYRIGHT Copyright (c) 2004 Brock Wilcox . All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1;