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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
|
# queue.tcl --
#
# Queue implementation for Tcl.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# Copyright (c) 2008-2010 Andreas Kupries
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: queue_oo.tcl,v 1.2 2010/09/10 17:31:04 andreas_kupries Exp $
package require Tcl 8.5 9
package require TclOO 0.6.1- ; # This includes 1 and higher.
# Cleanup first
catch {namespace delete ::struct::queue::queue_oo}
catch {rename ::struct::queue::queue_oo {}}
oo::class create ::struct::queue::queue_oo {
variable qat qret qadd
# variable qat - Index in qret of next element to return
# variable qret - List of elements waiting for return
# variable qadd - List of elements added and not yet reached for return.
constructor {} {
set qat 0
set qret [list]
set qadd [list]
return
}
# clear --
#
# Clear a queue.
#
# Results:
# None.
method clear {} {
set qat 0
set qret [list]
set qadd [list]
return
}
# get --
#
# Get an item from a queue.
#
# Arguments:
# count number of items to get; defaults to 1
#
# Results:
# item first count items from the queue; if there are not enough
# items in the queue, throws an error.
method get {{count 1}} {
if { $count < 1 } {
return -code error "invalid item count $count"
} elseif { $count > [my size] } {
return -code error "insufficient items in queue to fill request"
}
my Shift?
if { $count == 1 } {
# Handle this as a special case, so single item gets aren't
# listified
set item [lindex $qret $qat]
incr qat
my Shift?
return $item
}
# Otherwise, return a list of items
if {$count > ([llength $qret] - $qat)} {
# Need all of qret (from qat on) and parts of qadd, maybe all.
set max [expr {$qat + $count - 1 - [llength $qret]}]
set result [concat [lrange $qret $qat end] [lrange $qadd 0 $max]]
my Shift
set qat $max
} else {
# Request can be satisified from qret alone.
set max [expr {$qat + $count - 1}]
set result [lrange $qret $qat $max]
set qat $max
}
incr qat
my Shift?
return $result
}
# peek --
#
# Retrieve the value of an item on the queue without removing it.
#
# Arguments:
# count number of items to peek; defaults to 1
#
# Results:
# items top count items from the queue; if there are not enough items
# to fulfill the request, throws an error.
method peek {{count 1}} {
variable queues
if { $count < 1 } {
return -code error "invalid item count $count"
} elseif { $count > [my size] } {
return -code error "insufficient items in queue to fill request"
}
my Shift?
if { $count == 1 } {
# Handle this as a special case, so single item pops aren't
# listified
return [lindex $qret $qat]
}
# Otherwise, return a list of items
if {$count > [llength $qret] - $qat} {
# Need all of qret (from qat on) and parts of qadd, maybe all.
set over [expr {$qat + $count - 1 - [llength $qret]}]
return [concat [lrange $qret $qat end] [lrange $qadd 0 $over]]
} else {
# Request can be satisified from qret alone.
return [lrange $qret $qat [expr {$qat + $count - 1}]]
}
}
# put --
#
# Put an item into a queue.
#
# Arguments:
# args items to put.
#
# Results:
# None.
method put {args} {
if {![llength $args]} {
return -code error "wrong # args: should be \"[self] put item ?item ...?\""
}
foreach item $args {
lappend qadd $item
}
return
}
# unget --
#
# Put an item into a queue. At the _front_!
#
# Arguments:
# item item to put at the front of the queue
#
# Results:
# None.
method unget {item} {
if {![llength $qret]} {
set qret [list $item]
} elseif {$qat == 0} {
set qret [linsert [my K $qret [unset qret]] 0 $item]
} else {
# step back and modify return buffer
incr qat -1
set qret [lreplace [my K $qret [unset qret]] $qat $qat $item]
}
return
}
# size --
#
# Return the number of objects on a queue.
#
# Results:
# count number of items on the queue.
method size {} {
return [expr {
[llength $qret] + [llength $qadd] - $qat
}]
}
# ### ### ### ######### ######### #########
method Shift? {} {
if {$qat < [llength $qret]} return
# inlined Shift
set qat 0
set qret $qadd
set qadd [list]
return
}
method Shift {} {
set qat 0
set qret $qadd
set qadd [list]
return
}
method K {x y} { set x }
}
# ### ### ### ######### ######### #########
## Ready
namespace eval ::struct {
# Get 'queue::queue' into the general structure namespace for
# pickup by the main management.
proc queue_tcl {args} {
if {[llength $args]} {
uplevel 1 [::list ::struct::queue::queue_oo create {*}$args]
} else {
uplevel 1 [::list ::struct::queue::queue_oo new]
}
}
}
|