packages feed

language-ats-0.1.1.0: test/data/fworkshop.out

(***********************************************************************)
(*                                                                     *)
(*                       ATS/contrib/libats-hwxi                       *)
(*                                                                     *)
(***********************************************************************)
(*
** Copyright (C) 2017 Hongwei Xi, ATS Trustful Software, Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and associated documentation files (the "Software"),
** to deal in the Software without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
** and/or sell copies of the Software, and to permit persons to whom the
** Software is furnished to do so, subject to the following stated conditions:
** 
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
** 
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
** IN THE SOFTWARE.
*)
(* ****** ****** *)
(*
** HX-2017-02-07: Start it now!
*)
(* ****** ****** *)
(*
//
// HX-2017-02-11:
// It is supposed to be
// included rather than staloaded
//
#define
ATS_PACKNAME "ATSCNTRB.HX.fworkshop"
//
*)
(* ****** ****** *)
staload UN = "prelude/SATS/unsafe.sats"

(* ****** ****** *)
staload AT = "libats/SATS/athread.sats"

typedef tid = $AT.tid
typedef spin1 = $AT.spin1

(* ****** ****** *)
abstype fws$store_type() = ptr

typedef fws$store = fws$store_type

(* ****** ****** *)
absvtype fws$fwork_vtype() = ptr

vtypedef fws$fwork = fws$fwork_vtype

(* ****** ****** *)
extern
fun fws$store_capacity() : intGte(1)

extern
fun fws$store_insert(fws$store, fws$fwork) : void

extern
fun fws$store_takeout(store : fws$store) : fws$fwork

extern
fun fws$fwork_process(fws$fwork) : int

(* ****** ****** *)
abstype fworkshop_type() = ptr

typedef fworkshop = fworkshop_type

(* ****** ****** *)
vtypedef fworkshop_struct = @{ FWS_spin = spin1
                             , FWS_store = fws$store
                             , FWS_workerlst = List0_vt(tid)
                             }

(* ****** ****** *)
extern
fun fworkshop_create_exn() : fworkshop

extern
fun fws$store_create_exn() : fws$store

(* ****** ****** *)
extern
fun fworkshop_add_tid(fws : fworkshop, tid) : void

(* ****** ****** *)
extern
fun fworkshop_get_spin(fws : fworkshop) : spin1

(* ****** ****** *)
extern
fun fworkshop_get_store(fws : fworkshop) : fws$store

(* ****** ****** *)
extern
fun fworkshop_get_nworker(fws : fworkshop) : intGte(0)

(* ****** ****** *)
extern
fun fworkshop_insert_work(fws : fworkshop, fwork : fws$fwork) : void

extern
fun fworkshop_takeout_work(fws : fworkshop) : fws$fwork

extern
fun fworkshop_process_work(fws : fworkshop, fwork : fws$fwork) : int

(* ****** ****** *)
extern
fun fworkshop_add_worker(fws : fworkshop) : int

extern
fun fworkshop_add_nworker {n:nat} (fws : fworkshop, int(n)) : natLte(n)

(* ****** ****** *)
local
  assume fworkshop_type() = ref(fworkshop_struct)
in
  (* ****** ****** *)
  implement fworkshop_add_nworker {n} (fws, n) =
    loop(0, 0) where
    { fun loop { i : nat | i <= n } (i : int(i), res : natLte(i)) :
        natLte(n) =
        let
          
        in
          if i < n then
            let
              val err = fworkshop_add_worker{}(fws)
            in
              if err = 0 then
                loop(i + 1, res + 1)
              else
                res
            end
          else
            res
        end }
  
  (* ****** ****** *)
  implement fworkshop_add_worker (fws) =
    err where
    { fun fworker(fws : fworkshop) : void =
        let
          val fwork = fworkshop_takeout_work(fws)
          val status = fworkshop_process_work(fws, fwork)
        in
          if (status >= 0) then
            fworker(fws)
          else
            fworker_exit(fws)
        end
      
      and fworker_exit(fws : fworkshop) : void =
        let
          val tid0 = $AT.athread_self()
          
          fun auxrmv(tids : &List0_vt(tid) >> _) : void =
            (case+ tids of
              | list_vt_nil() => ()
              | @list_vt_cons (tid, tids_tl) => (if (tid0 != tid) then
                {
                  val () = auxrmv(tids_tl)
                  val () = fold@(tids)
                }
              else
                {
                  val tids_ = tids
                  val () = tids := tids_tl
                  val () = free@{..,0}(tids_)
                }))
          
          val (vbox pf | p0) = ref_get_viewptr(fws)
          val spn = p0->FWS_spin
          val (pflock | ()) = $AT.spin_lock(spn)
          val () = $effmask_ref(auxrmv(p0->FWS_workerlst))
          val () = $AT.spin_unlock(pflock | spn)
        in end
      
      var tid: lint? with 
      val err = $AT.athread_create_cloptr{}(tid, llam () => fworker(fws))
      val () = if (err = 0) then
        fworkshop_add_tid{}(fws, tid) }
  
  (* ****** ****** *)
  implement fworkshop_get_nworker (fws) =
    let
      val (vbox pf | p0) = ref_get_viewptr(fws)
      val spn = p0->FWS_spin
      val (pflock | ()) = $AT.spin_lock(spn)
      val nworker = list_vt_length(p0->FWS_workerlst)
      val () = $AT.spin_unlock(pflock | spn)
    in
      nworker
    end
  
  (* ****** ****** *)
  implement fworkshop_get_store (fws) =
    let
      val (vbox pf | p0) = ref_get_viewptr(fws)
    in
      p0->FWS_store
    end
  
  (* ****** ****** *)
  implement fworkshop_get_spin (fws) =
    let
      val (vbox pf | p0) = ref_get_viewptr(fws)
    in
      p0->FWS_spin
    end
  
  (* ****** ****** *)
  implement fworkshop_add_tid (fws, tid) =
    let
      val (vbox pf | p0) = ref_get_viewptr(fws)
      val spn = p0->FWS_spin
      val (pflock | ()) = $AT.spin_lock(spn)
      val tids = p0->FWS_workerlst
      val () = p0->FWS_workerlst := list_vt_cons(tid, tids)
      val () = $AT.spin_unlock(pflock | spn)
    in end
  
  (* ****** ****** *)
  implement fworkshop_create_exn () =
    let
      val (pf, fpf | p0) = ptr_alloc<fworkshop_struct>()
      val () = p0->FWS_spin := $AT.spin_create_exn()
      val () = p0->FWS_store := fws$store_create_exn{}(())
      val () = p0->FWS_workerlst := list_vt_nil()
    in
      $UN.castvwtp0{fworkshop}((p0, fpf, pf))
    end
  
  (* ****** ****** *)
end

(* ****** ****** *)
implement fworkshop_insert_work (fws, x0) =
  let
    val store = fworkshop_get_store{}(fws)
  in
    fws$store_insert{}(store, x0)
  end

(* ****** ****** *)
implement fworkshop_takeout_work (fws) =
  let
    val store = fworkshop_get_store{}(fws)
  in
    fws$store_takeout{}(store)
  end

(* ****** ****** *)
implement fworkshop_process_work (fws, fwork) =
  status where
  { val status = fws$fwork_process{}(fwork) }

(* ****** ****** *)
(* end of [fworkshop.dats] *)