Patch title: Release 85 bulk changes
Abstract:
File: /pliant/language/schedule/batch.pli
Key:
    Removed line
    Added line
module "/pliant/install/ring2.pli"
module "/pliant/language/type/misc/datetime.pli"

public
  gvar DateTime datetime_rough := datetime


constant batch_running 1
constant batch_cancel 2

type BatchPrototype
  field Str label
  field Link:Function function
  field DateTime last
  field Int frequency
  field Int flags

function batch_prototype p f
  arg_rw BatchPrototype p ; arg Function f
  indirect

gvar List list
gvar Sem sem
gvar Int batch_threads_limit := 5
gvar Float batch_overflow_sleep := 0.01
gvar CBool daemon_running := false
gvar Int running_count := 0


function batch_thread p
  arg_rw BatchPrototype p
  part batch_action p:label
    batch_prototype p p:function
  p last := datetime_rough
  p flags -= batch_running
  atomic_add running_count -1

function batch_daemon an_address
  arg Address an_address
  sem request
  while list:first<>null and pliant_execution_phase<=execution_phase_run
    datetime_rough := datetime
    var Pointer:Arrow c :> list first
    while c<>null
      var Link:BatchPrototype p :> c map BatchPrototype
      if (p:flags .and. batch_running)<>0
        c :> list next c
      eif (p:flags .and. batch_cancel)<>0
        c :> list remove c
      eif datetime_rough:seconds>=p:last:seconds+p:frequency
        if running_count>=batch_threads_limit
          sleep batch_overflow_sleep
        if running_count<batch_threads_limit
          p flags += batch_running
          atomic_add running_count 1
          var DelayedAction da
          da function :> the_function batch_thread BatchPrototype
          da parameter := addressof p
          if not run_thread:da
            p flags -= batch_running
            atomic_add running_count -1
          c :> list remove c
          list append addressof:p
        else
          c :> list next c
      else
        c :> list next c
    sem release
    sleep 1
    sem request
  daemon_running := false
  sem release


function batch_start label fun proto freq
  arg Str label ; arg Function fun ; arg_rw BatchPrototype proto ; arg Int freq
  sem request
  proto label := label
  proto function :> fun
  proto last := datetime
  proto frequency := freq
  proto flags := 0
  list append addressof:proto
  if not daemon_running
    var DelayedAction da
    da function :> the_function batch_daemon Address
    if run_thread:da
      daemon_running := true
  sem release

    
function batch_stop p
  arg_rw BatchPrototype p
  p flags := p:flags .or. batch_cancel


export BatchPrototype batch_start batch_stop batch_threads_limit batch_overflow_sleep


function batch_wakeup p
  arg Address p
  var DelayedAction da
  da function :> the_function batch_daemon Address
  if run_thread:da
    daemon_running := true
gvar DelayedAction startup
startup function :> the_function batch_wakeup Address
pliant_wakeup_actions append addressof:startup

function batch_shutdown p
  arg Address p
  while daemon_running or running_count>0
    sleep 0.1
  sleep 0.1
gvar DelayedAction shutdown
shutdown function :> the_function batch_shutdown Address
pliant_shutdown_actions append addressof:shutdown