#include <Iguana/Utilities/classlib/utils/MultiMethod.h>
Public Types | |
typedef void(* | MemberFunction )(void) |
Placeholder type for actual method implementations. | |
Protected Member Functions | |
MemberFunction | dispatch (XTypeInfo **actualTypes, Score **candidates, Score *best) const |
void | initialise (Definition *data, STDC::size_t formals, XTypeInfo::ClassDef **formalTypes) |
MultiMethod (void) | |
~MultiMethod (void) | |
Private Types | |
enum | { INITIAL_FAMILY_SIZE = 32 } |
Initial size of the number of member function allocation. More... | |
enum | { SCORE_HUNK_SIZE = 64 } |
The number of Score objects to allocate per ScoreHunk. More... | |
enum | { ENTRY_HUNK_SIZE = 32 } |
The number of Entry objects to allocate per EntryHunk. More... | |
enum | { LAST_SCORE = USHRT_MAX } |
The Score::m_index of the sentinel Score. More... | |
enum | { INFINITE_DISTANCE = USHRT_MAX } |
The Score::m_distance of the sentinel Score. More... | |
Private Member Functions | |
Entry * | allocateEntry (void) const |
Score * | allocateScores (STDC::size_t n) const |
void | ambiguity (XTypeInfo **actuals, Score **candidates, Score *best) const |
void | buildScores (const XTypeInfo *type) const |
void | cleanScores (const XTypeInfo *type) const |
EntryHunk * | createEntryHunk (void) const |
ScoreHunk * | createScoreHunk (STDC::size_t min) const |
void | freeEntry (Entry *item) const |
void | freeEntryHunks (void) const |
void | freeScoreHunks (void) const |
MultiMethod (const MultiMethod &) | |
void | newGeneration (void) const |
void | noViableAlt (XTypeInfo **actuals) const |
MultiMethod & | operator= (const MultiMethod &) |
void | regenerate (const XTypeInfo *type) const |
STDC::size_t | relatedFormal (const XTypeInfo *type) const |
bool | typeClean (STDC::size_t formal, XTypeInfo *type) const |
virtual void | typeHook (XTypeInfo *type) |
void | typePrepare (STDC::size_t formal, XTypeInfo *type) const |
virtual void | typeUnhook (XTypeInfo *type) |
Static Private Member Functions | |
static XTypeInfo::ExtensionKey | extensionKey (void) |
static Entry * | findTypeEntries (const XTypeInfo *type, Entry *&previous, STDC::size_t key, STDC::size_t formal=STDC::size_t(-1)) |
static STDC::size_t | methodKey (void) |
static bool | orderScores (const Score &x, const Score &y) |
Private Attributes | |
Definition * | m_data |
Friends | |
struct | Definition |
struct | Entry |
struct | EntryHunk |
struct | Member |
struct | ScoreHunk |
Classes | |
struct | Definition |
Actual data structure defining the multi-method. More... | |
struct | Entry |
A record of information chained into extended type information. More... | |
struct | EntryHunk |
A hunk of Entry objects. More... | |
struct | Member |
Description of a member belonging to the multi-method. More... | |
struct | Score |
Method scoring information. More... | |
struct | ScoreHunk |
A hunk of Score objects. More... |
This class implements most of the multi-method maintenance and dispatching functionality. Classes derived from this provide the actual interface layer needed for any real use.
Implementation
It can be very space consuming to store the full member matrix when the number of involved classes is large. For example, if there are fifty classes that may participate for each argument position, a three-virtual multi-method results in 125000-cell grid---and the grid is likely to be sparsely populated. It is also expensive in time to store the functions in the family just as a plain list and search on each call (not that computing the full matrix as described above would be cheap either).
This implementation aims for a compromise that is efficient both in space and time. We store only the grid cells that exist and are needed, and in a manner that minimises the search time at method dispatch time. The call overhead is not constant as it would be in a direct matrix lookup, but frequently called family members get close.
For each formal argument position and type involved in the dispatch (and hence inheriting from the virtual argument types of the multi-method), we record a dispatch vector of viable candidate functions: an indication of how far the member's accepted argument is from that actual type in that argument position. During a call, knowing the actual argument types, we look up the dispatch vectors for each argument position and traverse the candidates, looking for a member that is the best candidate in at least one argument position and no worse in any other argument position.
If a winning candidate is found, it is called. If no winning candidate is found, a fatal error is signalled either for no viable alternative or for ambiguity. The rules for these situations are the same as in C++ overload resolution, except that the error will arise only at run-time---it is not possible to diagnose the errors statically. Signalling the error means here printing a diagnostic and calling abort(); there is no way to recover. In particular, no exceptions will be thrown.
Another important feature is that members and participating types can be added to and removed from the method. The method recalculates the dispatch vectors described above only when called, and only for the types (and base types) in the actual arguments given. This on-demand update method therefore never recalculates the call "matrix" if the method is not actually called after the type or member changes. On the other hand, the behaviour of the method can be changed at run-time by dynamically loading and unloading shared libraries.
This implementation is not fully thread-safe. Introducing thread safety should be a matter of only a small amount of work: the methods that initialise the multi-method or alter the member lists need to be protected, in addition to protecting the operation of updating candidate vectors for participating types. Calling multi-methods is thread-safe, although it should be guarded with locks that prohibit information from being changed while dispatch is underway.
Definition at line 154 of file MultiMethod.h.
typedef void(* lat::MultiMethod::MemberFunction)(void) |
anonymous enum [private] |
Initial size of the number of member function allocation.
An array of this many pointers to functions will be allocated when the first family member is registered. Thereafter the array will be doubled in size every time it overgrows beyond its previous allocation.
Definition at line 321 of file MultiMethod.h.
00321 { INITIAL_FAMILY_SIZE = 32 }; // FIXME: STDC::size_t
anonymous enum [private] |
The number of Score objects to allocate per ScoreHunk.
Definition at line 324 of file MultiMethod.h.
00324 { SCORE_HUNK_SIZE = 64 }; // FIXME: STDC::size_t
anonymous enum [private] |
The number of Entry objects to allocate per EntryHunk.
Definition at line 327 of file MultiMethod.h.
00327 { ENTRY_HUNK_SIZE = 32 }; // FIXME: STDC::size_t
anonymous enum [private] |
The Score::m_index of the sentinel Score.
The number of member functions in the family must be less than this.
Definition at line 331 of file MultiMethod.h.
00331 { LAST_SCORE = USHRT_MAX }; // FIXME: unsigned short
anonymous enum [private] |
The Score::m_distance of the sentinel Score.
No actual argument object can be this far in inheritance from the corresponding formal argument types of any member function.
Definition at line 336 of file MultiMethod.h.
00336 { INFINITE_DISTANCE = USHRT_MAX }; // FIXME: unsigned short
lat::MultiMethod::MultiMethod | ( | void | ) | [protected] |
lat::MultiMethod::~MultiMethod | ( | void | ) | [protected] |
lat::MultiMethod::MultiMethod | ( | const MultiMethod & | ) | [private] |
Score* lat::MultiMethod::allocateScores | ( | STDC::size_t | n | ) | const [private] |
void lat::MultiMethod::ambiguity | ( | XTypeInfo ** | actuals, | |
Score ** | candidates, | |||
Score * | best | |||
) | const [private] |
ScoreHunk* lat::MultiMethod::createScoreHunk | ( | STDC::size_t | min | ) | const [private] |
MemberFunction lat::MultiMethod::dispatch | ( | XTypeInfo ** | actualTypes, | |
Score ** | candidates, | |||
Score * | best | |||
) | const [protected] |
Referenced by lat::MultiMethod_1_0< R, V1 >::operator()(), lat::MultiMethod_3_2< R, V1, V2, V3, T1, T2 >::operator()(), lat::MultiMethod_2_1< R, V1, V2, T1 >::operator()(), lat::MultiMethod_1_2< R, V1, T1, T2 >::operator()(), lat::MultiMethod_1_1< R, V1, T1 >::operator()(), lat::MultiMethod_3_0< R, V1, V2, V3 >::operator()(), lat::MultiMethod_2_0< R, V1, V2 >::operator()(), lat::MultiMethod_2_2< R, V1, V2, T1, T2 >::operator()(), and lat::MultiMethod_3_1< R, V1, V2, V3, T1 >::operator()().
static XTypeInfo::ExtensionKey lat::MultiMethod::extensionKey | ( | void | ) | [static, private] |
static Entry* lat::MultiMethod::findTypeEntries | ( | const XTypeInfo * | type, | |
Entry *& | previous, | |||
STDC::size_t | key, | |||
STDC::size_t | formal = STDC::size_t(-1) | |||
) | [static, private] |
void lat::MultiMethod::initialise | ( | Definition * | data, | |
STDC::size_t | formals, | |||
XTypeInfo::ClassDef ** | formalTypes | |||
) | [protected] |
Referenced by lat::MultiMethod_1_0< R, V1 >::MultiMethod_1_0(), lat::MultiMethod_1_1< R, V1, T1 >::MultiMethod_1_1(), lat::MultiMethod_1_2< R, V1, T1, T2 >::MultiMethod_1_2(), lat::MultiMethod_2_0< R, V1, V2 >::MultiMethod_2_0(), lat::MultiMethod_2_1< R, V1, V2, T1 >::MultiMethod_2_1(), lat::MultiMethod_2_2< R, V1, V2, T1, T2 >::MultiMethod_2_2(), lat::MultiMethod_3_0< R, V1, V2, V3 >::MultiMethod_3_0(), lat::MultiMethod_3_1< R, V1, V2, V3, T1 >::MultiMethod_3_1(), and lat::MultiMethod_3_2< R, V1, V2, V3, T1, T2 >::MultiMethod_3_2().
static STDC::size_t lat::MultiMethod::methodKey | ( | void | ) | [static, private] |
MultiMethod& lat::MultiMethod::operator= | ( | const MultiMethod & | ) | [private] |
STDC::size_t lat::MultiMethod::relatedFormal | ( | const XTypeInfo * | type | ) | const [private] |
Implements lat::XTypeInfo::Monitor.
Implements lat::XTypeInfo::Monitor.
friend struct Definition [friend] |
Definition at line 168 of file MultiMethod.h.
friend struct Entry [friend] |
Definition at line 174 of file MultiMethod.h.
friend struct EntryHunk [friend] |
Definition at line 173 of file MultiMethod.h.
friend struct Member [friend] |
Definition at line 171 of file MultiMethod.h.
friend struct ScoreHunk [friend] |
Definition at line 172 of file MultiMethod.h.
Definition* lat::MultiMethod::m_data [private] |
Definition at line 462 of file MultiMethod.h.