Click
Loading...
Searching...
No Matches
flow_nodes.hh
1#ifndef CLICK_FLOWNODES_HH
2#define CLICK_FLOWNODES_HH 1
3
4#include <click/allocator.hh>
5#include <click/straccum.hh>
6
7#include "../level/flow_level.hh"
8
9#define FLOW_NODE_DEFINE(T,fnt) \
10 static FlowNodePtr* find_ptr(void* thunk, FlowNodeData data, bool &need_grow) {\
11 return static_cast<T*>(thunk)->fnt(data,need_grow);\
12 }
13
14
15class FlowNode {
16private:
17
18protected:
19 union {
20 FlowLevel* _level;
21 void* pool_next_item;
22 };
23 union {
24 FlowNode* _parent;
25 void* pool_next_pool;
26 };
27 union {
28 uint32_t poison;
29 uint32_t num;
30 };
31 FlowNodePtr _default;
32
33
34 bool _growing;
35
36 typedef FlowNodePtr* (*FindFn)(void*,FlowNodeData data,bool &need_grow);
37
38 FindFn _find;
39
40#if FLOW_KEEP_STRUCTURE
41 bool _released;
42#endif
43
44 void duplicate_internal(FlowNode* node, bool recursive, int use_count, bool duplicate_leaf) {
45 assign(node);
46 if (unlikely(recursive)) {
47 this->_level = node->level()->duplicate();
48 if (_default.ptr) {
49 if ( _default.is_node()) {
50 _default.set_node(node->_default.node->duplicate(recursive, use_count, duplicate_leaf));
51
52 _default.set_parent(this);
53 } else {
54 if (duplicate_leaf) {
55 _default.set_leaf(_default.leaf->duplicate(use_count));
56 _default.set_parent(this);
57 } else {
58 _default.set_leaf(_default.leaf);
59 }
60 }
61 }
62
63 NodeIterator it = node->iterator();
64 FlowNodePtr* child;
65 while ((child = it.next()) != 0) {
66 if (child->is_leaf()) {
67 if (duplicate_leaf) {
68 FlowControlBlock* new_leaf = child->leaf->duplicate(use_count);
69 new_leaf->parent = this;
70 add_leaf(child->data(),new_leaf);
71 } else {
72 add_leaf(child->data(),child->leaf);
73 }
74 } else {
75 FlowNode* new_node = child->node->duplicate(recursive, use_count, duplicate_leaf);
76 new_node->set_parent(this);
77 add_node(child->data(),new_node);
78 }
79 }
80#if DEBUG_CLASSIFIER
81 this->assert_diff(node);
82#endif
83 }
84 }
85
90 inline bool _leaf_reverse_match(FlowControlBlock* &leaf, Packet* &p) {
91 flow_assert(level());
92 if (default_ptr()->ptr == leaf) { //If default, we need to check it does not match any non-default
93#if DEBUG_CLASSIFIER_MATCH > 1
94 click_chatter("%d -> %p %p",level()->get_data(p),this->find_or_default(level()->get_data(p))->ptr,leaf);
95#endif
96 return this->find_or_default(level()->get_data(p))->ptr == leaf;
97 } else {
98 return level()->get_data(p).equals(leaf->get_data());
99 }
100 }
101
105 inline bool _node_reverse_match(FlowNode* &child, Packet* &p) {
106 if (default_ptr()->ptr == child) //If default, we need to check it does not match any non-default
107 return this->find_or_default(level()->get_data(p))->ptr == child;
108 else
109 return level()->get_data(p).equals(child->node_data);
110 }
111
116 void assert_diff(FlowNode* node) {
117 assert(node->level() != this->level());
118 FlowNode::NodeIterator it = this->iterator();
119 FlowNode::NodeIterator ito = node->iterator();
120 FlowNodePtr* child;
121 FlowNodePtr* childo;
122 while ((child = it.next()) != 0) {
123 childo = ito.next();
124 assert(child != childo);
125 assert(child->is_leaf() == childo->is_leaf());
126 if (child->is_leaf()) {
127 } else {
128 child->node->assert_diff(childo->node);
129 }
130 }
131 assert(this->default_ptr() != node->default_ptr());
132 }
133
134public:
135 FlowNodeData node_data;
136
137#if DEBUG_CLASSIFIER
138 Bitvector threads;
139#endif
140
145 virtual void destroy() {
146 delete this;
147 }
148
149
150 FlowNode() : num(0), _level(0), _default(), _parent(0), _growing(false), node_data()
151#if FLOW_KEEP_STRUCTURE
152 ,_released(false)
153#endif
154 {
155 }
156
157 static FlowNode* create_hash(int l);
158 FlowLevel* level() const {
159 return _level;
160 }
161
162 void set_level(FlowLevel* level) {
163 _level = level;
164 }
165
166 inline void add_node(FlowNodeData data, FlowNode* node) {
167 bool need_grow;
168 FlowNodePtr* ptr = _find(this,data,need_grow);
169 if (ptr->ptr != 0) {
170 click_chatter("FATAL ERROR : Adding node to an existing node");
171 print();
172 node->print();
173 flow_assert(ptr->ptr == 0);
174 }
175 inc_num();
176 ptr->set_node(node);
177 ptr->set_data(data);
178 }
179
180 inline void add_leaf(FlowNodeData data, FlowControlBlock* leaf) {
181 bool need_grow;
182 FlowNodePtr* ptr = _find(this,data,need_grow);
183 flow_assert(ptr->ptr == 0);
184 inc_num();
185 ptr->set_leaf(leaf);
186 ptr->set_data(data);
187 }
188
192 void apply(std::function<void(FlowNodePtr*)> fnt);
196 void apply_default(std::function<void(FlowNodePtr*)> fnt);
197
198 FlowNode* combine(FlowNode* other, bool as_child, bool priority, bool duplicate_leaf, Element* origin) CLICK_WARN_UNUSED_RESULT;
199 void __combine_child(FlowNode* other, bool priority, bool duplicate_leaf, Element* origin);
200 void __combine_else(FlowNode* other, bool priority, bool duplicate_leaf, Element* origin);
201 FlowNodePtr prune(FlowLevel* level,FlowNodeData data, bool inverted, bool &changed) CLICK_WARN_UNUSED_RESULT;
202
203 FlowNode* find_node(FlowNode* other);
204
205 virtual FlowNode* duplicate(bool recursive, int use_count, bool duplicate_leaf) = 0;
206
207 void assign(FlowNode* node) {
208 _level = node->_level;
209 _parent = node->_parent;
210 _default = node->_default;
211 }
212
213 int getNum() const { return num; };
214
215 //To use for testing purposes only
216 int findGetNum();
217
218 virtual ~FlowNode() {
219/* if (_default.ptr && _default.is_node()) {
220 click_chatter("%p", _default.node);
221 delete _default.node;
222 }*/
223 //Default may be referenced multiple times in dynamics, TODO: delete from somewhere else
224 };
225
226#if FLOW_KEEP_STRUCTURE
227 inline bool released() const {
228 return _released;
229 }
230
231 inline void release() {
232 flow_assert(!growing());
233 _released = true;
234#if DEBUG_CLASSIFIER
235 apply([](FlowNodePtr* p) {
236 if (p->ptr && p->is_node()) {
237#if FLOW_KEEP_STRUCTURE
238 flow_assert(p->node->released());
239#endif
240 }
241 });
242#endif
243 };
244
245#endif
246
247 inline FlowNodePtr* find(FlowNodeData data, bool &need_grow) {
248 return _find((void*)this,data,need_grow);
249 }
250
251
252 inline FlowNodePtr* find_or_default(const FlowNodeData data) {
253 bool need_grow;
254 FlowNodePtr* ptr = _find(this,data,need_grow);
255 if (ptr->ptr == 0
256#if FLOW_KEEP_STRUCTURE
257 || (ptr->is_node() && ptr->node->released())
258#endif
259 )
260 return default_ptr();
261 return ptr;
262 }
263
264 void inc_num() {
265 num++;
266 }
267
268 void dec_num() {
269 num--;
270 }
271
272 inline FlowNode* parent() const {
273 return _parent;
274 }
275
276 inline FlowNodePtr get_default() {
277 return _default;
278 }
279
280 inline FlowNodePtr* default_ptr() {
281 return &_default;
282 }
283
284
285 inline void set_default(FlowNodePtr ptr) {
286 if (ptr.ptr) {
287 flow_assert(ptr.ptr != this);
288 _default = ptr;
289 _default.set_parent(this);
290 }
291 flow_assert(_default.ptr == ptr.ptr);
292 }
293
294
295 inline void set_default(FlowNode* node) {
296 flow_assert(_default.ptr == 0);
297 flow_assert(node != this);
298 _default.ptr = node;
299 node->set_parent(this);
300 }
301
302 virtual void release_child(FlowNodePtr fl, FlowNodeData data) = 0;
303
304#if FLOW_KEEP_STRUCTURE
305 inline void renew() {
306 _released = false;
307 }
308#endif
309
310 virtual String name() const = 0;
311
312 class NodeIteratorBase {
313 public:
314 virtual ~NodeIteratorBase() = default;
315 virtual FlowNodePtr* next() = 0;
316 };
317
318 class NodeIterator {
319 private:
320 NodeIteratorBase* _base;
321 public:
322 NodeIterator(NodeIteratorBase* b) {
323 _base = b;
324 }
325 ~NodeIterator(){
326 delete _base;
327 }
328 FlowNodePtr* next() {
329 return _base->next();
330 }
331 NodeIterator operator=(const NodeIterator& it) {
332 NodeIterator nit(it._base);
333 _base = 0;
334 return nit;
335 }
336 };
337
338 FlowNode* root() {
339 FlowNode* p = _parent;
340 while (p->parent() != 0) {
341 p = p->parent();
342 }
343 return p;
344 }
345 virtual NodeIterator iterator() = 0;
346
347 inline void set_parent(FlowNode* parent) {
348 _parent = parent;
349 }
350
351
352 bool growing() const {
353 return _growing;
354 }
355
356 void set_growing(bool g) {
357 //assert(g); //There is no stopping of growing, when it stops, the table should be deleted,well we reset it also
358 _growing = g;
359 }
360 FlowNode* start_growing(bool impl);
361
362#if DEBUG_CLASSIFIER || DEBUG_CLASSIFIER_CHECK
363 void check(bool allow_parent = false, bool allow_default=true, bool multithread=false);
364#else
365 inline void check(bool allow_parent = false, bool allow_default=true) {};
366#endif
367
368 virtual FlowNode* optimize(Bitvector threads) CLICK_WARN_UNUSED_RESULT;
369
370 void traverse_all_leaves(std::function<void(FlowNodePtr*)> fnt, bool do_final, bool do_default);
371
372 void traverse_all_leaves_and_empty_default(std::function<void(FlowNodePtr*,FlowNode*)> fnt, bool do_final, bool do_default);
373
374 bool traverse_all_default_leaf(std::function<bool(FlowNode*)> fnt);
375
376 bool traverse_all_nodes(std::function<bool(FlowNode*)> fnt);
377
378 void traverse_parents(std::function<bool(FlowNode*)> fnt);
379
380 void traverse_parents(std::function<void(FlowNode*)> fnt);
381
382 bool is_dummy();
383
384 bool is_full_dummy();
385
386 bool has_no_default(bool allow_dynamic = false);
387
388 void reverse_print();
389 static void print(const FlowNode* node,String prefix,int data_offset = -1, bool show_ptr = true, bool recursive=true, bool do_release = true);
390
391 static Spinlock printlock;
392 inline void print(int data_offset = -1, bool show_ptr = true, bool recursive = true, bool do_release = true) const {
393#if DEBUG_CLASSIFIER > 2
394 printlock.acquire();
395#endif
396 click_chatter("---");
397 print(this,"", data_offset, show_ptr, recursive, do_release);
398 click_chatter("---");
399#if DEBUG_CLASSIFIER > 2
400 printlock.release();
401#endif
402 }
403#if DEBUG_CLASSIFIER
404 void debug_print(int data_offset = -1) const {
405 print(data_offset,true);
406 }
407#else
408 void debug_print(int = -1) const {}
409#endif
410private:
411 void leaf_combine_data(FlowControlBlock* leaf, bool do_final, bool do_default, Element* origin);
412 void leaf_combine_data_create(FlowControlBlock* leaf, bool do_final, bool do_default, bool discard_my_data, Element* origin);
413 FlowNodePtr prune(FlowNode* parent, FlowNodeData data);
414 FlowNodePtr prune_with_parent(FlowNode* parent, FlowNodeData data, bool was_default);
415 FlowNode* replace_leaves(FlowNode* other, bool do_final, bool do_default, bool discard_my_fcb_data, Element* origin);
416 friend class FlowClassificationTable;
417 friend class FlowNodePtr;
418 friend class FlowNodeDefinition;
419
420template <typename T, int POOL_SIZE, int POOL_COUNT>
421 friend class pool_allocator_aware_mt;
422
423template<class T>
424 friend class FlowAllocator;
425};
426
427
/*
431class FlowNodeList : public FlowNode {
432 std::list<FlowNode*> children;
433 int highwater = 16;
434public:
435
436 FlowNodeList() {};
437
438 FlowNode* find(FlowNodeData data) {
439
440 for (auto it = children.begin();it != children.end(); it++)
441 if ((*it)->data == data)
442 return *it;
443 return NULL;
444 }
445
446 void set(uint32_t data, FlowNode* fl) {
447 children.push_back(fl);
448 num++;
449 if (_child_deletable && num > highwater) {
450
451 int freed = 0;
452 for (auto it = children.begin();it != children.end(); it++) {
453
454 if ((*it)->released()) {
455 _remove((*it));
456 freed++;
457 }
458 }
459 if (!freed) highwater += 16;
460 }
461 }
462
463
464 void _remove(FlowNode* child) {
465 delete child;
466 children.remove(child);
467 num--;
468 }
469
470 virtual void release_child(FlowNode* child, FlowNodeData data) {
471 _remove(child);
472 }
473
474 virtual ~FlowNodeList() {
475 //click_chatter("Delete list");
476 for (auto it = children.begin(); it != children.end(); it++)
477 delete (*it);
478 }
479};*/
480
484class FlowNodeHeap: public FlowNode {
485 Vector<FlowNodePtr> children;
486
487public:
488
489 FlowNodeHeap() {
490 _find = &find_ptr;
491 }
492
493 void append_heap(FlowNode* fn,Vector<uint32_t>& vls, int i, int v_left, int v_right);
494 void initialize(FlowNode*);
495
496 FLOW_NODE_DEFINE(FlowNodeHeap,find_heap);
497
498#define left_idx(i) (i*2 + 1)
499#define right_idx(i) (i*2 + 2)
500
501 inline FlowNodePtr* find_heap(FlowNodeData data, bool &need_grow) {
502 int i = 0;
503 while (FLOW_INDEX(children,i).ptr) {
504 uint32_t cd = FLOW_INDEX(children,i).data().data_32;
505 if (cd == data.data_32)
506 return &FLOW_INDEX(children,i);
507 else if (cd < data.data_32) {
508 i = right_idx(i);
509 } else {
510 i = left_idx(i);
511 }
512 }
513 return &FLOW_INDEX(children,i);
514 }
515
516 String name() const {
517 return "HEAP";
518 }
519
520 void release_child(FlowNodePtr child, FlowNodeData data) override {
521 click_chatter("TODO : release child heap");
522 abort();
523 }
524
526
527 FlowNode* duplicate(bool recursive, int use_count, bool duplicate_leaf) override;
528
529 class HeapNodeIterator : public NodeIteratorBase {
530 FlowNodeHeap* _node;
531 int cur;
532 public:
533 HeapNodeIterator(FlowNodeHeap* n) : cur(0) {
534 _node = n;
535 }
536
537 FlowNodePtr* next() {
538 do {
539 if (cur >= _node->children.size())
540 return 0;
541 if (_node->children[cur].ptr)
542 return &_node->children[cur++];
543 cur++;
544 }
545 while (1);
546 }
547 };
548
549 NodeIterator iterator() override {
550 return NodeIterator(new HeapNodeIterator(this));
551 }
552};
553
554
558class FlowNodeArray : public FlowNode {
559 Vector<FlowNodePtr> children;
560
561public:
562 void destroy() override;
563
564 FlowNodeArray() {
565 _find = &find_ptr;
566 }
567
568 void initialize(unsigned int max_size) {
569 children.resize(max_size);
570 }
571
572 FLOW_NODE_DEFINE(FlowNodeArray,find_array);
573
574 inline FlowNodePtr* find_array(FlowNodeData data, bool &need_grow) {
575 return &FLOW_INDEX(children,data.data_32);
576 }
577
578 String name() const {
579 return "ARRAY";
580 }
581 void release_child(FlowNodePtr child, FlowNodeData data) override;
582
583
585
586 FlowNode* duplicate(bool recursive, int use_count, bool duplicate_leaf) override;
587
588 class ArrayNodeIterator : public NodeIteratorBase {
589 FlowNodeArray* _node;
590 int cur;
591 public:
592 ArrayNodeIterator(FlowNodeArray* n) : cur(0) {
593 _node = n;
594 }
595
596 FlowNodePtr* next() {
597 do {
598 if (cur >= _node->children.size())
599 return 0;
600 if (_node->children[cur].ptr)
601 return &_node->children[cur++];
602 cur++;
603 }
604 while (1);
605 }
606 };
607
608 NodeIterator iterator() override {
609 return NodeIterator(new ArrayNodeIterator(this));
610 }
611};
612
613static const uint8_t HASH_SIZES_NR = 10;
614
615//const int FlowNodeHash::hash_sizes[FlowNodeHash::HASH_SIZES_NR] = {256,512,1024,2048,4096,8192};
616
617
621template<int capacity_n>
622class FlowNodeHash : public FlowNode {
623
624#if FLOW_HASH_RELEASE == RELEASE_EPOCH
625 uint64_t epoch;
626 #define MAX_EPOCH 16777216
627 #define SET_DESTRUCTED_NODE(ptr,parent) (ptr = (void*)parent->epoch)
628 #define IS_EMPTY_PTR(ptr,parent) ((uint64_t)ptr < parent->epoch)
629 #define IS_DESTRUCTED_PTR(ptr,parent) ((uint64_t)ptr == parent->epoch)
630 #define IS_FREE_PTR(ptr,parent) ((uint64_t)ptr <= parent->epoch)
631 #define IS_FREE_PTR_ANY(ptr) ((uint64_t)ptr < MAX_EPOCH)
632#else
633 #define IS_EMPTY_PTR(ptr,parent) (ptr == 0)
634# if HAVE_FLOW_DYNAMIC
635 #define DESTRUCTED_NODE (void*)1
636 #define IS_FREE_PTR(ptr,parent) (IS_EMPTY_PTR(ptr,parent) || IS_DESTRUCTED_PTR(ptr,parent))
637 #define IS_FREE_PTR_ANY(ptr) (!((uintptr_t)ptr & (uintptr_t)-2))
638# else
639 #define DESTRUCTED_NODE (void*)0
640 #define IS_FREE_PTR(ptr,parent) (IS_EMPTY_PTR(ptr,parent))
641 #define IS_FREE_PTR_ANY(ptr) (ptr == 0)
642# endif
643 #define SET_DESTRUCTED_NODE(ptr,parent) (ptr = DESTRUCTED_NODE)
644 #define IS_DESTRUCTED_PTR(ptr,parent) (ptr == DESTRUCTED_NODE)
645#endif
646 #define IS_VALID_PTR(ptr,parent) (!IS_FREE_PTR(ptr,parent))
647 #define IS_VALID_NODE(pptr,parent) (IS_VALID_PTR(pptr.ptr,parent) && pptr.is_node())
648
649 static constexpr uint32_t hash_sizes[HASH_SIZES_NR] = {257,521,1031,2053,4099,8209,16411,32771,65539,131072}; //Prime for less collisions, after the last we double
650 static constexpr uint32_t step_sizes[HASH_SIZES_NR] = { 37, 67, 131, 257, 521,1031, 2053, 4099, 8209, 16411}; //Prime for less collisions, after the last we double
651
652
656 inline static constexpr uint32_t capacity() {
657 return hash_sizes[capacity_n];
658 }
659
663 inline static constexpr uint32_t step() {
664 return step_sizes[capacity_n];
665 }
666
667 FlowNodePtr children[capacity()];
668
669 inline constexpr uint32_t max_highwater() const {
670 return 3 * (capacity() / 5);
671 }
672
673 inline constexpr uint32_t collision_threshold() const {
674 return ((capacity() / 20) > 32 ? 32 : capacity()/20);
675 }
676
677 inline constexpr uint32_t hole_threshold() const {
678 return ((capacity() / 30) > 24 ? 24 : capacity()/30);
679 }
680
681 unsigned int hash32(uint32_t d) const {
682 return ((d << 3) + (d >> 9) + (d >> 12) + (d >> 25)) % capacity();
683 }
684
685#if HAVE_LONG_CLASSIFICATION
686 unsigned int hash64(uint64_t ld) const {
687 uint32_t d = (uint32_t)ld ^ (ld >> 32);
688 return ((d << 3) + (d >> 9) + (d >> 12) + (d >> 25)) % capacity();
689 }
690#endif
691
692 inline int next_idx(int idx) const {
693 idx = (idx + step());
694 if (idx >= capacity()) //This is permitied per step() and capacity() invariants
695 return idx - capacity();
696 return idx;
697 }
698
699 inline int prev_idx(int idx) const {
700 idx = (idx - step());
701 if (idx < 0)
702 return idx + capacity();
703 return idx;
704
705 }
706
707
708 String name() const {
709 return "HASH-" + String(capacity());
710 }
711
712
713 class HashNodeIterator : public virtual NodeIteratorBase {
714 FlowNodeHash* _node;
715 unsigned cur;
716 public:
717 HashNodeIterator(FlowNodeHash* n) : cur(0) {
718 _node = n;
719 }
720
721 virtual FlowNodePtr* next() override {
722 while (cur < _node->capacity() && (IS_FREE_PTR(_node->children[cur].ptr,_node))) {
723 cur++;
724 }
725 if (cur >= _node->capacity())
726 return 0;
727 return &_node->children[cur++];
728 }
729 };
730
731 void destroy() override;
732
733 //Resizing is now done by the growing system
734 void resize() {
735 /*
736 int current_size = hash_size;
737 if (size_n < HASH_SIZES_NR)
738 hash_size = hash_sizes[size_n];
739 else {
740 hash_size *= 2;
741 }
742 mask = hash_size - 1;
743
744 highwater = hash_size / 3;
745 max_highwater = hash_size / 2;
746 click_chatter("New hash table size %d",hash_size);
747
748 Vector<FlowNodePtr> children_old = children;
749 children.resize(hash_size);
750 num = 0;
751
752 for (int i = 0; i < current_size; i++) {
753 children[i].ptr= NULL;
754 }
755 size_n++;
756 for (int i = 0; i < current_size; i++) {
757 if (children_old[i].ptr) {
758 if (children_old[i].is_leaf()) {
759 GET IDX CANNOT BE USED FOR OLD
760 children[get_idx(children_old[i].data())] = children_old[i];
761 } else {
762 if (children_old[i].node->released()) {
763 delete children_old[i].node;
764 } else {
765 children[get_idx(children_old[i].data())] = children_old[i];
766 }
767 }
768 }
769 }*/
770 }
771
772 public:
774#if FLOW_HASH_RELEASE == RELEASE_EPOCH
775 : epoch(1)
776#endif
777 {
778 _find = &find_ptr;
779#if DEBUG_CLASSIFIER
780 for (int i = 0; i < capacity(); i++) {
781 flow_assert(children[i].ptr == NULL);
782 }
783#endif
784 };
785 virtual FlowNode* duplicate(bool recursive, int use_count, bool duplicate_leaf) override;
786
787 FLOW_NODE_DEFINE(FlowNodeHash,find_hash);
788
789 static uint32_t capacity_for(int level) {
790 return level << (8+level);
791 }
792
793 FlowNodePtr* find_hash(FlowNodeData data, bool &need_grow);
794
795 void release_child(FlowNodePtr child, FlowNodeData data);
796
797 virtual ~FlowNodeHash() override;
798
799 NodeIterator iterator() override {
800 return NodeIterator(new HashNodeIterator(this));
801 }
802};
803
804
805
806
810class FlowNodeDummy : public FlowNode {
811
812 class DummyIterator : public NodeIteratorBase{
813 FlowNode* _node;
814 public:
815 DummyIterator(FlowNode* n) {
816 _node = n;
817 }
818
819 FlowNodePtr* next() {
820 return 0;
821 }
822 };
823
824 public:
825
826 String name() const {
827 return "DUMMY";
828 }
829
830 FlowNode* duplicate(bool recursive, int use_count, bool duplicate_leaf) override {
831 FlowNodeDummy* fh = new FlowNodeDummy();
832 fh->duplicate_internal(this,recursive,use_count, duplicate_leaf);
833 return fh;
834 }
835
836 FlowNodeDummy() {
837 _find = &find_ptr;
838 }
839 FLOW_NODE_DEFINE(FlowNodeDummy,find_dummy);
840
841 void release_child(FlowNodePtr child, FlowNodeData data) override {
842 click_chatter("TODO : release child of flow node dummy");
843 assert(false);
844 }
845
846 FlowNodePtr* find_dummy(FlowNodeData data, bool&) {
847 return &_default;
848 }
849
850 virtual ~FlowNodeDummy() {
851 }
852
853 NodeIterator iterator() override {
854 return NodeIterator(new DummyIterator(this));
855 }
856};
857
861class FlowNodeTwoCase : public FlowNode {
862 FlowNodePtr child;
863
864 class TwoCaseIterator : public NodeIteratorBase{
865 FlowNodeTwoCase* _node;
866 int cur;
867 public:
868 TwoCaseIterator(FlowNodeTwoCase* n) : cur(0) {
869 _node = n;
870 }
871
872 FlowNodePtr* next() {
873 if (cur++ == 0)
874 return &_node->child;
875 else
876 return 0;
877 }
878 };
879
880 public:
881 String name() const {
882 return "TWOCASE";
883 }
884
885 FlowNode* duplicate(bool recursive, int use_count, bool duplicate_leaf) override {
886 FlowNodeTwoCase* fh = new FlowNodeTwoCase(child);
887 fh->duplicate_internal(this,recursive,use_count, duplicate_leaf);
888 return fh;
889 }
890
891 FlowNodeTwoCase(FlowNodePtr c) : child(c) {
892 c.set_parent(this);
893 _find = &find_ptr;
894 }
895 FLOW_NODE_DEFINE(FlowNodeTwoCase,find_two);
896
897 FlowNodePtr* find_two(FlowNodeData data, bool&) {
898 if (data.equals(child.data()))
899 return &child;
900 else
901 return &_default;
902 }
903
904 void release_child(FlowNodePtr child, FlowNodeData data) override {
905 click_chatter("TODO : release two case");
906 /*if (child_deletable()) {
907 if (is_leaf()) {
908 children[get_idx(child.data())].ptr = NULL;
909 num--;
910 } else {
911 child.node->release();;
912 num--;
913 }
914 }*/
915 assert(false);
916 }
917
918 virtual ~FlowNodeTwoCase() {
919 if (child.ptr && child.is_node())
920 child.node->destroy();
921 }
922
923 NodeIterator iterator() override {
924 return NodeIterator(new TwoCaseIterator(this));
925 }
926};
927
931class FlowNodeThreeCase : public FlowNode {
932 FlowNodePtr childA;
933 FlowNodePtr childB;
934
935 class ThreeCaseIterator : public NodeIteratorBase {
936 FlowNodeThreeCase* _node;
937 int cur;
938 public:
939 ThreeCaseIterator(FlowNodeThreeCase* n) : cur(0) {
940 _node = n;
941 }
942
943 FlowNodePtr* next() {
944
945 FlowNodePtr* ptr = 0;
946 if (cur == 0)
947 ptr = &_node->childA;
948 else if (cur == 1)
949 ptr = &_node->childB;
950 else
951 ptr = 0;
952 cur ++;
953 return ptr;
954 }
955 };
956
957 public:
958 String name() const {
959 return "THREECASE";
960 }
961
962 FlowNode* duplicate(bool recursive, int use_count, bool duplicate_leaf) override {
963 FlowNodeThreeCase* fh = new FlowNodeThreeCase(childA,childB);
964 fh->duplicate_internal(this,recursive,use_count, duplicate_leaf);
965 return fh;
966 }
967
968 FlowNodeThreeCase(FlowNodePtr a,FlowNodePtr b) : childA(a),childB(b) {
969 a.set_parent(this);
970 b.set_parent(this);
971 _find = &find_ptr;
972 }
973 FLOW_NODE_DEFINE(FlowNodeThreeCase,find_three);
974
975 FlowNodePtr* find_three(FlowNodeData data, bool&) {
976 if (data.equals(childA.data()))
977 return &childA;
978 else if (data.equals(childB.data()))
979 return &childB;
980 else
981 return &_default;
982 }
983
984 void release_child(FlowNodePtr child, FlowNodeData data) override {
985 click_chatter("TODO renew release threecase");
986 /*if (child_deletable()) {
987 if (is_leaf()) {
988 children[get_idx(child.data())].ptr = NULL;
989 num--;
990 } else {
991 child.node->release();;
992 num--;
993 }
994 }*/
995 assert(false);
996 }
997
998 virtual ~FlowNodeThreeCase() {
999 if (childA.ptr && childA.is_node())
1000 childA.node->destroy();
1001 if (childB.ptr && childB.is_node())
1002 childB.node->destroy();
1003 }
1004
1005 NodeIterator iterator() override {
1006 return NodeIterator(new ThreeCaseIterator(this));
1007 }
1008};
1009
1014class FlowNodeDefinition : public FlowNodeHash<HASH_SIZES_NR - 1> { public:
1015 bool _else_drop;
1016 String _hint;
1017 Element* _creator;
1018
1019 FlowNodeDefinition(Element* creator) : _else_drop(false), _hint(String::make_empty()), _creator(creator) {
1020
1021 }
1022
1023 String name() const {
1024 return String("DEFINITION") + (_else_drop?"!":"");
1025 }
1026
1027 FlowNodeDefinition* duplicate(bool recursive,int use_count, bool duplicate_leaf) override;
1028
1029 FlowNode* create_final(Bitvector threads);
1030};
1031
1032inline void FlowNodePtr::traverse_all_leaves(std::function<void(FlowNodePtr*)> fnt) {
1033 if (is_leaf()) {
1034 fnt(this);
1035 } else {
1036 node->traverse_all_leaves(fnt,true,true);
1037 }
1038}
1039
1040inline void FlowNodePtr::check() {
1041 if (!is_leaf())
1042 node->check();
1043}
1044
1045
1046#define POOL_SZ 4096
1047#define EXCH_MAX 1024
1048
1052template<class T>
1053class FlowAllocator { public:
1056 flow_assert(instance.weight() == click_max_cpu_ids());
1057 flow_assert(instance->initialized());
1058 return instance;
1059 }
1060
1061 static T* allocate() {
1062 T* v = instance()->allocate_uninitialized();
1063 flow_assert(v->_default.ptr == 0);
1064 flow_assert(!v->growing());
1065 flow_assert(v->num == 0);
1066 flow_assert(v->_find);
1067
1068#if FLOW_KEEP_STRUCTURE
1069 flow_assert(!v->released());
1070#endif
1071 return v;
1072 }
1073
1074 static void release(T* e) {
1075 flow_assert(pool_allocator_mt_base::dying() || e->num == 0);
1076 flow_assert(!e->growing());
1077 instance()->release_unitialized(e);
1078 }
1079};
1080
1081#endif
Vector of bits.
Definition bitvector.hh:21
Base class for Click elements.
Definition element.hh:42
Definition flow_nodes.hh:1053
Definition flow_nodes.hh:558
void destroy() override
Definition flownode.cc:618
~FlowNodeArray()
Definition flownode.cc:627
Definition flow_nodes.hh:1014
FlowNode * create_final(Bitvector threads)
Definition flownode.cc:447
Definition flow_nodes.hh:810
Definition flow_nodes.hh:622
virtual ~FlowNodeHash() override
Definition flownode.cc:704
void release_child(FlowNodePtr child, FlowNodeData data)
Definition flownode.cc:826
Definition flow_nodes.hh:484
~FlowNodeHeap()
Definition flownode.cc:592
Definition flow_nodes.hh:931
Definition flow_nodes.hh:861
A network packet.
Definition packet.hh:68
A recursive spinlock for SMP Click threads.
Definition sync.hh:439
void release()
Releases the Spinlock.
Definition sync.hh:534
void acquire()
Acquires the Spinlock.
Definition sync.hh:488
A string of characters.
Definition string.hh:22
static const String & make_empty()
Return a const reference to an empty String.
Definition string.hh:439
Vector template.
Definition vector.hh:111
void resize(size_type n, value_argument_type v=T())
Resize the vector to contain n elements.
Definition vector.hh:390
size_type size() const
Return the number of elements.
Definition vector.hh:231
Definition sync.hh:57
unsigned weight() const
Definition sync.hh:203
Click's StringAccum class, used to construct Strings efficiently from pieces.