xorp

dispatcher.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 // vim:set sts=4 ts=8:
00003 
00004 // Copyright (c) 2001-2011 XORP, Inc and Others
00005 //
00006 // This program is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License, Version 2, June
00008 // 1991 as published by the Free Software Foundation. Redistribution
00009 // and/or modification of this program under the terms of any other
00010 // version of the GNU General Public License is not permitted.
00011 // 
00012 // This program is distributed in the hope that it will be useful, but
00013 // WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00015 // see the GNU General Public License, Version 2, a copy of which can be
00016 // found in the XORP LICENSE.gpl file.
00017 // 
00018 // XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00019 // http://xorp.net
00020 
00021 // $XORP: xorp/policy/common/dispatcher.hh,v 1.15 2008/10/02 21:58:06 bms Exp $
00022 
00023 #ifndef __POLICY_COMMON_DISPATCHER_HH__
00024 #define __POLICY_COMMON_DISPATCHER_HH__
00025 
00026 
00027 
00028 
00029 
00030 
00031 #include "policy/policy_module.h"
00032 #include "libxorp/xlog.h"
00033 #include "element_base.hh"
00034 #include "operator_base.hh"
00035 #include "register_operations.hh"
00036 #include "policy_exception.hh"
00037 
00049 class Dispatcher {
00050 public:
00051     typedef vector<const Element*> ArgList;
00052 
00053     Dispatcher();
00054 
00060     class OpNotFound : public PolicyException {
00061     public:
00062     OpNotFound(const char* file, size_t line, const string& init_why = "")   
00063         : PolicyException("OpNotFound", file, line, init_why) {}
00064     };
00065 
00074     template<class L, class R, Element* (*funct)(const L&,const R&)>
00075     void add(const BinOper& op)
00076     {
00077         // XXX: do it in a better way
00078         L arg1;
00079         R arg2;
00080 
00081     const Element* args[] = { &arg1, &arg2 };
00082 
00083         Key key = makeKey(op, 2, args);
00084 
00085         struct Local {
00086             static Element* Trampoline(const Element& left, const Element& right)
00087         {
00088                 return funct(static_cast<const L&>(left),
00089                              static_cast<const R&>(right));
00090             }
00091         };
00092 
00093         _map[key].bin = &Local::Trampoline;
00094     }
00095 
00103     template<class T, Element* (*funct)(const T&)>
00104     void add(const UnOper& op)
00105     {
00106     // XXX: ugly
00107     T arg;
00108 
00109     const Element* args[] = { &arg };
00110 
00111         Key key = makeKey(op, 1, args);
00112 
00113         struct Local {
00114         static Element* Trampoline(const Element& arg) {
00115                 return funct(static_cast<const T&>(arg));
00116             }
00117         };
00118 
00119         _map[key].un = &Local::Trampoline;
00120     }
00121 
00131     Element* run(const Oper& op, unsigned argc, const Element** argv) const;
00132 
00140     Element* run(const UnOper& op, const Element& arg) const;
00141     
00150     Element* run(const BinOper& op, 
00151          const Element& left, 
00152          const Element& right) const;
00153 
00154 private:
00155     // Callback for binary operation
00156     typedef Element* (*CB_bin)(const Element&, const Element&);
00157     
00158     // Callback for unary operation
00159     typedef Element* (*CB_un)(const Element&);
00160 
00161     // Key which relates to a callback
00162     typedef unsigned Key;
00163 
00164     // A key relates to either a binary (x)or unary operation.
00165     typedef union {
00166     CB_un un;
00167         CB_bin bin;
00168     } Value;
00169 
00170     // Hashtable would be better
00171     typedef map<Key,Value> Map;
00172 
00180     Key makeKey(const Oper& op, unsigned argc, const Element** argv) const
00181     {
00182     XLOG_ASSERT(op.arity() == argc);
00183     XLOG_ASSERT(argc <= 2);
00184 
00185     unsigned key = 0;
00186 
00187     key |= op.hash();
00188     XLOG_ASSERT(key);
00189 
00190     for (unsigned i = 0; i < argc; i++) {
00191         const Element* arg = argv[i];
00192         unsigned eh = arg->hash();
00193 
00194         XLOG_ASSERT(eh);
00195 
00196         key |= eh << (5*(i+1));
00197     }
00198 
00199     return key;
00200     }
00201 
00202     // XXX: definition moved in header file to allow compilation on 2.95.x
00211     Value lookup(const Oper& op, unsigned argc, const Element** argv) const
00212     {
00213     XLOG_ASSERT(op.arity() == argc);
00214 
00215         // find callback
00216         Key key = makeKey(op, argc, argv);
00217         return _map[key];
00218     }
00219 
00220     // Only one global map. Creating multiple dispatcher is thus harmless.
00221     // However, we may not have different dispatchers.
00222     static Value _map[32768];
00223 };
00224 
00225 #endif // __POLICY_COMMON_DISPATCHER_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations