staload _ = "prelude/DATS/pointer.dats"
staload "libats/SATS/parworkshop.sats"
staload _ = "libats/DATS/parworkshop.dats"
absviewtype work_vt
viewtypedef WSptr (l:addr) = WORKSHOPptr (work_vt, l)
viewtypedef work = {l:agz} (!WSptr l) -<lincloptr1> void
extern castfn work_encode (x: work): work_vt
typedef fwork_type
(a:viewt@ype) = {l:agz} (!WSptr l, &a >> a?) -> int
extern fun fwork : fwork_type (work)
implement fwork (ws, wk) = let
val wk = wk
val pfun = __cast (wk) where {
extern castfn __cast
(wk: !work >> opt (work, i >= 2)): #[i:nat] uintptr i
} in
if pfun >= (uintptr1_of_uint1)2U then let
prval () = opt_unsome {work} (wk)
val () = wk (ws)
val () = cloptr_free (wk)
in
1 end else let
val u = uint1_of_uintptr1 (pfun)
val i = int_of_uint (u)
prval () = opt_unnone {work} (wk)
prval () = cleanup_top {work} (wk)
in
~i end end
#define ARG_QUICKSORT_MT_DATS 1
typedef T = int
#include "qsort_mt.dats"
#define CUTOFF %(1 << 20)
fun qsort_splt {lws:agz}
{n:nat} {A:addr} (ws: !WSptr lws, A: ptr A, n: int n): void = let
prval (pf, fpf) = __assert () where {
extern prfun __assert (): (array_v (T, n, A), array_v (T, n, A) -<prf> void)
} in
if n > CUTOFF then let
val i_pivot = partition (pf | A, n)
val (pf_mul | ofs) = (size)i_pivot szmul2 sizeof<T>
prval (pf1, pf2) = array_v_split {T} (pf_mul, pf)
prval (pf21, pf22) = array_v_uncons {T} (pf2)
prval pf1_mul = mul_add_const {1} (pf_mul)
val () = workshop_insert_work (ws, f) where {
val f = lam {l:agz} (ws: !WSptr l)
: void =<lincloptr1> qsort_splt (ws, A, i_pivot)
val f = work_encode (f)
} val () = workshop_insert_work (ws, f) where {
val f = lam {l:agz} (ws: !WSptr l)
: void =<lincloptr1> qsort_splt (ws, A+ofs+sizeof<T>, n-i_pivot-1)
val f = work_encode (f)
} prval () = pf2 := array_v_cons {T} (pf21, pf22)
prval () = pf := array_v_unsplit {T} (pf_mul, pf1, pf2)
prval () = fpf (pf)
in
end else let
val () = qsort (pf | A, n)
prval () = fpf (pf)
in
end
end
staload RAND = "libc/SATS/random.sats"
fn array_ptr_print {n:nat} {l:addr}
(pf_arr: !array_v (T, n, l) | A: ptr l, n: size_t n): void = let
var !p_f = @lam
(pf: !unit_v | i: sizeLt n, x: &T): void =<clo> begin
$effmask_all (if i > 0 then print ", "; printf ("%i", @(x)))
end prval pf = unit_v ()
val () = array_ptr_iforeach_clo_tsz {T} (pf | !A, !p_f, n, sizeof<T>)
prval unit_v () = pf
in
end
#define N 100000000
fn random_array_ptr_gen {n:nat} (n: size_t n):<>
[l:addr | l <> null] (free_gc_v (T, n, l), array_v (T, n, l) | ptr l) = let
val (pfgc, pfarr | parr) = array_ptr_alloc_tsz {T} (n, sizeof<T>)
prval pf = unit_v
val () = array_ptr_initialize_fun_tsz {T} {unit_v} (
pf
| !parr
, n
, lam (pf | i, x) => x := $effmask_ref ($RAND.randint (N))
, sizeof<T>
) prval unit_v () = pf
in
(pfgc, pfarr | parr)
end
fn prerr_usage (cmd: string): void = begin
prerr ("Usage:\n");
prerrf (" single core: %s [integer]\n", @(cmd));
prerrf (" multiple core: %s [integer(arg)] [integer(core)]\n", @(cmd));
end
#define QSZ %(1 << 16)
#define NWORKER 1
implement
main (argc, argv) = let
val () = assert_errmsg_bool1
(argc >= 2, "command format: qsort_mt_int <int> <ncore>")
val n = int_of argv.[1]
val n = int1_of_int (n)
val () = assert_errmsg (n >= 0, #LOCATION)
val fwork = __cast (fwork) where {
extern castfn __cast (x: fwork_type work):<> fwork_type (work_vt)
} val ws = workshop_make<work_vt> (QSZ, fwork)
val nworker =
(if (argc >= 3) then int_of argv.[2] else NWORKER): int
val nworker = int1_of_int (nworker)
val () = assert_errmsg (nworker > 0, #LOCATION)
val _err = workshop_add_nworker (ws, nworker)
val () = assert_errmsg (_err = 0, #LOCATION)
val nsz = size1_of_int1 (n)
val (pfgc, pfarr | A) = random_array_ptr_gen (nsz)
val t = qsort_splt (ws, A, n)
val () = workshop_wait_blocked_all (ws)
val () = if (n <= 100) then
(array_ptr_print (pfarr | A, nsz); print_newline ())
val () = array_ptr_free {T} (pfgc, pfarr | A)
var i: Nat = 0
val () = while (i < nworker) let
val _quit = $extval (work_vt, "(void*)0")
val () = workshop_insert_work (ws, _quit) in i := i + 1
end val () = workshop_wait_quit_all (ws)
val () = (print "sorting is finished"; print_newline ())
val () = workshop_free_vt_exn (ws)
in
end