File: imp-queue.sml

package info (click to toggle)
mlton 20061107-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 27,828 kB
  • ctags: 61,118
  • sloc: ansic: 11,446; makefile: 1,339; sh: 1,160; lisp: 900; pascal: 256; asm: 97
file content (121 lines) | stat: -rw-r--r-- 4,982 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