-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDelayLine.pm
More file actions
247 lines (171 loc) · 5.57 KB
/
Copy pathDelayLine.pm
File metadata and controls
247 lines (171 loc) · 5.57 KB
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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
package DelayLine;
# $Id$
use strict;
use Carp;
use vars qw($VERSION);
$VERSION = '0.02';
my %fields = (
_LINE => [],
_BORN => undef,
DEBUG => 0,
DELAY => 0,
);
sub new {
my ($proto, %args) = @_;
# new() can be used as both class and object method
my $class = ref($proto) || $proto;
# build object
my $self = bless {
%fields,
}, $class;
# set creation time
$self->{_BORN} = time();
# parse arguments
foreach my $arg (keys %args) {
foreach my $attrib (grep {!/^_/} keys %fields) {
if ($arg =~ /^-?$attrib$/i) {
$self->{$attrib} = delete $args{$arg};
}
}
}
# complain about unknown arguments
if (my @unknown = keys %args) {
croak __PACKAGE__, ": Unknown argument",
(@unknown == 1 ? ' ' : 's '),
join(', ', map {"'$_'"} @unknown);
}
print STDERR "new\n"
if $self->{DEBUG};
$self;
}
# clone standard attribute accessor methods
for my $attrib (grep {!/^_/} keys %fields) {
no strict "refs";
*{lc $attrib} = sub {
my $self = shift;
my $prev = $self->{$attrib};
$self->{$attrib} = shift if @_;
$prev;
}
}
sub in {
my ($self, $obj, $delay) = @_;
my $now = time();
$delay = $self->delay unless defined $delay;
my %entry = (
'OBJ' => $obj,
'DELAY' => $delay,
'INTIME' => $now,
'OUTTIME' => $now + $delay,
);
print STDERR __PACKAGE__, "::in obj='$obj' delay=$entry{DELAY} outtime=$entry{OUTTIME}\n"
if $self->{DEBUG};
# push new object onto delayline
push @{$self->{_LINE}}, \%entry;
# re-sort delayline according to outtime
@{$self->{_LINE}} = sort {
$a->{OUTTIME} <=> $b->{OUTTIME}
} @{$self->{_LINE}};
}
sub out {
my ($self) = @_;
my $now = time();
# return immediately if the DelayLine is empty
unless (@{$self->{_LINE}}) {
print STDERR __PACKAGE__, "::out now=$now empty\n"
if $self->{DEBUG};
return;
}
# return overdue object
if ($self->{_LINE}->[0]->{OUTTIME} <= $now) {
my $obj = (shift @{$self->{_LINE}})->{OBJ};
print STDERR __PACKAGE__, "::out now=$now obj='$obj'\n"
if $self->{DEBUG};
return $obj;
}
# nothing ready yet
print STDERR __PACKAGE__, "::out now=$now next=$self->{_LINE}->[0]->{OUTTIME}\n"
if $self->{DEBUG};
return;
}
1;
__END__
=head1 NAME
DelayLine - Simple time-delay data stucture
=head1 SYNOPSIS
use DelayLine;
my $dl = DelayLine->new(delay => $defaultdelay);
$dl->in($item);
[ ... ]
if (my $ob = $dl->out()) {
# do stuff with $ob
}
=head1 DESCRIPTION
The C<DelayLine> is a simple two-port data structure, like a FIFO, but
with variable delay. Each object put into the input of the DelayLine
will appear on the output only after some pre-determined amount of
time has elapsed. This time can be set as a default for the DelayLine,
or can be individually overridden for each object put into the
DelayLine.
If the default delay time is set to zero, and is not overridden for
the individual objects, the DelayLine mimics a straightforward FIFO.
The DelayLine accepts any scalar value as input, including
references.
The DelayLine is a very useful component when building simple event
loops.
=head2 Methods
C<DelayLine> provides the following methods:
=over 4
=item DelayLine->new( [ delay => DELAY [, debug => DEBUG ]] )
Returns a newly created C<DelayLine> object.
The default delay is 0 seconds, unless an optional C<DELAY> time in
seconds is given.
Debugging is turned off by default. Setting DEBUG to true, enables
debugging output to STDOUT.
The parameter naming style is very flexible: the keyword can be in
lower, upper or mixed case, and can be optionally prefixed with a
dash. Thus, the following are all equivalent:
$dl = DelayLine->new( -delay => 42 );
$dl = DelayLine->new( delay => 42 );
$dl = DelayLine->new( -Delay => 42 );
$dl = DelayLine->new( DELAY => 42 );
$dl = DelayLine->new( -deLaY => 42 );
C<new()> can be called as a class (static) or object method. Calling
C<new()> as an object method is only a convenience; no data from the
original DelayLine is carried over into the newly created object.
=item $DL->in( OBJ [, DELAY ] )
This method puts object C<OBJ> into DelayLine C<$DL>.
The object C<OBJ> can be any scalar value, including references.
The default delay as set in the C<new()> method is used, unless
overridden by setting C<DELAY>.
=item $DL->out()
This method fetches objects from the out from the DelayLine C<$DL>.
Returns the first of the timed-out objects, if any.
Returns C<undef> if the DelayLine is empty, of if no objects in the
DelayLine have timed out yet.
=item $DL->delay( [ DELAY ] )
Returns the current default delay setting of the DelayLine. If the
optional value DELAY is set, sets a new default delay value.
=item $DL->debug( [ DEBUG ] )
Returns the current debug setting of the DelayLine. If the
optional value DEBUG is set, sets a new debug value.
If the debug value is set (true), calling any of the 'active' methods
(C<in()> or C<out()> will yield a short debug message on STDERR.
=back
=head1 BUGS
This is a fairly simple module, so no serious bugs are
expected. Patches are welcome, though.
=head1 RELEASE HISTORY
=item v0.02 - 2000-jul-22
Fixed test for multiple unknown args.
Removed superfluous test output.
Streamlined debug output.
=item v0.01 - 2000-jul-13
Initial release.
=head1 COPYRIGHT
Copyright (c) 2000 Lars Thegler. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=head1 AUTHOR
Lars Thegler <lars@thegler.dk>
=cut