File: imp-queue.sml

package info (click to toggle)
mlton 20041109-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 18,212 kB
  • ctags: 58,085
  • sloc: ansic: 10,386; makefile: 1,178; sh: 1,139; pascal: 256; asm: 97
file content (121 lines) | stat: -rw-r--r-- 3,729 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
(* imp-queue.sml
 * 2004 Matthew Fluet (mfluet@acm.org)
 *  Ported to MLton threads.
 *)

structure ImpQueue : IMP_QUEUE =
   struct
      datatype 'a t = T of {front: 'a list ref, back: 'a list ref}

      local
	 fun filterPrefix (xs, p) =
	    case xs of
	       [] => []
	     | y::ys => if p y
			  then filterPrefix (ys, p)
			  else xs
	 fun filter (xs, p) = List.filter (not o p) xs
	 fun filterRevAcc ((xs, zs), p) =
	    case xs of
	       [] => zs
	     | y::ys => if p y
			  then filterRevAcc ((ys, zs), p)
			  else filterRevAcc ((ys, y::zs), p)
	 fun filterRev (xs, p) = filterRevAcc ((xs, []), p)
      in
	 fun cleanPrefix (T {front, back}, p) =
	    (Assert.assertAtomic' ("ImpQueue.cleanPrefix", NONE)
	     ; case filterPrefix (!front, p) of
	          [] => (front := filterPrefix (List.rev(!back), p)
			 ; back := [])
		| front' =>  front := front')
	 fun clean (T {front, back}, p) =
	    (Assert.assertAtomic' ("ImpQueue.clean", NONE)
	     ; case filter (!front, p) of
	          [] => (front := filterRev (!back, p)
			 ; back := [])
		| front' =>  (front := front'
			      ; back := filter (!back, p)))
	 fun cleanAndDeque (T {front, back}, p) =
	    (Assert.assertAtomic' ("ImpQueue.cleanAndDeque", NONE)
	     ; case filter (!front, p) of
	          [] => (case filterRev(!back, p) of
			    [] => (front := []
				   ; back := []
				   ; NONE)
			  | x::front' => (front := front'
					  ; back := []
					  ; SOME x))
		| [x] => (front := filterRev (!back, p)
			  ; back := []
			  ; SOME x)
		| x::front' => (front := front'
				; back := filter (!back, p)
				; SOME x))
      end

      fun deque (T {front, back}) =
	 (Assert.assertAtomic' ("ImpQueue.deque", NONE)
	  ; case !front of
	       [] => (case !back of
			 [] => NONE
		       | l => let val l = List.rev l
			      in case l of
				    [] => raise Fail "ImpQueue.deque:impossible"
				  | x :: front' => 
				       (front := front'
					; back := []
					; SOME x)
			      end)
	     | x::front' => (front := front'; SOME x))

      fun empty (T {front, back}) =
	 (Assert.assertAtomic' ("ImpQueue.empty", NONE)
	  ; case !front of
	       [] => (case !back of
			 [] => true
		       | _ => false)
	     | _ => false)
	     
      fun enque (T {back, ...}, x) = 
	 (Assert.assertAtomic' ("ImpQueue.enque", NONE)
	  ; back := x::(!back))

      fun enqueAndClean (q, y, p) =
	 (enque (q, y); clean (q, p))

      fun new () = T {front = ref [], back = ref []}

      fun peek (T {front, back}) =
	 (Assert.assertAtomic' ("ImpQueue.peek", NONE)
	  ; case !front of
	       [] => (case !back of
			 [] => NONE
		       | l => let val l = List.rev l
			      in case l of
				    [] => raise Fail "ImpQueue.peek:impossible"
				  | x::front' => 
				       (front := x::front'
					; back := []
					; SOME x)
			      end)
	     | x::_ => SOME x)

      fun reset (T {front, back}) =
	 (Assert.assertAtomic' ("ImpQueue.reset", NONE)
	  ; front := []
	  ; back := [])

(*
      val clean = fn arg => TimeIt.timeit "ImpQueue.clean" clean arg
      val cleanAndDeque = fn arg => TimeIt.timeit "ImpQueue.cleanAndDeque" cleanAndDeque arg
      val cleanPrefix = fn arg => TimeIt.timeit "ImpQueue.cleanPrefix" cleanPrefix arg
      val deque = fn arg => TimeIt.timeit "ImpQueue.deque" deque arg
      val empty = fn arg => TimeIt.timeit "ImpQueue.empty" empty arg
      val enque = fn arg => TimeIt.timeit "ImpQueue.enque" enque arg
      val enqueAndClean = fn arg => TimeIt.timeit "ImpQueue.enqueAndClean" enqueAndClean arg
      val new = fn arg => TimeIt.timeit "ImpQueue.new" new arg
      val peek = fn arg => TimeIt.timeit "ImpQueue.peek" peek arg
      val reset = fn arg => TimeIt.timeit "ImpQueue.reset" reset arg
*)
   end