PreviousUpNext

15.4.1561  src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg

## widgetspace-imp.pkg
#
# For background see comments at top of
#     src/lib/x-kit/widget/gui/guiboss-imp.pkg
#
# For the big picture see the imp dataflow diagrams in
#
#     src/lib/x-kit/xclient/src/window/xclient-ximps.pkg
#
# At present this imp does nothing.  It was intended to maintain
# per-running-gui state, but later widgets became highly mobile
# between running guis which made it better to maintain state
# globally in guiboss-imp rather than locally here.  I'm leaving
# this imp and its associated infrastructure in place because
# I suspect that the week after I rip all this stuff out, I'll
# discover a pressing need for it.         -- 2015-02-07 CrT

# Compiled by:
#     src/lib/x-kit/widget/xkit-widget.sublib


stipulate
    include package   threadkit;                                # threadkit                     is from   src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg
    #
#   package ap  =  client_to_atom;                              # client_to_atom                is from   src/lib/x-kit/xclient/src/iccc/client-to-atom.pkg
#   package au  =  authentication;                              # authentication                is from   src/lib/x-kit/xclient/src/stuff/authentication.pkg
#   package cpm =  cs_pixmap;                                   # cs_pixmap                     is from   src/lib/x-kit/xclient/src/window/cs-pixmap.pkg
#   package cpt =  cs_pixmat;                                   # cs_pixmat                     is from   src/lib/x-kit/xclient/src/window/cs-pixmat.pkg
#   package dy  =  display;                                     # display                       is from   src/lib/x-kit/xclient/src/wire/display.pkg
#   package xet =  xevent_types;                                # xevent_types                  is from   src/lib/x-kit/xclient/src/wire/xevent-types.pkg
#   package w2x =  windowsystem_to_xserver;                     # windowsystem_to_xserver       is from   src/lib/x-kit/xclient/src/window/windowsystem-to-xserver.pkg
#   package fil =  file__premicrothread;                        # file__premicrothread          is from   src/lib/std/src/posix/file--premicrothread.pkg
#   package fti =  font_index;                                  # font_index                    is from   src/lib/x-kit/xclient/src/window/font-index.pkg
#   package r2k =  xevent_router_to_keymap;                     # xevent_router_to_keymap       is from   src/lib/x-kit/xclient/src/window/xevent-router-to-keymap.pkg
#   package mtx =  rw_matrix;                                   # rw_matrix                     is from   src/lib/std/src/rw-matrix.pkg
#   package r8  =  rgb8;                                        # rgb8                          is from   src/lib/x-kit/xclient/src/color/rgb8.pkg
#   package rgb =  rgb;                                         # rgb                           is from   src/lib/x-kit/xclient/src/color/rgb.pkg
#   package rop =  ro_pixmap;                                   # ro_pixmap                     is from   src/lib/x-kit/xclient/src/window/ro-pixmap.pkg
#   package rw  =  root_window;                                 # root_window                   is from   src/lib/x-kit/widget/lib/root-window.pkg
#   package rwv =  rw_vector;                                   # rw_vector                     is from   src/lib/std/src/rw-vector.pkg
#   package sep =  client_to_selection;                         # client_to_selection           is from   src/lib/x-kit/xclient/src/window/client-to-selection.pkg
#   package shp =  shade;                                       # shade                         is from   src/lib/x-kit/widget/lib/shade.pkg
#   package sj  =  socket_junk;                                 # socket_junk                   is from   src/lib/internet/socket-junk.pkg
#   package tr  =  logger;                                      # logger                        is from   src/lib/src/lib/thread-kit/src/lib/logger.pkg
#   package tsr =  thread_scheduler_is_running;                 # thread_scheduler_is_running   is from   src/lib/src/lib/thread-kit/src/core-thread-kit/thread-scheduler-is-running.pkg
#   package u1  =  one_byte_unt;                                # one_byte_unt                  is from   src/lib/std/one-byte-unt.pkg
#   package v1u =  vector_of_one_byte_unts;                     # vector_of_one_byte_unts       is from   src/lib/std/src/vector-of-one-byte-unts.pkg
#   package v2w =  value_to_wire;                               # value_to_wire                 is from   src/lib/x-kit/xclient/src/wire/value-to-wire.pkg
#   package wg  =  widget;                                      # widget                        is from   src/lib/x-kit/widget/old/basic/widget.pkg
#   package wi  =  window;                                      # window                        is from   src/lib/x-kit/xclient/src/window/window.pkg
#   package wme =  window_map_event_sink;                       # window_map_event_sink         is from   src/lib/x-kit/xclient/src/window/window-map-event-sink.pkg
#   package wpp =  client_to_window_watcher;                    # client_to_window_watcher      is from   src/lib/x-kit/xclient/src/window/client-to-window-watcher.pkg
#   package wy  =  widget_style;                                # widget_style                  is from   src/lib/x-kit/widget/lib/widget-style.pkg
#   package e2s =  xevent_to_string;                            # xevent_to_string              is from   src/lib/x-kit/xclient/src/to-string/xevent-to-string.pkg
#   package xc  =  xclient;                                     # xclient                       is from   src/lib/x-kit/xclient/xclient.pkg
#   package xj  =  xsession_junk;                               # xsession_junk                 is from   src/lib/x-kit/xclient/src/window/xsession-junk.pkg
#   package xt  =  xtypes;                                      # xtypes                        is from   src/lib/x-kit/xclient/src/wire/xtypes.pkg
#   package xtr =  xlogger;                                     # xlogger                       is from   src/lib/x-kit/xclient/src/stuff/xlogger.pkg
    package pl  =  paired_lists;                                # paired_lists                  is from   src/lib/std/src/paired-lists.pkg

    package g2d =  geometry2d;                                  # geometry2d                    is from   src/lib/std/2d/geometry2d.pkg
    package g2j =  geometry2d_junk;                             # geometry2d_junk               is from   src/lib/std/2d/geometry2d-junk.pkg

    package b2s =  spritespace_to_sprite;                       # spritespace_to_sprite         is from   src/lib/x-kit/widget/space/sprite/spritespace-to-sprite.pkg
    package c2o =  objectspace_to_object;                       # objectspace_to_object         is from   src/lib/x-kit/widget/space/object/objectspace-to-object.pkg
    package g2p =  gadget_to_pixmap;                            # gadget_to_pixmap              is from   src/lib/x-kit/widget/theme/gadget-to-pixmap.pkg

    package im  =  int_red_black_map;                           # int_red_black_map             is from   src/lib/src/int-red-black-map.pkg
    package gt  =  guiboss_types;                               # guiboss_types                 is from   src/lib/x-kit/widget/gui/guiboss-types.pkg
    package blk =  blank;                                       # blank                         is from   src/lib/x-kit/widget/leaf/blank.pkg

    package pp  =  standard_prettyprinter;                      # standard_prettyprinter        is from   src/lib/prettyprint/big/src/standard-prettyprinter.pkg
    #
    tracefile   =  "widget-unit-test.trace.log";

    nb = log::note_on_stderr;                                   # log                           is from   src/lib/std/src/log.pkg
herein

    package widgetspace_imp
    :       Widgetspace_Imp                                                                                             # Widgetspace_Imp               is from   src/lib/x-kit/widget/space/widget/widgetspace-imp.api
    {
        #
        Widgetspace_State                                                                                               # Holds all nonephemeral mutable state maintained by shape.
          =
          { id:         Id,
            state:      Ref( Void )
          };

        Imports = {                                                                                                     # Ports we use, provided by other imps.
                    int_sink:                   Int -> Void,
                    space_to_gui:               gt::Space_To_Gui                                                        # Our channel to        src/lib/x-kit/widget/gui/guiboss-imp.pkg
                  };

        Exports = {                                                                                                     # Ports we provide for use by other imps.
                    guiboss_to_widgetspace:     gt::Guiboss_To_Widgetspace
                  };

        Widgetspace_Egg =  Void -> (Exports,   (Imports, Run_Gun) -> Void);

        Me_Slot = Mailslot  ( { imports:                Imports,
                                me:                     Widgetspace_State,
                                options:                List(gt::Widgetspace_Option),
                                run_gun':               Run_Gun,
                                shutdown_oneshot:       Null_Or(Oneshot_Maildrop( Void )),                              # When die() runs shutdown is signalled via this.
                                callback:               Null_Or(gt::Guiboss_To_Widgetspace -> Void)
                              }
                            );

        Runstate =  {                                                                                                   # These values will be statically globally visible throughout the code body for the imp.
                      me:               Widgetspace_State,                                                              # 
                      options:          List(gt::Widgetspace_Option),
                      imports:          Imports,                                                                        # Imps to which we send requests.
                      to:               Replyqueue,                                                                     # The name makes   foo::pass_something(imp) to {. ... }   syntax read well.
                      shutdown_oneshot: Null_Or(Oneshot_Maildrop( Void ))                                               # When die() runs shutdown is signalled via this.
                    };

        Widgetspace_Q    = Mailqueue( Runstate -> Void );


        fun shut_down_widgetspace_imp ({ shutdown_oneshot, options, ... }: Runstate)
            =
            {   case shutdown_oneshot                                                                                   # Pass our state back to guiboss to allow later impnet restart without state loss.
                    #
                    NULL        => ();
                    THE oneshot =>  put_in_oneshot (oneshot, ());                                                       # 
                esac;

                thread_exit { success => TRUE };                                                                        # Will not return.      
            };

        fun run   ( widgetspace_q:      Widgetspace_Q,                                                                  # 
                    #
                    runstate as
                    {                                                                                                   # These values will be statically globally visible throughout the code body for the imp.
                      me:               Widgetspace_State,                                                              # 
                      options:          List(gt::Widgetspace_Option),
                      imports:          Imports,                                                                        # Imps to which we send requests.
                      to:               Replyqueue,                                                                     # The name makes   foo::pass_something(imp) to {. ... }   syntax read well.
                      shutdown_oneshot: Null_Or(Oneshot_Maildrop( Void ))                                               # When die() runs shutdown is signalled via this.
                    }
                  )
            =
            {
                loop ();
            }
            loop ()
            where
                fun loop ()                                                                                             # Outer loop for the imp.
                    =
                    {   do_one_mailop' to [
                            #
                            (take_from_mailqueue' widgetspace_q ==>  do_label_plea)
                        ];

                        loop ();
                    }   
                    where
                        fun do_label_plea thunk
                            =
                            thunk runstate;
                    end;
            end;        



        fun startup   (id: Id,   reply_oneshot:  Oneshot_Maildrop( (Me_Slot, Exports) ))   ()                           # Root fn of imp microthread.  Note currying.
            =
            {   me_slot  =  make_mailslot  ()   :  Me_Slot;
                #
                guiboss_to_widgetspace  = { id, do_something, pass_something, die       };

                exports =  { guiboss_to_widgetspace };

                to          =  make_replyqueue();
                #
                put_in_oneshot (reply_oneshot, (me_slot, exports));                                                     # Return value from widgetspace_egg'().

                (take_from_mailslot  me_slot)                                                                           # Imports from widgetspace_egg'().
                    ->
                    { me, options, imports, run_gun', shutdown_oneshot, callback };

                block_until_mailop_fires  run_gun';                                                                     # Wait for the starting gun.

                case callback   THE callback => callback guiboss_to_widgetspace;                                        # Tell application how to contact us.
                                NULL         => ();
                esac;

                run (widgetspace_q, { me, options, imports, to, shutdown_oneshot });                                    # Will not return.
            }
            where
                widgetspace_q     =  make_mailqueue (get_current_microthread()):  Widgetspace_Q;



                #######################################################################
                # guiboss_to_widgetspace fns:

                fun do_something (i: Int)                                                                               # PUBLIC.
                    =   
                    put_in_mailqueue  (widgetspace_q,
                        #
                        \\ ({ me, imports, ... }: Runstate)
                            =
                            imports.int_sink i                                                                          # Demonstrate use of imports.
                    );

                fun pass_something  (replyqueue: Replyqueue)  (reply_handler: Int -> Void)                              # PUBLIC.
                    =
                    {   reply_oneshot =  make_oneshot_maildrop():  Oneshot_Maildrop( Int );
                        #
                        put_in_mailqueue  (widgetspace_q,
                            #
                            \\ ({ me, ... }: Runstate)
                                =
                                put_in_oneshot (reply_oneshot, 0)
                        );

                        put_in_replyqueue (replyqueue, (get_from_oneshot' reply_oneshot) ==> reply_handler);
                    };

                fun die ()
                    =
                    put_in_mailqueue  (widgetspace_q,
                        #
                        \\ (runstate: Runstate)
                            =
                            shut_down_widgetspace_imp  runstate
                    );

            end;


        fun process_options
            (
              options:          List(gt::Widgetspace_Option),
              #
              { name,
                id,
                callback
              }
            )
            =
            {   my_name         =  REF name;
                my_id           =  REF id;
                my_callback     =  REF callback;
                #
                apply  do_option  options
                where
                    fun do_option (gt::PS_MICROTHREAD_NAME      n) =>  my_name          :=  n;
                        do_option (gt::PS_ID                    i) =>  my_id            :=  i;
                        do_option (gt::PS_CALLBACK              c) =>  my_callback      :=  THE c;
                    end;
                end;

                { name     =>  *my_name,
                  id       =>  *my_id,
                  callback =>  *my_callback
                };
            };

        ##########################################################################################
        # PUBLIC.
        #
        fun make_widgetspace_egg
                (options:               List(gt::Widgetspace_Option))                                                   # PUBLIC. PHASE 1: Construct our state and initialize from 'options'.
                (shutdown_oneshot:      Null_Or(Oneshot_Maildrop( Void )))                                              # When die() runs shutdown is signalled via this.
            =
            {   (process_options
                  ( options,
                  #
                    { name      => "widgetspace",
                      id        =>  id_zero,
                      callback  =>  NULL
                    } 
                ) )
                    ->
                    { name,
                      id, 
                      callback
                    };

                my (id, options)
                    =
                    if (id_to_int(id) == 0)
                        id = issue_unique_id();                                                                         # Allocate unique imp id.
                        (id, gt::PS_ID id ! options);                                                                   # Make our id stable across stop/restart cycles.
                    else
                        (id, options);
                    fi;

                me = { id, state => REF () };

                \\ () = {   reply_oneshot = make_oneshot_maildrop():  Oneshot_Maildrop( (Me_Slot, Exports) );           # PUBLIC. PHASE 2: Start our microthread and return our Exports to caller.
                            #
                            xlogger::make_thread  name  (startup  (id, reply_oneshot));                                 # Note that startup() is curried.

                            (get_from_oneshot  reply_oneshot) -> (me_slot, exports);

                            fun phase3                                                                                  # PUBLIC. PHASE 3: Accept our Imports, then wait for Run_Gun to fire.
                                ( imports:      Imports,
                                  run_gun':     Run_Gun 
                                )
                                =
                                {
                                    put_in_mailslot  (me_slot, { me, options, imports, run_gun', shutdown_oneshot, callback });
                                };

                            (exports, phase3);
                        };
            };

    };

end;




Comments and suggestions to: bugs@mythryl.org

PreviousUpNext