Here is the current demo!

It is very important to note how termination is handled!

To refresh your memory .. if you have any .. 

When you spawn an fthread it will block on an schannel
operation until there is a matching operation: a read will
block until there is a write, and a write until there is a read.

This means to properly terminate a program, if you're
using a driver loop, as with the event handling fthreads
in the code below, you must organise a way to allow the
fthread to terminate.

Fthread can die in two ways: they can exit gracefully,
by doing a usual return statement.

Or they can suicide due to what would otherwise be a deadlock.

A deadlock would occur if an schannel is reading (or writing)
an schannel which no other active fthread can reach.

to understand what happens: active fthreads (and ones waiting for
async I/O) are GC roots. When you do a read or write on an schannel
the fthread loses its root status. Instead, it is owned by the schannel!
So if the schannel isn't reachable, the GC will reap the schannel
AND the fthread.

therefore: do NOT make global variables containing schannels,
unless you're going to use them to satisfy I/O requests, otherwise
the program will halt from starvation: the schannel and waiting
thread are reachable but you're not sending them any messages!

If you do have a global variable it is OK if you make sure the fthread
on the other end of the schannel exits.

If you do not take proper care, the program will either hang,
or it will suicide.

this is common! Getting a system of fthreads to terminate properly
is non-trivial: you have to design the system to do it.

Suicide is a normal and good design choice sometimes,
however if you have to destroy some resource such as a window
suicide probably isn't an option.

You must always think; fthreads are NOT threads. They're just
procedures which exchange control via schannels.
And you must also remember: active fthreads OWN channels.
Inactive fthreads are owned BY channels. Performing an
I/O operation doesn't just exchange control .. it also exchanges
ownership.

Finally don't forget the mainline is just another fthread.
There's nothing special about it (except that it returns implicitly
when control drops of the end).

//////////////////////////////////////////////////////////////////////
include "gui/__init__";
open FlxGui;

// Initialise the SDL system (SDL + TTF + IMAGE)
FlxGui::init();

// Make a window
var w = window_t("My Window",50,50,400,400);

// get a font, and the recommended vertical 
// spacing between lines
var font : font_t = get_font(OSX_dflt_font());
var lineskip = get_lineskip font;

// create some colours and clear the window
var red = RGB(255,0,0);
var green = RGB (0,255,0);
w.clear green;

// write some text and some lines
w.write (100,100,font,red,"HELLO");
w.write (100,100+lineskip,font,red,"WORLD");
w.draw_line (RGB(0,0,255), 100,100,200,200);

// update the window with the stuff we drew
w.update;

// create a window manager
var wm = window_manager();

// get the channel to read events from
var input = wm.get_event_source();

// make an event handler for our window
proc ehandler (input:ischannel[event_t]) () 
{
  var run = true;
  while run do
    var e: event_t = read input;
    println$ "  WINDOW specific EVENT: " + e.window.event.SDL_WindowEventID.str;
    run = e.window.event.SDL_WindowEventID != SDL_WINDOWEVENT_CLOSE ;
  done
  println$ "Terminating window event processing loop";
}

// make a controller for the window using our event handler
var wc = window_controller (w, ehandler);

// place the controller under the window manager
var i = wm.add_window wc;

// report the index number of the window
// indices allow us to loop over windows
println$ "Window index " + i.str;

// get a first event from the window manager
var event : event_t = read input;

// while the event isn't a quit event ..
while event.type.SDL_EventType != SDL_QUIT do

  // print a diagnostic
  println$ event.type.SDL_EventType.str;

  // dispatch the event to the window it is associated with
  wm.dispatch_window_event event;

  // get another event
  event = read input;
done

// we must have got a quit ..
println$ "QUIT EVENT";

var clock = Faio::mk_alarm_clock();
Faio::sleep(clock,10.0);

begin
  for var j in 0 upto #(wm.get_n_windows) - 1 do 
    // this is messy! Fix soon!
    var wc = wm.get_window_controller_from_index 0;
    var wid = #(wc.get_window_id);
    wm.delete_window wid;
  done
end 
println$ "Windows deleted, quitting";
//////////////////////////////////////////////////////////////////////

One of the things that should start to become apparent with fthread/schannel
design methodology is the total and utter decoupling of the components.
Systems are made from totally independent "chips" which are though of 
as active processes that do I/O.

The actual structure of the system (circuit board) requires wiring the chips
together with schannels.

This means, for example, if you have one or more window controllers,
you can just plug multiple instances of them into the window manager.
No extra work is required to do multiple windows.

--
john skaller
skal...@users.sourceforge.net
http://felix-lang.org




------------------------------------------------------------------------------
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to