Source: ../../policy/common/dispatcher.hh
|
|
|
|
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// vim:set sts=4 ts=8:
// Copyright (c) 2001-2009 XORP, Inc.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, Version 2, June
// 1991 as published by the Free Software Foundation. Redistribution
// and/or modification of this program under the terms of any other
// version of the GNU General Public License is not permitted.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
// see the GNU General Public License, Version 2, a copy of which can be
// found in the XORP LICENSE.gpl file.
//
// XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
// http://xorp.net
// $XORP: xorp/policy/common/dispatcher.hh,v 1.16 2009/01/05 18:31:06 jtc Exp $
#ifndef __POLICY_COMMON_DISPATCHER_HH__
#define __POLICY_COMMON_DISPATCHER_HH__
#include <string>
#include <sstream>
#include <map>
#include <vector>
#include "policy/policy_module.h"
#include "libxorp/xlog.h"
#include "element_base.hh"
#include "operator_base.hh"
#include "register_operations.hh"
#include "policy_exception.hh"
/**
* @short Link between elements and operations. Executes operations on elments.
*
* Implementation of multimethods.
* Insipred/copied from Alexandrescu [Modern C++ Design].
*
* By taking base element arguments and an operation, it will execute the
* correct operation based on the concrete type of the arguments.
*
* Similar to an ElementFactory.
*/
class Dispatcher {
public:
typedef vector<const Element*> ArgList;
Dispatcher();
/**
* @short Exception thrown if no operation is found for given arguments.
*
* If there is no combination for the given operation and element types.
*/
class OpNotFound : public PolicyException {
public:
OpNotFound(const char* file, size_t line, const string& init_why = "")
: PolicyException("OpNotFound", file, line, init_why) {}
};
/**
* Method to register a binary operation callback with dispatcher.
*
* @param L concrete class of first argument
* @param R concrete class of second argument
* @param funct function to be called to perform operation.
* @param op binary operation to be registered.
*/
template<class L, class R, Element* (*funct)(const L&,const R&)>
void add(const BinOper& op)
{
// XXX: do it in a better way
L arg1;
R arg2;
const Element* args[] = { &arg1, &arg2 };
Key key = makeKey(op, 2, args);
struct Local {
static Element* Trampoline(const Element& left, const Element& right)
{
return funct(static_cast<const L&>(left),
static_cast<const R&>(right));
}
};
_map[key].bin = &Local::Trampoline;
}
/**
* Method to register a unary operation callback with dispatcher.
*
* @param T concrete class of argument
* @param funct function to be called to perform operation.
* @param op unary operation to be registered.
*/
template<class T, Element* (*funct)(const T&)>
void add(const UnOper& op)
{
// XXX: ugly
T arg;
const Element* args[] = { &arg };
Key key = makeKey(op, 1, args);
struct Local {
static Element* Trampoline(const Element& arg) {
return funct(static_cast<const T&>(arg));
}
};
_map[key].un = &Local::Trampoline;
}
/**
* Execute an n-ary operation.
*
* Throws an exception on failure.
*
* @return result of operation.
* @param op operation to dispatch.
* @param args arguments of operation.
*/
Element* run(const Oper& op, unsigned argc, const Element** argv) const;
/**
* Execute an unary operation.
*
* @return Result of operation. Caller is responsible for delete.
* @param op Operation to perform.
* @param arg Argument of operation.
*/
Element* run(const UnOper& op, const Element& arg) const;
/**
* Execute a binary operation.
*
* @return result of operation. Caller is responsible for delete.
* @param op Operation to perform.
* @param left first argument.
* @param right second argument.
*/
Element* run(const BinOper& op,
const Element& left,
const Element& right) const;
private:
// Callback for binary operation
typedef Element* (*CB_bin)(const Element&, const Element&);
// Callback for unary operation
typedef Element* (*CB_un)(const Element&);
// Key which relates to a callback
typedef unsigned Key;
// A key relates to either a binary (x)or unary operation.
typedef union {
CB_un un;
CB_bin bin;
} Value;
// Hashtable would be better
typedef map<Key,Value> Map;
/**
* Create a key for the callback table based on operation and arguments.
*
* @return key used for callback lookup.
* @param op requested operation.
* @param args the arguments for the operation.
*/
Key makeKey(const Oper& op, unsigned argc, const Element** argv) const
{
XLOG_ASSERT(op.arity() == argc);
XLOG_ASSERT(argc <= 2);
unsigned key = 0;
key |= op.hash();
XLOG_ASSERT(key);
for (unsigned i = 0; i < argc; i++) {
const Element* arg = argv[i];
unsigned eh = arg->hash();
XLOG_ASSERT(eh);
key |= eh << (5*(i+1));
}
return key;
}
// XXX: definition moved in header file to allow compilation on 2.95.x
/**
* Lookup a callback for the requested operation and elements.
* Throws exception if none is found.
*
* @return callback which will perform requested operation.
* @param op operation to perform.
* @param args the arguments of the operation.
*/
Value lookup(const Oper& op, unsigned argc, const Element** argv) const
{
XLOG_ASSERT(op.arity() == argc);
// find callback
Key key = makeKey(op, argc, argv);
return _map[key];
}
// Only one global map. Creating multiple dispatcher is thus harmless.
// However, we may not have different dispatchers.
static Value _map[32768];
};
#endif // __POLICY_COMMON_DISPATCHER_HH__
Generated by: pavlin on kobe.xorp.net on Wed Jan 7 19:11:01 2009, using kdoc 2.0a54+XORP.