Re: OO theory question
by Abigail-II (Bishop) on Jun 09, 2004 at 15:00 UTC
|
Well, you basically will need somewhere in your program a piece where all the irc connections work together (unless you want to give each irc connection its own separate thread or process) - and that's called the select loop. OO is nice for modelling data, but it doesn't do the program flow for you. Deep down, the heart of your program will be a simple loop:
while true
do is there anything to read or write on my IRC connections?
if so, read or write,
else maybe do something else
done
There are several modules out there that will help you implement it - but you'll need the loop.
Abigail | [reply] [d/l] |
|
|
basically option 1 then. in that context, would it make more sense to have the ->new method do a simple bless, and implement another method, perhaps ->connect, that creates connections as properties of the object returned by ->new?
| [reply] |
|
|
IMO, a constructor should only construct, and not do anything else. Otherwise, your subclassing classes will be forced to call your constructor, and that's a major pain in the ass if the subclass wants to do MI.
Abigail
| [reply] |
|
|
|
|
Re: OO theory question
by bart (Canon) on Jun 09, 2004 at 14:51 UTC
|
This sounds like a job for POE, to me. | [reply] |
|
|
I used to use POE, in fact. Problem is that I like to do things by hand. It's not that I intend to write the next greatest thing or anything, P::C::I absolutely rocks, but I just like to write things myself so I know what's happening under the hood.
| [reply] |
|
|
Welp nothing stopping you from making your own P::C::I to handle the irc interface. Just use POE for the multitasking.
| [reply] |
Re: OO theory question
by stvn (Monsignor) on Jun 09, 2004 at 21:03 UTC
|
Of your 3 options, I would throw out option 2 as it places to much responsibility on your calling script IMO. As for the other options, its a matter of taste.
Option 1 is similar to the select-style of doing IO. The idea of select is that you have a tight loop in a single process, on each round of the loop you call select and get back information on which file handles are read for reading, which are ready for writing and which have errors and then do what is appropriate. It is basically the best way to do asyncronous non-blocking IO without spawning multiple processes. This technique tends to be more management intensive, but it's less resource intensive than threads or forking processes (aka - your 3rd option).
In order to do this in the most OO way, my suggestion would be to make run a class method, which references a package level array of all your connection instances. Or if that seems un-OO to you, you can make a factory class for your connections, which will retain a reference to all connections it dispenses and then have your factory "run" everything. With OO, as with perl, TIMTOWTDI.
Your 3rd option is the more common way to do about these things (at least in my experience). Apache works this way (yes I know I am greatly simplifying Apache), as do most web servers. The benefits are that you can code your connection objects in such a way that you need not worry about resource (net-connection) sharing and asyncronous behaviour. The forked-process/thread takes care of that for you. But, as I mentioned above, its much more resource intensive in terms of memory and CPU.
The good thing about this technique is that your connection objects can become simplier since they have no need to worry about hogging resources. You will still need to write some code to fork a process or spawn a thread for each one, but once that is done, the processes/threads take care of a lot of the "management" stuff that you would do by hand with option 1.
If you do go for option 3 (which I would recommend), you should look for some thread/fork managers on CPAN. Thread::Pool of Parallel::ForkManager come to mind.
| [reply] [d/l] [select] |
|
|
Edit2, wooohah! iet ies alive! now if only i can find a way to make it stop dying because the main script ends i'm all the way there :/
Edit, problem solved by using threads->create(\&_run); instead
well, i went for your suggestion concerning threads, and all seems to be fine, except for one thing, the thread doesn't return control to the calling subroutine :(
I've spent quite a bit of time reading tutorials and the like, and they all tell me that when using the threads module the calling script should continue normally after spawning off a thread...here's the bit of code that i use:
sub run
{
my $self = shift;
$self->{thread} = threads->create($self->_run);
print "does this ever show up?\n";
}
The print statement never gets executed, as the thread takes control of the entire script. Any ideas? | [reply] [d/l] |
|
|
Sorry, threads aren't my thing, so I am not the best person to answer your question. But I think showing us your _run method might be helpful in helping solve this problem. I can give you a basic example of how one would do this with fork:
sub run {
my ($self) = @_;
my $PID = fork();
# fork returns undef if it fails
(defined $PID) || die "Could not fork successfully";
# fork returns the Process ID of the new process it
# has created to the parent process, and 0 to the
# child process, so if we have a "true" value in $PID
# then we are in the parent
if ($PID) {
# so we let the parent store the PID
# of the process which is "_run"-ning
$self->{PID} = $PID
}
else {
# otherwise we are in the child, so we
# should call _run
$self->_run();
# we sure to call exit here so our child
# process cleans up nicely
exit();
}
}
# you can call stop from the parent
# process to kill the child, you can adapt
# this to send any number of signals to
# the child depending upon your needs
sub stop {
my ($self) = @_;
kill "INT", $self->{PID};
}
Here are a couple of links to relevant documentation:
| [reply] [d/l] [select] |
Re: OO theory question
by pbeckingham (Parson) on Jun 09, 2004 at 15:10 UTC
|
Is threading an option available to you? It would let your connection objects operate in a more natural way. If your Perl supports it (5.8 or later recommended), and if your familiarity with threading, or your tolerance for a bit of a learning curve is sufficient, then perhaps consider threads.
| [reply] |
|
|
i'm running 5.8.3, Activeperl to be exact. I'm not scared of learning something new, but my knowledge of threading is, well, negligible :-) I've been doing a little searching on how I might go about this, but so far I haven't really been able to find a tutorial or explanation that offers me great enlightenment.
| [reply] |
|
|
Threading is a good thing to learn. It's becoming more prevalent, and as the implementations mature, and multiple CPU machines become more popular, it will become a more valuable skill. Or put another way, you'll need to be good at threads one day.
Try perlthrtut, and of course, PerlMonks - there are many tutorials, helpful hints, and patient folks willing to help.
Now the caveats - if this project has a challenging deadline, or if you anticipate difficulties, or if this is a high-profile app with low tolerance for bugs, you may want to back off threads.
| [reply] |
|
|