PageRenderTime 35ms CodeModel.GetById 9ms RepoModel.GetById 1ms app.codeStats 0ms

/elements/standard/simplequeue.cc

https://github.com/bhesmans/click
C++ | 228 lines | 180 code | 25 blank | 23 comment | 50 complexity | 91a9e6753a1dfbeae1311df3826dfb91 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. // -*- c-basic-offset: 4 -*-
  2. /*
  3. * simplequeue.{cc,hh} -- queue element
  4. * Eddie Kohler
  5. *
  6. * Copyright (c) 1999-2000 Massachusetts Institute of Technology
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a
  9. * copy of this software and associated documentation files (the "Software"),
  10. * to deal in the Software without restriction, subject to the conditions
  11. * listed in the Click LICENSE file. These conditions include: you must
  12. * preserve this copyright notice, and you cannot mention the copyright
  13. * holders in advertising related to the Software without their permission.
  14. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
  15. * notice is a summary of the Click LICENSE file; the license in that file is
  16. * legally binding.
  17. */
  18. #include <click/config.h>
  19. #include "simplequeue.hh"
  20. #include <click/args.hh>
  21. #include <click/error.hh>
  22. CLICK_DECLS
  23. SimpleQueue::SimpleQueue()
  24. : _q(0)
  25. {
  26. }
  27. void *
  28. SimpleQueue::cast(const char *n)
  29. {
  30. if (strcmp(n, "Storage") == 0)
  31. return (Storage *)this;
  32. else if (strcmp(n, "SimpleQueue") == 0
  33. || strcmp(n, "Queue") == 0)
  34. return (Element *)this;
  35. else
  36. return 0;
  37. }
  38. int
  39. SimpleQueue::configure(Vector<String> &conf, ErrorHandler *errh)
  40. {
  41. unsigned new_capacity = 1000;
  42. if (Args(conf, this, errh).read_p("CAPACITY", new_capacity).complete() < 0)
  43. return -1;
  44. _capacity = new_capacity;
  45. return 0;
  46. }
  47. int
  48. SimpleQueue::initialize(ErrorHandler *errh)
  49. {
  50. assert(!_q && _head == 0 && _tail == 0);
  51. _q = (Packet **) CLICK_LALLOC(sizeof(Packet *) * (_capacity + 1));
  52. if (_q == 0)
  53. return errh->error("out of memory");
  54. _drops = 0;
  55. _highwater_length = 0;
  56. return 0;
  57. }
  58. int
  59. SimpleQueue::live_reconfigure(Vector<String> &conf, ErrorHandler *errh)
  60. {
  61. // change the maximum queue length at runtime
  62. Storage::index_type old_capacity = _capacity;
  63. // NB: do not call children!
  64. if (SimpleQueue::configure(conf, errh) < 0)
  65. return -1;
  66. if (_capacity == old_capacity || !_q)
  67. return 0;
  68. Storage::index_type new_capacity = _capacity;
  69. _capacity = old_capacity;
  70. Packet **new_q = (Packet **) CLICK_LALLOC(sizeof(Packet *) * (new_capacity + 1));
  71. if (new_q == 0)
  72. return errh->error("out of memory");
  73. Storage::index_type i, j;
  74. for (i = _head, j = 0; i != _tail && j != new_capacity; i = next_i(i))
  75. new_q[j++] = _q[i];
  76. for (; i != _tail; i = next_i(i))
  77. _q[i]->kill();
  78. CLICK_LFREE(_q, sizeof(Packet *) * (_capacity + 1));
  79. _q = new_q;
  80. _head = 0;
  81. _tail = j;
  82. _capacity = new_capacity;
  83. return 0;
  84. }
  85. void
  86. SimpleQueue::take_state(Element *e, ErrorHandler *errh)
  87. {
  88. SimpleQueue *q = (SimpleQueue *)e->cast("SimpleQueue");
  89. if (!q)
  90. return;
  91. if (_tail != _head || _head != 0) {
  92. errh->error("already have packets enqueued, can%,t take state");
  93. return;
  94. }
  95. _head = 0;
  96. Storage::index_type i = 0, j = q->_head;
  97. while (i < _capacity && j != q->_tail) {
  98. _q[i] = q->_q[j];
  99. i++;
  100. j = q->next_i(j);
  101. }
  102. _tail = i;
  103. _highwater_length = size();
  104. if (j != q->_tail)
  105. errh->warning("some packets lost (old length %d, new capacity %d)",
  106. q->size(), _capacity);
  107. while (j != q->_tail) {
  108. q->_q[j]->kill();
  109. j = q->next_i(j);
  110. }
  111. q->set_head(0);
  112. q->set_tail(0);
  113. }
  114. void
  115. SimpleQueue::cleanup(CleanupStage)
  116. {
  117. for (Storage::index_type i = _head; i != _tail; i = next_i(i))
  118. _q[i]->kill();
  119. CLICK_LFREE(_q, sizeof(Packet *) * (_capacity + 1));
  120. _q = 0;
  121. }
  122. void
  123. SimpleQueue::push(int, Packet *p)
  124. {
  125. // If you change this code, also change NotifierQueue::push()
  126. // and FullNoteQueue::push().
  127. Storage::index_type h = _head, t = _tail, nt = next_i(t);
  128. // should this stuff be in SimpleQueue::enq?
  129. if (nt != h) {
  130. _q[t] = p;
  131. packet_memory_barrier(_q[t], _tail);
  132. _tail = nt;
  133. int s = size(h, nt);
  134. if (s > _highwater_length)
  135. _highwater_length = s;
  136. } else {
  137. // if (!(_drops % 100))
  138. if (_drops == 0 && _capacity > 0)
  139. click_chatter("%p{element}: overflow", this);
  140. _drops++;
  141. checked_output_push(1, p);
  142. }
  143. }
  144. Packet *
  145. SimpleQueue::pull(int)
  146. {
  147. return deq();
  148. }
  149. String
  150. SimpleQueue::read_handler(Element *e, void *thunk)
  151. {
  152. SimpleQueue *q = static_cast<SimpleQueue *>(e);
  153. int which = reinterpret_cast<intptr_t>(thunk);
  154. switch (which) {
  155. case 0:
  156. return String(q->size());
  157. case 1:
  158. return String(q->highwater_length());
  159. case 2:
  160. return String(q->capacity());
  161. case 3:
  162. return String(q->_drops);
  163. default:
  164. return "";
  165. }
  166. }
  167. void
  168. SimpleQueue::reset()
  169. {
  170. while (Packet *p = pull(0))
  171. checked_output_push(1, p);
  172. }
  173. int
  174. SimpleQueue::write_handler(const String &, Element *e, void *thunk, ErrorHandler *errh)
  175. {
  176. SimpleQueue *q = static_cast<SimpleQueue *>(e);
  177. int which = reinterpret_cast<intptr_t>(thunk);
  178. switch (which) {
  179. case 0:
  180. q->_drops = 0;
  181. q->_highwater_length = q->size();
  182. return 0;
  183. case 1:
  184. q->reset();
  185. return 0;
  186. default:
  187. return errh->error("internal error");
  188. }
  189. }
  190. void
  191. SimpleQueue::add_handlers()
  192. {
  193. add_read_handler("length", read_handler, 0);
  194. add_read_handler("highwater_length", read_handler, 1);
  195. add_read_handler("capacity", read_handler, 2, Handler::CALM);
  196. add_read_handler("drops", read_handler, 3);
  197. add_write_handler("capacity", reconfigure_keyword_handler, "0 CAPACITY");
  198. add_write_handler("reset_counts", write_handler, 0, Handler::BUTTON | Handler::NONEXCLUSIVE);
  199. add_write_handler("reset", write_handler, 1, Handler::BUTTON);
  200. }
  201. CLICK_ENDDECLS
  202. ELEMENT_PROVIDES(Storage)
  203. EXPORT_ELEMENT(SimpleQueue)