feisty meow concerns codebase  2.140
span_manager.cpp
Go to the documentation of this file.
1 /*****************************************************************************\
2 * *
3 * Name : span_manager *
4 * Author : Chris Koeritz *
5 * *
6 *******************************************************************************
7 * Copyright (c) 1990-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
13 \*****************************************************************************/
14 
15 #include "span_manager.h"
16 
17 #include <basis/functions.h>
18 #include <basis/guards.h>
19 #include <basis/astring.h>
20 #include <structures/bit_vector.h>
21 #include <structures/set.h>
22 
23 using namespace basis;
24 using namespace structures;
25 //using namespace basis;
26 
27 namespace sockets {
28 
29 span_manager::span_manager(int packs)
30 : _implementation(new bit_vector(packs))
31 {}
32 
34 : _implementation(new bit_vector(*to_copy._implementation))
35 {}
36 
37 span_manager::~span_manager() { WHACK(_implementation); }
38 
40 {
41  if (this == &to_copy) return *this;
42  *_implementation = *to_copy._implementation;
43  return *this;
44 }
45 
47 { return _implementation->find_first(0); }
48 
49 void span_manager::reset(int packs) { _implementation->resize(packs); }
50 
51 const bit_vector &span_manager::vector() const { return *_implementation; }
52 
53 bit_vector &span_manager::vector() { return *_implementation; }
54 
56 {
57  int recd_to = _implementation->find_first(0);
58  if (negative(recd_to)) return _implementation->bits() - 1;
59  return recd_to - 1;
60 }
61 
62 void span_manager::make_received_list(int_array &to_make, int max_spans) const
63 {
64  to_make.reset(0);
65  int zeros_start_at = _implementation->find_first(0);
66  if (negative(zeros_start_at)) {
67  // all bits are set in the vector, so the whole message is received.
68  to_make.concatenate(0);
69  to_make.concatenate(short(_implementation->bits() - 1));
70  return;
71  }
72  zeros_start_at--;
73  // the sequence of ones ends right before the first zero
74  if (zeros_start_at >= 0) {
75  to_make.concatenate(0);
76  to_make.concatenate(short(zeros_start_at));
77  }
78 
79  int ones_to_here; // keeps track of the position of the ones.
80 
81  for (int outer_loop = zeros_start_at + 2;
82  outer_loop < _implementation->bits(); ) {
83  // the first zero is zeros_start_at + 1, so we start at the first
84  // unknown bit.
85  if (_implementation->on(outer_loop)) {
86  // the bit is a one, so we are in a one-gathering mode.
87  ones_to_here = outer_loop;
88  int inner_loop = outer_loop + 1;
89  while (inner_loop < _implementation->bits()) {
90  if (_implementation->on(inner_loop)) ones_to_here=inner_loop;
91  else break; // a zero is found at this position, so leave loop.
92  inner_loop++;
93  }
94  // the stretch of ones is entered in the array.
95  to_make.concatenate(short(outer_loop));
96  to_make.concatenate(short(ones_to_here));
97  if ( (max_spans >= 0) && (to_make.length() >= 2 * max_spans) )
98  return;
99  outer_loop = ones_to_here + 1;
100  } else {
101  // the bit is a zero, so we are gathering zeros.
102  int inner_loop = outer_loop + 1;
103  ones_to_here = _implementation->bits();
104  while (inner_loop < _implementation->bits()) {
105  if (!_implementation->on(inner_loop)) inner_loop++;
106  else {
107  // ones_to_here is set to the first position of a one, actually.
108  ones_to_here = inner_loop;
109  break;
110  }
111  }
112  // the loop variable is set to the first unknown position again.
113  outer_loop = ones_to_here;
114  }
115  }
116 }
117 
118 bool span_manager::update(const int_array &new_spans)
119 {
120  for (int i = 0; i < new_spans.length(); i += 2) {
121  if ( (new_spans.get(i) >= _implementation->bits())
122  || (new_spans.get(i+1) >= _implementation->bits()) )
123  return false;
124  for (int j = new_spans.get(i); j <= new_spans.get(i+1); j++)
125  _implementation->light(j);
126  }
127  return true;
128 }
129 
130 void span_manager::make_missing_list(int_array &to_make, int max_spans) const
131 {
132  to_make.reset(0);
133  int ones_start_at = _implementation->find_first(1);
134  if (negative(ones_start_at)) {
135  // all bits are zero in the vector; no packets have been received.
136  to_make.concatenate(0);
137  to_make.concatenate(short(_implementation->bits() - 1));
138  return;
139  }
140  ones_start_at--;
141  // the sequence of zeros ends right before the first one
142  if (ones_start_at >= 0) {
143  to_make.concatenate(0);
144  to_make.concatenate(short(ones_start_at));
145  }
146 
147  int zeros_to_here;
148  for (int outer_loop = ones_start_at + 2;
149  outer_loop < _implementation->bits(); ) {
150  int inner_loop;
151  // the first one is ones_start_at+1, so we start at the first unknown bit
152  if (!_implementation->on(outer_loop)) {
153  // the bit is a zero, so we are in a zero-gathering mode.
154  zeros_to_here = outer_loop;
155  int inner_loop = outer_loop + 1;
156  while (inner_loop < _implementation->bits()) {
157  if (!_implementation->on(inner_loop)) zeros_to_here=inner_loop;
158  else break;
159  // a one is found at this position, so leave loop.
160  inner_loop++;
161  }
162  // the stretch of zeros is entered in the array.
163  to_make.concatenate(short(outer_loop));
164  to_make.concatenate(short(zeros_to_here));
165  if ( (max_spans >= 0) && (to_make.length() >= 2 * max_spans) ) return;
166  outer_loop = zeros_to_here + 1;
167  } else {
168  // the bit is a one, so we are gathering ones.
169  inner_loop = outer_loop + 1;
170  zeros_to_here = _implementation->bits();
171  while (inner_loop < _implementation->bits()) {
172  if (_implementation->on(inner_loop))
173  inner_loop++;
174  else {
175  // zeros_to_here is set to the first position of a zero, actually.
176  zeros_to_here = inner_loop;
177  break;
178  }
179  }
180  // the loop variable is set to the first unknown position again.
181  outer_loop = zeros_to_here;
182  }
183  }
184 }
185 
186 astring span_manager::funky_print(const int_array &to_spew, int rec_seq) const
187 {
188  astring to_return(astring::SPRINTF, "through %d, [", rec_seq);
189  for (int i = 0; i < to_spew.length(); i += 2) {
190  to_return += astring(astring::SPRINTF, " %d-%d", to_spew.get(i),
191  to_spew.get(i+1));
192  }
193  to_return += astring(" ] ");
194  return to_return;
195 }
196 
198 {
199  int_array hold_info;
200  make_received_list(hold_info);
201  astring to_return("received ");
202  to_return += funky_print(hold_info, received_sequence());
203  return to_return;
204 }
205 
207 {
208  int_array hold_info;
209  make_missing_list(hold_info);
210  astring to_return("missing ");
211  to_return += funky_print(hold_info, received_sequence());
212  return to_return;
213 }
214 
215 } //namespace.
216 
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
Definition: array.h:349
array & concatenate(const array &to_concatenate)
Appends the array "to_concatenate" onto "this" and returns "this".
Definition: array.h:379
const contents & get(int index) const
Accesses individual objects stored in "this" at the "index" position.
Definition: array.h:372
int length() const
Returns the current reported length of the allocated C array.
Definition: array.h:115
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
A simple object that wraps a templated array of ints.
Definition: array.h:275
Manages lists of numbers representing the completion of some activity.
Definition: span_manager.h:32
bool update(const basis::int_array &new_spans)
updates the span information.
int received_sequence() const
returns the highest chunk number at which all chunks are ready.
const structures::bit_vector & vector() const
observes the held bit_vector that represents the spans.
void make_missing_list(basis::int_array &spans, int max_spans=-1) const
creates a list representing the spans that are not ready yet.
void make_received_list(basis::int_array &spans, int max_spans=-1) const
Creates a list for the received spans that are ready.
span_manager(int number_of_items)
span_manager & operator=(const span_manager &to_copy)
basis::astring print_received_list() const
prints out the span list for received blocks into a string.
basis::astring print_missing_list() const
prints out the span list for missing blocks into a string.
void reset(int number_of_items)
sets up the span manager with a new configuration.
int missing_sequence() const
returns the number of the chunk where the first item is missing.
An array of bits with operations for manipulating and querying individual bits.
Definition: bit_vector.h:26
bool on(int position) const
returns true if the bit at "position" is set.
Definition: bit_vector.cpp:75
int find_first(bool to_find) const
Seeks the first occurrence of "to_find".
Definition: bit_vector.cpp:158
int bits() const
returns the number of bits in the vector.
Definition: bit_vector.cpp:66
void light(int position)
sets the value of the bit at "position".
Definition: bit_vector.cpp:146
void resize(int size)
Changes the size of the bit_vector to "size" bits.
Definition: bit_vector.cpp:80
The guards collection helps in testing preconditions and reporting errors.
Definition: array.h:30
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
Definition: functions.h:121
bool negative(const type &a)
negative returns true if "a" is less than zero.
Definition: functions.h:43
Provides access to the operating system's socket methods.
Definition: base_address.h:26
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55