Open Scope nat_scope.
(* Definition containsThread_dec (tp : t) (i : NatTID.tid) : bool:= Compare.Pcompare i (num_threads tp). *)
Definition containsThread (tp : t) (i : NatTID.tid) : Prop:=
i < num_threads tp.
Definition containsThread_dec:
forall i tp, {containsThread tp i} + { ~ containsThread tp i}.
Definition getThreadR {i tp} (cnt: containsThread tp i) : res :=
(perm_maps tp) (Ordinal cnt).
Definition latestThread tp := n (num_threads tp).
Definition addThread (tp : t) (vf arg : val) (pmap : res) : t :=
let: new_num_threads := pos_incr (num_threads tp) in
let: new_tid := ordinal_pos_incr (num_threads tp) in
mk new_num_threads
(fun (n : 'I_new_num_threads) =>
match unlift new_tid n with
| None => Kinit vf arg
| Some n' => tp n'
end)
(fun (n : 'I_new_num_threads) =>
match unlift new_tid n with
| None => pmap
| Some n' => (perm_maps tp) n'
end)
(lset tp).
Definition updLockSet tp (add:address) (lf:lock_info) : t :=
mk (num_threads tp)
(pool tp)
(perm_maps tp)
(AMap.add add lf (lockGuts tp)).
Definition remLockSet tp  (add:address) : t :=
mk (num_threads tp)
(pool tp)
(perm_maps tp)
(AMap.remove add (lockGuts tp)).
Definition updThreadC {tid tp} (cnt: containsThread tp tid) (c' : ctl) : t :=
mk (num_threads tp)
(fun n => if n == (Ordinal cnt) then c' else (pool tp)  n)
(perm_maps tp)
(lset tp).
Definition updThreadR {tid tp} (cnt: containsThread tp tid)
(pmap' : res) : t :=
mk (num_threads tp) (pool tp)
(fun n =>
if n == (Ordinal cnt) then pmap' else (perm_maps tp) n)
(lset tp).
Definition updThread {tid tp} (cnt: containsThread tp tid) (c' : ctl)
(pmap : res) : t :=
mk (num_threads tp)
(fun n =>
if n == (Ordinal cnt) then c' else tp n)
(fun n =>
if n == (Ordinal cnt) then pmap else (perm_maps tp) n)
(lset tp).
(*TODO: see if typeclasses can automate these proofs, probably not thanks dep types*)

(*Proof Irrelevance of contains*)
Lemma cnt_irr: forall t tid
(cnt1 cnt2: containsThread t tid),
cnt1 = cnt2.