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*)

(* Specifications: *)
(*Proof Irrelevance of contains*)
Lemma cnt_irr: forall t tid
(cnt1 cnt2: containsThread t tid),
cnt1 = cnt2.
Lemma cntUpdateC :
forall {tid tid0 tp} c
(cnt: containsThread tp tid),
containsThread tp tid0 ->
containsThread (updThreadC cnt c) tid0.
Lemma cntUpdateC':
forall {tid tid0 tp} c
(cnt: containsThread tp tid),
containsThread (updThreadC cnt c) tid0 ->
containsThread tp tid0.
Lemma cntUpdateR:
forall {i j tp} r
(cnti: containsThread tp i),
containsThread tp j->
containsThread (updThreadR cnti r) j.
Lemma cntUpdateR':
forall {i j tp} r
(cnti: containsThread tp i),
containsThread (updThreadR cnti r) j ->
containsThread tp j.
Lemma cntUpdate :
forall {i j tp} c p
(cnti: containsThread tp i),
containsThread tp j ->
containsThread (updThread cnti c p) j.
Lemma cntUpdate':
forall {i j tp} c p
(cnti: containsThread tp i),
containsThread (updThread cnti c p) j ->
containsThread tp j.
Lemma cntUpdateL:
forall {j tp} add lf,
containsThread tp j ->
containsThread (updLockSet tp add lf) j.
Lemma cntRemoveL:
forall {j tp} add,
containsThread tp j ->
containsThread (remLockSet tp add) j.
Lemma cntUpdateL':
forall {j tp} add lf,
containsThread (updLockSet tp add lf) j ->
containsThread tp j.
Lemma cntRemoveL':
forall {j tp} add,
containsThread (remLockSet tp add) j ->
containsThread tp j.
Lemma cntAdd:
forall {j tp} vf arg p,
containsThread tp j ->
containsThread (addThread tp vf arg p) j.
Lemma cntAddLatest:
forall {tp} vf arg p,
containsThread (addThread tp vf arg p) (latestThread tp).
Lemma cntAdd':
forall {j tp} vf arg p,
containsThread (addThread tp vf arg p) j ->
(containsThread tp j /\ j <> num_threads tp) \/ j = num_threads tp.
Lemma contains_add_latest: forall ds p a r,
containsThread (addThread ds p a r)
(latestThread ds).
Lemma updLock_updThread_comm:
forall ds,
forall i (cnti: containsThread ds i) c map l lmap,
forall (cnti': containsThread (updLockSet ds l lmap) i),
updLockSet
(@updThread _ ds cnti c map) l lmap =
@updThread _ (updLockSet ds l lmap) cnti' c map.