00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00033
00034 #ifndef GROOVX_VISX_TIMINGHDLR_CC_UTC20050626084016_DEFINED
00035 #define GROOVX_VISX_TIMINGHDLR_CC_UTC20050626084016_DEFINED
00036
00037 #include "timinghdlr.h"
00038
00039 #include "io/readutils.h"
00040 #include "io/writeutils.h"
00041
00042 #include "nub/log.h"
00043 #include "nub/objmgr.h"
00044 #include "nub/ref.h"
00045
00046 #include "tcl/timerscheduler.h"
00047
00048 #include "rutz/error.h"
00049 #include "rutz/sfmt.h"
00050 #include "rutz/shared_ptr.h"
00051 #include "rutz/stopwatch.h"
00052
00053 #include "visx/trialevent.h"
00054
00055 #include <algorithm>
00056 #include <vector>
00057
00058 #include "rutz/trace.h"
00059 #include "rutz/debug.h"
00060 GVX_DBG_REGISTER
00061
00063
00064
00065
00067
00068 namespace
00069 {
00070 const io::version_id TIMINGHDLR_SVID = 1;
00071 }
00072
00074
00075
00076
00078
00079 class TimingHdlr::Impl
00080 {
00081 private:
00082 Impl(const Impl&);
00083 Impl& operator=(const Impl&);
00084
00085 public:
00086 Impl() :
00087 scheduler(rutz::make_shared(new tcl::timer_scheduler)),
00088 immediateEvents(),
00089 startEvents(),
00090 responseEvents(),
00091 abortEvents(),
00092 timer(),
00093 trial(0)
00094 {}
00095
00096 rutz::shared_ptr<nub::scheduler> scheduler;
00097
00098 typedef std::vector<nub::ref<TrialEvent> > EventGroup;
00099
00100 EventGroup immediateEvents;
00101 EventGroup startEvents;
00102 EventGroup responseEvents;
00103 EventGroup abortEvents;
00104
00105 mutable rutz::stopwatch timer;
00106
00107 EventGroup& eventsAt(TimePoint time_point)
00108 {
00109 switch (time_point)
00110 {
00111 case IMMEDIATE: return immediateEvents;
00112 case FROM_START: return startEvents;
00113 case FROM_RESPONSE: return responseEvents;
00114 case FROM_ABORT: return abortEvents;
00115 }
00116
00117 GVX_ASSERT(false);
00118
00119 return abortEvents;
00120 }
00121
00122 Trial* trial;
00123
00124 static void scheduleAll(EventGroup& events,
00125 rutz::shared_ptr<nub::scheduler> s,
00126 Trial* trial);
00127 static void cancelAll(EventGroup& events);
00128 };
00129
00131
00132
00133
00135
00136 const TimingHdlr::TimePoint TimingHdlr::IMMEDIATE;
00137 const TimingHdlr::TimePoint TimingHdlr::FROM_START;
00138 const TimingHdlr::TimePoint TimingHdlr::FROM_RESPONSE;
00139 const TimingHdlr::TimePoint TimingHdlr::FROM_ABORT;
00140
00142
00143
00144
00146
00147 TimingHdlr* TimingHdlr::make()
00148 {
00149 GVX_TRACE("TimingHdlr::make");
00150 return new TimingHdlr;
00151 }
00152
00153 TimingHdlr::TimingHdlr() :
00154 rep(new Impl)
00155 {
00156 GVX_TRACE("TimingHdlr::TimingHdlr");
00157 }
00158
00159 TimingHdlr::~TimingHdlr() throw()
00160 {
00161 GVX_TRACE("TimingHdlr::~TimingHdlr");
00162
00163 delete rep;
00164 }
00165
00166 io::version_id TimingHdlr::class_version_id() const
00167 {
00168 GVX_TRACE("TimingHdlr::class_version_id");
00169 return TIMINGHDLR_SVID;
00170 }
00171
00172 void TimingHdlr::read_from(io::reader& reader)
00173 {
00174 GVX_TRACE("TimingHdlr::read_from");
00175
00176 reader.ensure_version_id("TimingHdlr", 1, "Try groovx0.8a4", SRC_POS);
00177
00178 rep->immediateEvents.clear();
00179 io::read_utils::read_object_seq<TrialEvent>(reader, "immediateEvents",
00180 std::back_inserter(rep->immediateEvents));
00181
00182 rep->startEvents.clear();
00183 io::read_utils::read_object_seq<TrialEvent>(reader, "startEvents",
00184 std::back_inserter(rep->startEvents));
00185
00186 rep->responseEvents.clear();
00187 io::read_utils::read_object_seq<TrialEvent>(reader, "responseEvents",
00188 std::back_inserter(rep->responseEvents));
00189
00190 rep->abortEvents.clear();
00191 io::read_utils::read_object_seq<TrialEvent>(reader, "abortEvents",
00192 std::back_inserter(rep->abortEvents));
00193 }
00194
00195 void TimingHdlr::write_to(io::writer& writer) const
00196 {
00197 GVX_TRACE("TimingHdlr::write_to");
00198
00199 writer.ensure_output_version_id("TimingHdlr", TIMINGHDLR_SVID, 1,
00200 "Try groovx0.8a4", SRC_POS);
00201
00202 io::write_utils::write_object_seq(writer, "immediateEvents",
00203 rep->immediateEvents.begin(), rep->immediateEvents.end());
00204
00205 io::write_utils::write_object_seq(writer, "startEvents",
00206 rep->startEvents.begin(), rep->startEvents.end());
00207
00208 io::write_utils::write_object_seq(writer, "responseEvents",
00209 rep->responseEvents.begin(), rep->responseEvents.end());
00210
00211 io::write_utils::write_object_seq(writer, "abortEvents",
00212 rep->abortEvents.begin(), rep->abortEvents.end());
00213 }
00214
00216
00218
00219 nub::ref<TrialEvent> TimingHdlr::getEvent(TimePoint time_point,
00220 unsigned int index) const
00221 {
00222 GVX_TRACE("TimingHdlr::getEvent");
00223 return rep->eventsAt(time_point).at(index);
00224 }
00225
00226 double TimingHdlr::getElapsedMsec() const
00227 {
00228 GVX_TRACE("TimingHdlr::getElapsedMsec");
00229 return rep->timer.elapsed().msec();
00230 }
00231
00233
00235
00236 unsigned int TimingHdlr::addEvent(nub::ref<TrialEvent> event_item,
00237 TimePoint time_point)
00238 {
00239 GVX_TRACE("TimingHdlr::addEvent");
00240
00241 Impl::EventGroup& events = rep->eventsAt(time_point);
00242 events.push_back(event_item);
00243 return events.size() - 1;
00244 }
00245
00246 unsigned int TimingHdlr::addEventByName(const char* event_type,
00247 TimePoint timepoint, int msec_delay)
00248 {
00249 GVX_TRACE("TimingHdlr::addEventByName");
00250
00251 nub::ref<TrialEvent> event_item
00252 (nub::obj_mgr::new_typed_obj<TrialEvent>(event_type));
00253
00254 event_item->setDelay(msec_delay);
00255 return addEvent(event_item, timepoint);
00256 }
00257
00259
00260
00261
00263
00264 namespace
00265 {
00266 bool cmp_delay_less(const nub::ref<TrialEvent>& e1,
00267 const nub::ref<TrialEvent>& e2)
00268 {
00269 return (e1->getDelay() < e2->getDelay());
00270 }
00271 }
00272
00273 void TimingHdlr::Impl::scheduleAll(EventGroup& events,
00274 rutz::shared_ptr<nub::scheduler> s,
00275 Trial* trial)
00276 {
00277 GVX_TRACE("TimingHdlr::Impl::scheduleAll");
00278 GVX_PRECONDITION(trial != 0);
00279
00280
00281
00282
00283
00284
00285
00286
00287 std::stable_sort(events.begin(), events.end(), cmp_delay_less);
00288
00289 unsigned int minimum_delay = 0;
00290
00291 for (size_t i = 0; i < events.size(); ++i)
00292 {
00293 unsigned int scheduled_delay =
00294 events[i]->schedule(s, *trial, minimum_delay);
00295 minimum_delay = scheduled_delay+1;
00296
00297 nub::log(rutz::sfmt("scheduled @ %u: %s", scheduled_delay,
00298 events[i]->unique_name().c_str()));
00299 }
00300 }
00301
00302 void TimingHdlr::Impl::cancelAll(EventGroup& events)
00303 {
00304 GVX_TRACE("TimingHdlr::Impl::cancelAll");
00305 for (size_t i = 0; i < events.size(); ++i)
00306 {
00307 events[i]->cancel();
00308 }
00309 }
00310
00312
00313
00314
00316
00317 void TimingHdlr::thBeginTrial(Trial& trial)
00318 {
00319 GVX_TRACE("TimingHdlr::thBeginTrial");
00320
00321 rep->timer.restart();
00322
00323 rep->trial = &trial;
00324
00325 Impl::cancelAll(rep->responseEvents);
00326 Impl::cancelAll(rep->abortEvents);
00327 Impl::scheduleAll(rep->immediateEvents, rep->scheduler, rep->trial);
00328 Impl::scheduleAll(rep->startEvents, rep->scheduler, rep->trial);
00329 }
00330
00331 void TimingHdlr::thResponseSeen()
00332 {
00333 GVX_TRACE("TimingHdlr::thResponseSeen");
00334 if (rep->responseEvents.size() > 0)
00335 {
00336 Impl::cancelAll(rep->startEvents);
00337 Impl::scheduleAll(rep->responseEvents, rep->scheduler, rep->trial);
00338 }
00339 }
00340
00341 void TimingHdlr::thAbortTrial()
00342 {
00343 GVX_TRACE("TimingHdlr::thAbortTrial");
00344 if (rep->abortEvents.size() > 0)
00345 {
00346 Impl::cancelAll(rep->startEvents);
00347 Impl::cancelAll(rep->responseEvents);
00348 Impl::scheduleAll(rep->abortEvents, rep->scheduler, rep->trial);
00349 }
00350 }
00351
00352 void TimingHdlr::thEndTrial()
00353 {
00354 GVX_TRACE("TimingHdlr::thEndTrial");
00355 Impl::cancelAll(rep->immediateEvents);
00356 Impl::cancelAll(rep->startEvents);
00357 Impl::cancelAll(rep->responseEvents);
00358 Impl::cancelAll(rep->abortEvents);
00359 }
00360
00361 void TimingHdlr::thHaltExpt()
00362 {
00363 GVX_TRACE("TimingHdlr::thHaltExpt");
00364 Impl::cancelAll(rep->startEvents);
00365 Impl::cancelAll(rep->responseEvents);
00366 Impl::cancelAll(rep->abortEvents);
00367 }
00368
00369 static const char __attribute__((used)) vcid_groovx_visx_timinghdlr_cc_utc20050626084016[] = "$Id: timinghdlr.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00370 #endif // !GROOVX_VISX_TIMINGHDLR_CC_UTC20050626084016_DEFINED