comparison doc/v2_planning/plugin.txt @ 1135:a1957faecc9b

revised plugin interface and implementation
author Olivier Breuleux <breuleuo@iro.umontreal.ca>
date Thu, 16 Sep 2010 02:58:24 -0400
parents 81ea57c6716d
children
comparison
equal deleted inserted replaced
1134:0653a85ff2e8 1135:a1957faecc9b
65 ============== 65 ==============
66 66
67 I have implemented the feature in plugin.py, in this directory. Simply 67 I have implemented the feature in plugin.py, in this directory. Simply
68 run python plugin.py to test it. 68 run python plugin.py to test it.
69 69
70
71
72 ===============
73 Revised version
74 ===============
75
76 Taking into account ideas thrown around during the September 16
77 meeting I (OB) have made the following modifications to my original
78 proposal:
79
80 Event objects
81 =============
82
83 In the revised framework, an Event is a generic object which can
84 contain any attributes you want, with one privileged attribute, the
85 'type' attribute, which is a string. I expect the following attributes
86 to be used widely:
87
88 * type: this is a string describing the abstract semantics of this
89 event ("tick", "second", "millisecond", "batch", etc.)
90
91 * issuer: a pointer to the plugin that issued this event. This allows
92 for fine grained filtering in the case where several plugins can
93 fire the same event type
94
95 * time: an integer or float index on an abstract timeline. For
96 instance, the "tick" event would have a "time" field, which would be
97 increased by one every time the event is fired. Pretty much all
98 recurrent events should include this.
99
100 * data: some data associated to the event. presumably it doesn't have
101 to be named "data", and more than one data field could be given.
102
103 The basic idea is that it should be possible to say: "I want this
104 plugin to be executed every tenth time an event of this type is fired
105 by this plugin", or any subset of these conditions.
106
107 Matching events
108 ===============
109
110 When registering a plugin, you specify a sort of "abstract event" that
111 an event must "match" in order to be fed to the plugin. This can be
112 done by simply instantiating an event with the fields you want to
113 match. I think examples would explain best my idea
114 (sch.schedule_plugin = add a plugin to the scheduler):
115
116 # Print the error on every parameter update (learner given in the event)
117 sch.schedule_plugin(Event("parameter_update"), PrintError())
118 # Print the reconstruction error of daa0 whenever it does a parameter update
119 sch.schedule_plugin(Event("parameter_update", issuer = daa0), PrintReconstructionError())
120 # Save the learner every 10 minutes
121 sch.schedule_plugin(Event("minute", time = each(10)), Save(learner))
122
123 The events given as first argument to schedule_plugin are not real
124 events: they are "template events" meant to be *matched* against the
125 real events that will be fired. If the terminology is confusing, it
126 would not be a problem to use another class with a better name (for
127 example, On("minute", time = each(10)) could be clearer than
128 Event(...), I don't know).
129
130 Note that fields in these Event objects can be a special kind of
131 object, a Matcher, which allows to filter events based on arbitrary
132 conditions. My Schedule objects (each, at, etc.) now inherit from
133 Matcher. You could easily have a matcher that allows you to match
134 issuers that are instances of a certain class, or matches every single
135 event (I have an example of the latter in plugin.py).
136
137 Plugins
138 =======
139
140 The plugin class would have the following methods:
141
142 * attach(scheduler): tell the plugin that it is being scheduled by the
143 scheduler, store the scheduler in self. The method can return self,
144 or a copy of itself.
145
146 * fire(type, **attributes): adds Event(type, issuer = self, **attributes)
147 to the event queue of self.scheduler
148
149 Scheduler
150 =========
151
152 A Scheduler would have a schedule_plugin(event_template, plugin)
153 method to add plugins, a queue(event) method to queue a new event, and
154 it would be callable.
155
156 My current version proceeds as follows:
157
158 * Fire Event("begin"). Somewhat equivalent to "tick" at time 0, but I
159 find it cleaner to have a special event to mark the beginning of the
160 event loop.
161 * Infinite loop
162 * Fire Event("tick", time = <iteration#>)
163 * Loop until the queue is empty
164 * Pop event, execute all plugins that respond to it
165 * Check if event.type == "terminate". If so, stop.
166
167 Varia
168 =====
169
170 I've made a very simple implementation of a DispatchPlugin which, upon
171 reception of an event, dispatches it to its "on_<event.type>" method
172 (or calls a fallback). It seems nice. However, in order for it to work
173 reliably, it has to be registered on all events, and I'm not sure it
174 can scale well to more complex problems where the source of events is
175 important.
176
177 Implementation
178 ==============
179
180 See plugin.py.
181