Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Curses - Running other "background tasks"?

Status
Not open for further replies.

Kirsle

Programmer
Jan 21, 2006
1,179
US
Hi, I recently installed the Curses modules for Perl, both so I could become familiar with how to use it and also because I already had an idea in mind for an application for it.

There's been some small demand for a command-line based chat client for CyanChat ( ). Somebody wrote one in Python but it wasn't that good (it didn't use Curses or anything fancy like that, so the input text and printed chat dialog text ran together).

I figured it'd only take me a few hours to roll out a pretty simple chat client, but after spending those few hours figuring out how to work with Curses, I've hit a bit of a snag: Curses doesn't seem to make it very easy to do other, non-GUI-related tasks in the background.

With the CyanChat client I made with Tk ( ), I used code along these lines to get Tk to play well with the Net::CyanChat module (which, like all IM and chat-based modules, requires looping to keep up with the server):

Code:
Instead of the "give-all-control of-my-program-to-Tk" code that most programs are fine with...

MainLoop;

# I make my own loop.

while (1) {
   select (undef,undef,undef,0.01); # a short sleep to lower CPU %
   $mw->update(); # update Tk's stuff
   $cc->do_one_loop(); # loop our CyanChat object
}

However, from what I've seen, Curses doesn't make it easy to do this kind of thing. I tried a couple of workarounds.

First I viewed the source of Curses::UI (the particular module set I'm working with) to see how their MainLoop function works. This is their code:

Code:
sub mainloop ()
{
    my $this = shift;

    # Draw the initial screen.
    $this->focus(undef, 1); # 1 = forced focus
    $this->draw;
    doupdate();

    # Inifinite event loop.
    for(;;) 
    { 
        $this->do_one_event 
    }
}

So, in my Curses app, I simply replaced my "$curses->mainloop()" line with something along the lines of

Code:
$curses->focus (undef, 1);
$curses->draw();

while (1) {
   select (undef,undef,undef,0.01);
   $curses->do_one_event();

   if (defined $cc) {
      $cc->do_one_loop();
   }
}

It seemed to work... until I tried to connect to CyanChat. It seemed like the connect attempt was hanging, so I put in some debug things (since Curses takes over the CLI, I had to write the debug messages to the chat dialog window in the GUI). I had it write a line of text each time my "$cc->do_one_loop()" line was called.

It turned out that, $curses->do_one_event blocks until there's "something" for it to do (be it, I type something, click something, or otherwise make there be a need for the GUI to update in some way).

So, workaround attempt #2: digging through the source code I found some subroutines related to timers. So I used the code...

Code:
our $loops = 0;

$curses->set_timer ($loops, \&loopCC, 1); # id, callback, time

$curses->mainloop();

sub loopCC {
   $cc->do_one_loop();
   $loops++;
   $curses->set_timer ($loops, \&loopCC, 1);
}

This had unstable results. I put in debugging messages that would write that the timer was called and what the current value of $loops was ($loops being an incrementing number to give each timer call a unique ID). When the program would first start, it would insert "timeout 1" in the dialog box, and then do nothing. If I'd type a character, it would spit out a few more timeout lines and stop at somewhere around 4 or 5. type another key and it'd spit out a few more all at once and stop around 20. then it would stop around 40 or 50. and it would keep getting exponentially greater from there, eventually taking up a lot of CPU and forcing me to kill the process (probably deep recursion is to blame).

So, that solution wasn't satisfactory either.

I could use a separate thread for the CC object, and that might at least eliminate the possibility of it being disconnected for being unresponsive, but it still leaves the problem of how that new thread would still have trouble communicating with the GUI thread, which doesn't seem to let the program continue until something "happens".

If anybody has any experience with using Curses and knows of a way to fix this problem, please reply. Thanks in advance. :)

-------------
Cuvou.com | My personal homepage
Project Fearless | My web blog
 
Never used it but that Module has some bad reviews and seems to indicate it is difficult to use.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top