Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

STFL Terminal UI - Concurrency Demonstrations

by marioroy (Priest)
on Oct 08, 2017 at 00:16 UTC ( #1200923=CUFP: print w/replies, xml ) Need Help??

Hello brothers and sisters of the monastery,

I came across a dated article by Philip Durbin (from 10/2011). I thought to give MCE::Hobo a try and see how it goes.

The STFL library, a curses-based widget set for text terminals, compiles seamlessly on the Linux platform. Ncurses development libraries and swig are needed on CentOS 7.3. I've not tested on other Unix platforms.

sudo yum install ncurses-devel swig tar xzf /path/to/stfl-0.24.tar.gz cd stfl-0.24 # Modify Makefile and comment out the SWIG lines #ifeq ($(FOUND_SWIG)$(FOUND_PERL5),11) #include perl5/Makefile.snippet #endif #ifeq ($(FOUND_SWIG)$(FOUND_PYTHON),11) #include python/Makefile.snippet #endif #ifeq ($(FOUND_SWIG)$(FOUND_RUBY),11) #include ruby/Makefile.snippet #endif sudo make install # Finally, build the Perl module cd perl5 swig -Wall -perl stfl.i perl Makefile.PL sudo make install

example.stfl

From the STFL documentation, a special language is used to describe the STFL GUI.

** * example.stfl: STFL layout for example1.pl and example2.pl. ** vbox hbox .expand:0 @style_normal:bg=yellow,fg=black label text:'Little STFL Program' label["label 1"] text["text 1"]:"10000" label["label 2"] text["text 2"]:"20000" label["label 3"] text["text 3"]:"30000" table .expand:0 @input#style_focus:bg=blue,fg=white,attr=bold @input#style_normal:bg=blue,fg=black @input#.border:rtb @L#style_normal:fg=red @L#.expand:0 @L#.border:ltb @L#.spacer:r label#L text:'Field A:' input .colspan:3 text[value_a]:'foo' tablebr label#L text:'Field B:' input text[value_b]:'bar' label#L text:'Field C:' input text[value_c]:'baz' label .expand:v .tie:bl text[helpmsg]:''

example_p1.pl

Each worker increments a shared counter. What is cool about STFL is being able to enter text while the counters increment simultaneously in the terminal. Pressing F2 signals the workers to exit. F1 spawns new Hobo workers. Pressing ESC or Ctrl-C (handled by MCE::Signal) exits the application.

#!/usr/bin/env perl use strict; use warnings; use stfl; use MCE::Hobo 1.831; use MCE::Shared; use Time::HiRes qw/sleep/; my $count1 = MCE::Shared->scalar(10000); my $count2 = MCE::Shared->scalar(20000); my $count3 = MCE::Shared->scalar(30000); my $layout; { open my $fh, "<", "example.stfl" or die "open error 'example.stfl': $!"; local $/; $layout = <$fh>; } my $f = stfl::create($layout); my $s = 0; # MCE::Hobo 1.832 and later releases will set posix_exit # automatically when present, $INC{'stfl.pm'}. MCE::Hobo->init( posix_exit => 1 ); sub bg_start { unless ($s) { mce_async { sleep(0.9), $count1->incr() while 1 }; mce_async { sleep(0.6), $count2->incr() while 1 }; mce_async { sleep(0.3), $count3->incr() while 1 }; $s = 1; } } sub bg_stop { if ($s) { $_->exit()->join() for MCE::Hobo->list(); $s = 0; } } $f->set('helpmsg', '[ ESC = exit | F1 = start | F2 = stop ]'); bg_start(); while (1) { my $event = $f->run(50); if ($s) { # must stringify in case numeric value $f->set('text 1', ''.$count1->get()); $f->set('text 2', ''.$count2->get()); $f->set('text 3', ''.$count3->get()); } next unless (defined $event); bg_start() if $event eq 'F1'; bg_stop() if $event eq 'F2'; last if $event eq 'ESC'; } bg_stop();

example_p2.pl

Here, workers enqueue the form ID and value into a queue. The main process makes one trip to the shared-manager, maximum 3 replies.

#!/usr/bin/env perl use strict; use warnings; use stfl; use MCE::Hobo 1.831; use MCE::Shared; use Time::HiRes qw/sleep/; my $q = MCE::Shared->queue(); my $layout; { open my $fh, "<", "example.stfl" or die "open error 'example.stfl': $!"; local $/; $layout = <$fh>; } my $f = stfl::create($layout); my $s = 0; # MCE::Hobo 1.832 and later releases will set posix_exit # automatically when present, $INC{'stfl.pm'}. MCE::Hobo->init( posix_exit => 1 ); mce_async { my $c = 10000; sleep(0.9), $q->enqueue([ 'text 1', ++$c ]) while 1; }; mce_async { my $c = 20000; sleep(0.6), $q->enqueue([ 'text 2', ++$c ]) while 1; }; mce_async { my $c = 30000; sleep(0.3), $q->enqueue([ 'text 3', ++$c ]) while 1; }; $f->set('helpmsg', '[ ESC = exit ]'); while (1) { my $event = $f->run(50); foreach my $ret ($q->dequeue_nb(3)) { # must stringify in case numeric value $f->set($ret->[0], ''.$ret->[1]); } next unless (defined $event); last if $event eq "ESC"; } $_->exit()->join() for MCE::Hobo->list();

Entering text into an input box and have other areas of the form update automatically is quite nice. Furthermore, a worker may run an event loop and not impact the main process. There are a lot of possibilities.

Regards, Mario

Replies are listed 'Best First'.
Re: STFL Terminal UI - Concurrency Demonstrations
by marioroy (Priest) on Oct 08, 2017 at 05:17 UTC

    Updated: Threads require a signal handler when requested to terminate.

    The threads module along with MCE::Shared is another possibility. Like before using MCE::Hobo, shared data constructed with MCE::Shared resides under the shared-manager. MCE::Shared spawns a thread versus a child process when threads is present.

    example_t1.pl

    #!/usr/bin/env perl use strict; use warnings; use stfl; use threads; use MCE::Shared; use Time::HiRes qw/sleep/; my $count1 = MCE::Shared->scalar(10000); my $count2 = MCE::Shared->scalar(20000); my $count3 = MCE::Shared->scalar(30000); my $layout; { open my $fh, "<", "example.stfl" or die "open error 'example.stfl': $!"; local $/; $layout = <$fh>; } my $f = stfl::create($layout); my $s = 0; sub bg_start { unless ($s) { async { local $SIG{'QUIT'} = sub { threads->exit() }; sleep(0.9), $count1->incr() while 1; }; async { local $SIG{'QUIT'} = sub { threads->exit() }; sleep(0.6), $count2->incr() while 1; }; async { local $SIG{'QUIT'} = sub { threads->exit() }; sleep(0.3), $count3->incr() while 1; }; $s = 1; } } sub bg_stop { if ($s) { # Signal the thread to terminate, and then detach # it so that it will get cleaned up automatically. $_->kill('QUIT')->detach() for threads->list(); $s = 0; } } $f->set('helpmsg', '[ ESC = exit | F1 = start | F2 = stop ]'); bg_start(); while (1) { my $event = $f->run(50); if ($s) { # must stringify in case numeric value $f->set('text 1', ''.$count1->get()); $f->set('text 2', ''.$count2->get()); $f->set('text 3', ''.$count3->get()); } next unless (defined $event); bg_start() if $event eq 'F1'; bg_stop() if $event eq 'F2'; last if $event eq 'ESC'; } bg_stop();

    example_t2.pl

    #!/usr/bin/env perl use strict; use warnings; use stfl; use threads; use MCE::Shared; use Time::HiRes qw/sleep/; my $q = MCE::Shared->queue(); # Start the shared-manager manually. # https://metacpan.org/pod/MCE::Shared::Queue#LIMITATIONS MCE::Shared->start() unless $INC{'IO::FDPass.pm'}; my $layout; { open my $fh, "<", "example.stfl" or die "open error 'example.stfl': $!"; local $/; $layout = <$fh>; } my $f = stfl::create($layout); my $s = 0; async { my $c = 10000; sleep(0.9), $q->enqueue([ 'text 1', ++$c ]) while 1; }; async { my $c = 20000; sleep(0.6), $q->enqueue([ 'text 2', ++$c ]) while 1; }; async { my $c = 30000; sleep(0.3), $q->enqueue([ 'text 3', ++$c ]) while 1; }; $f->set('helpmsg', '[ ESC = exit ]'); while (1) { my $event = $f->run(50); foreach my $ret ($q->dequeue_nb(3)) { # must stringify in case numeric value $f->set($ret->[0], ''.$ret->[1]); } next unless (defined $event); last if $event eq "ESC"; } $_->exit()->join() for threads->list();

    Regards, Mario

Re: STFL Terminal UI - Concurrency Demonstrations
by marioroy (Priest) on Oct 10, 2017 at 07:42 UTC

    Running STFL (Terminal UI) on the Mac is possible. Four small changes are needed inside three files.

    diff -ur stfl-0.24/Makefile stfl-0.24.new/Makefile --- stfl-0.24/Makefile 2015-02-12 07:14:33.000000000 -0600 +++ stfl-0.24.new/Makefile 2017-10-10 02:40:59.000000000 -0500 @@ -22,7 +22,7 @@ export CC = gcc -pthread export CFLAGS += -I. -Wall -Os -ggdb -D_GNU_SOURCE -fPIC -export LDLIBS += -lncursesw +export LDLIBS += -lncurses -liconv SONAME := libstfl.so.0 VERSION := 0.24 @@ -39,7 +39,7 @@ libstfl.so.$(VERSION): public.o base.o parser.o dump.o style.o bindin +g.o iconv.o \ $(patsubst %.c,%.o,$(wildcard widgets/*.c)) - $(CC) -shared -Wl,-soname,$(SONAME) -o $@ $(LDLIBS) $^ + $(CC) -shared -Wl,-install_name,$(SONAME) -o $@ $(LDLIBS) $^ clean: rm -f libstfl.a example core core.* *.o Makefile.deps diff -ur stfl-0.24/perl5/Makefile.PL stfl-0.24.new/perl5/Makefile.PL --- stfl-0.24/perl5/Makefile.PL 2007-09-03 11:13:49.000000000 -0500 +++ stfl-0.24.new/perl5/Makefile.PL 2017-10-10 02:37:34.000000000 - +0500 @@ -3,6 +3,6 @@ "NAME" => "stfl", # The -D_LARGEFILE64_SOURCE -D_GNU_SOURCE are needed by perl (not + STFL!) on some systems "CCFLAGS" => "-pthread -I.. -D_LARGEFILE64_SOURCE -D_GNU_SOURCE +", - "LIBS" => ["-lpthread -lncursesw"], + "LIBS" => ["-lpthread -lncurses -liconv"], "OBJECT" => "stfl_wrap.o ../libstfl.a" ); diff -ur stfl-0.24/stfl_internals.h stfl-0.24.new/stfl_internals.h --- stfl-0.24/stfl_internals.h 2015-01-05 04:47:32.000000000 -0600 +++ stfl-0.24.new/stfl_internals.h 2017-10-10 02:23:32.000000000 -0 +500 @@ -28,7 +28,7 @@ #endif #include "stfl.h" -#include <ncursesw/ncurses.h> +#include <ncurses.h> #include <pthread.h> struct stfl_widget_type;

    Swig is needed for making the Perl module later on.

    $ tar xzf $HOME/Downloads/swig-3.0.12.tar.gz $ cd swig-3.0.12 $ ./configure $ make $ sudo make install

    Afterwards, follow the instructions found here.

    Regards, Mario

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://1200923]
Front-paged by stevieb
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2018-06-23 09:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?



    Results (125 votes). Check out past polls.

    Notices?