📄 signature.cc
字号:
/* * signature.{cc,hh} -- specializer * Eddie Kohler * * Copyright (c) 2000 Massachusetts Institute of Technology * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include "signature.hh"#include "processingt.hh"#include "toolutils.hh"#include "elementmap.hh"#include <click/error.hh>#include <stdio.h>#include <string.h>// determine an element's signatureSignatures::Signatures(const RouterT *router) : _router(router), _sigid(router->nelements(), 1){}voidSignatures::create_phase_0(const ProcessingT &pt){ _sigs.clear(); _sigs.push_back(SignatureNode(-1)); // not special Vector<ElementClassT *> sig_eclass; sig_eclass.push_back(0); int ne = _router->nelements(); for (int i = 0; i < ne; i++) { if (_sigid[i] == SIG_NOT_SPECIAL) continue; ElementClassT *ec = _router->etype(i); for (int j = 0; j < _sigs.size(); j++) if (sig_eclass[j] == ec && pt.same_processing(i, _sigs[j]._eid)) { _sigid[i] = j; goto found_sigid; } _sigs.push_back(SignatureNode(i)); sig_eclass.push_back(ec); _sigid[i] = _sigs.size() - 1; found_sigid: ; }}voidSignatures::check_port_numbers(int eid, const ProcessingT &pt){ const ElementT *e = _router->element(eid); int old_sigid = _sigid[eid]; if (old_sigid == SIG_NOT_SPECIAL) return; // create new ports array Vector<int> new_ports; int ni = e->ninputs(), no = e->noutputs(); for (int i = 0; i < ni; i++) { const PortT &h = pt.input_connection(eid, i); if (h.element) new_ports.push_back(h.port); } for (int i = 0; i < no; i++) { const PortT &h = pt.output_connection(eid, i); if (h.element) new_ports.push_back(h.port); } // check for no interesting connections if (new_ports.size() == 0) return; // add new node to list if (_sigs[old_sigid]._connections.size() == 0) { // set new from old _sigs[old_sigid]._connections.swap(new_ports); _sigs[old_sigid]._next = -1; return; } // otherwise, search for a match int prev = -1, trav = old_sigid; while (trav >= 0) { if (memcmp(&_sigs[trav]._connections[0], &new_ports[0], new_ports.size() * sizeof(int)) == 0) { _sigid[eid] = trav; return; } prev = trav; trav = _sigs[trav]._next; } // if not found, append _sigs.push_back(SignatureNode(eid)); SignatureNode &new_node = _sigs.back(); new_node._connections.swap(new_ports); _sigid[eid] = _sigs[prev]._next = _sigs.size() - 1;}boolSignatures::next_phase(int phase, int eid, Vector<int> &new_sigid, const ProcessingT &pt){ const ElementT *e = _router->element(eid); int old_sigid = _sigid[eid]; if (old_sigid == SIG_NOT_SPECIAL || _sigs[old_sigid]._connections.size() == 0) { new_sigid[eid] = old_sigid; return false; } // create new connections Vector<int> new_connections; int ni = e->ninputs(), no = e->noutputs(); for (int i = 0; i < ni; i++) { const PortT &h = pt.input_connection(eid, i); if (h.element) new_connections.push_back(_sigid[h.eindex()]); } for (int i = 0; i < no; i++) { const PortT &h = pt.output_connection(eid, i); if (h.element) new_connections.push_back(_sigid[h.eindex()]); } // add new node to list if (_sigs[old_sigid]._phase != phase) { // set new from old _sigs[old_sigid]._phase = phase; _sigs[old_sigid]._connections.swap(new_connections); _sigs[old_sigid]._next = -1; new_sigid[eid] = old_sigid; return false; } // otherwise, search for a match int prev = -1, trav = old_sigid; while (trav >= 0) { if (memcmp(&_sigs[trav]._connections[0], &new_connections[0], new_connections.size() * sizeof(int)) == 0) { new_sigid[eid] = trav; return false; } prev = trav; trav = _sigs[trav]._next; } // if not found, append _sigs.push_back(SignatureNode(eid)); SignatureNode &new_node = _sigs.back(); new_node._phase = phase; new_node._connections.swap(new_connections); new_sigid[eid] = _sigs[prev]._next = _sigs.size() - 1; return true;}voidSignatures::print_signature() const{ fprintf(stderr, "["); for (int i = 0; i < _router->nelements(); i++) { fprintf(stderr, (i ? ", %s %d" : "%s %d"), _router->ename(i).cc(), _sigid[i]); } fprintf(stderr, "]\n");}voidSignatures::specialize_class(const String &eclass_name, bool doit){ for (RouterT::const_type_iterator x = _router->begin_elements(ElementClassT::base_type(eclass_name)); x; x++) _sigid[x->eindex()] = (doit ? 1 : SIG_NOT_SPECIAL);}voidSignatures::analyze(ElementMap &em){ int ne = _router->nelements(); ProcessingT pt(_router, &em, true, 0); // true -> AGNOSTIC becomes PUSH create_phase_0(pt); for (int i = 0; i < ne; i++) check_port_numbers(i, pt); int phase = 0; bool alive = true; Vector<int> new_sigid = _sigid; while (alive) { phase++; alive = false; for (int i = 0; i < ne; i++) alive |= next_phase(phase, i, new_sigid, pt); _sigid.swap(new_sigid); }}// generate Vector template instance#include <click/vector.cc>template class Vector<SignatureNode>;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -