Lumiera  0.pre.03
»edit your freedom«
visitor-dispatcher.hpp
Go to the documentation of this file.
1 /*
2  VISITOR-DISPATCHER.hpp - visitor implementation details
3 
4  Copyright (C)
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
14 
22 #ifndef LUMIERA_VISITOR_DISPATCHER_H
23 #define LUMIERA_VISITOR_DISPATCHER_H
24 
25 #include "lib/error.hpp"
26 #include "lib/util.hpp"
27 #include "lib/sync-classlock.hpp"
28 #include "lib/depend.hpp"
29 #include "lib/util.hpp"
30 
31 #include <vector>
32 
33 
34 namespace lib {
35 namespace visitor {
36 
37  using lib::ClassLock;
38  using lib::Depend;
39 
40 
41  template<class TOOL> class Tag;
42 
43 
44  template<class TOOL, class TOOLImpl>
46  {
47  static Tag<TOOL> tag;
48  };
49 
55  template<class TOOL>
56  class Tag
57  {
58  size_t tagID;
59  static size_t lastRegisteredID;
60 
61  static void
62  generateID (size_t& id)
63  {
64  ClassLock<Tag> guard;
65  if (!id)
66  id = ++lastRegisteredID;
67  }
68 
69  public:
70  Tag() : tagID(0) { }
71  operator size_t() const { return tagID; }
72 
73 
74  template<class TOOLImpl>
75  static Tag&
76  get (TOOLImpl* const =0)
77  {
79  if (!t) generateID (t.tagID);
80  return t;
81  }
82 
83  };
84 
85 
86 
88  template<class TOOL, class TOOLImpl>
90 
91  template<class TOOL>
92  size_t Tag<TOOL>::lastRegisteredID (0);
93 
94 
95 
96 
97 
98 
99 
100 
108  template<class TAR, class TOOL>
110  {
111  typedef typename TOOL::ReturnType ReturnType;
112 
118  template<class TOOLImpl>
119  static ReturnType
120  callTrampoline (TAR& obj, TOOL& tool)
121  {
122  // cast down to real implementation type
123  REQUIRE (INSTANCEOF (TOOLImpl, &tool));
124  TOOLImpl& toolObj = static_cast<TOOLImpl&> (tool);
125 
126  // trigger (compile time) overload resolution
127  // based on concrete type, then dispatch the call.
128  // Note this may cause obj to be upcasted.
129  return toolObj.treat (obj);
130  }
131 
132  typedef ReturnType (*Trampoline) (TAR&, TOOL& );
133 
134 
136  std::vector<Trampoline> table_;
137 
138 
139  void
140  accomodate (size_t index)
141  {
142  ClassLock<Dispatcher> guard; // note: this lock is also used for the singleton!
143  if (index > table_.size())
144  table_.resize (index); // performance bottleneck?? TODO: measure the real impact!
145  }
146 
147  inline bool
148  is_known (size_t id)
149  {
150  return id<=table_.size() && table_[id-1];
151  }
152 
153  inline void
154  storePtr (size_t id, Trampoline func)
155  {
156  REQUIRE (func);
157  REQUIRE (0 < id);
158  if (id>table_.size())
159  accomodate (id);
160  table_[id-1] = func;
161  }
162 
163  inline Trampoline
164  storedTrampoline (size_t id)
165  {
166  if (id<=table_.size() && table_[id-1])
167  return table_[id-1];
168  else
169  return &errorHandler;
170  }
171 
172  static ReturnType
173  errorHandler (TAR& target, TOOL& tool)
174  {
175  return tool.onUnknown (target);
176  }
177 
178 
179  public:
181 
182  inline ReturnType
183  forwardCall (TAR& target, TOOL& tool)
184  {
185  // get concrete type via tool's VTable
186  Tag<TOOL> index = tool.getTag();
187  return (*storedTrampoline(index)) (target, tool);
188  }
189 
190  template<class TOOLImpl>
191  inline void
192  enrol(TOOLImpl* typeref)
193  {
194  Tag<TOOL>& index = Tag<TOOL>::get (typeref);
195  if (is_known (index))
196  return;
197  else
198  {
199  Trampoline func = &callTrampoline<TOOLImpl>;
200  storePtr (index, func);
201  }
202 
203  }
204  };
205 
207  template<class TAR, class TOOL>
209 
210 
211 
212 
213 }} // namespace lib::visitor
214 #endif
size_t tagID
tag value
#define INSTANCEOF(CLASS, EXPR)
shortcut for subclass test, intended for assertions only.
Definition: util.hpp:514
Access point to singletons and other kinds of dependencies designated by type.
Definition: depend.hpp:280
Implementation namespace for support and library code.
static Tag< TOOL > tag
storage for the Tag registry for each concrete tool
static ReturnType callTrampoline(TAR &obj, TOOL &tool)
generator for Trampoline functions, used to dispatch calls down to the right "treat"-Function on the ...
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
A special implementation of lib::Sync, where the storage of the object monitor is associated directly...
Singleton services and Dependency Injection.
Lumiera error handling (C++ interface).
Type tag for concrete visiting tool classes.
A synchronisation protection guard employing a lock scoped to the parameter type as a whole...
For each possible call entry point via some subclass of the visitable hierarchy, we maintain a dispat...
static Depend< Dispatcher< TAR, TOOL > > instance
storage for the dispatcher table(s)
std::vector< Trampoline > table_
VTable for storing the Trampoline pointers.