bool ScheduledActions::execute() { if (node) { node->cancel(); } timeScheduled = clock->getCurrentTimeUS(); scheduledDelay = MWTime(*delay); scheduledInterval = MWTime(*interval); nRepeated = 0; boost::weak_ptr<ScheduledActions> weakThis(component_shared_from_this<ScheduledActions>()); node = Scheduler::instance()->scheduleUS(FILELINE, scheduledDelay, scheduledInterval, int(*n_repeats), [weakThis]() { if (auto sharedThis = weakThis.lock()) { sharedThis->executeOnce(); } return nullptr; }, M_DEFAULT_PRIORITY, M_DEFAULT_WARN_SLOP_US, M_DEFAULT_FAIL_SLOP_US, M_MISSED_EXECUTION_CATCH_UP); return true; }
CVReturn StimulusDisplay::displayLinkCallback(CVDisplayLinkRef _displayLink, const CVTimeStamp *now, const CVTimeStamp *outputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *_display) { StimulusDisplay *display = static_cast<StimulusDisplay*>(_display); { unique_lock lock(display->display_lock); if (bool(warnOnSkippedRefresh->getValue())) { if (display->lastFrameTime) { int64_t delta = (outputTime->videoTime - display->lastFrameTime) - outputTime->videoRefreshPeriod; if (delta) { mwarning(M_DISPLAY_MESSAGE_DOMAIN, "Skipped %g display refresh cycles", (double)delta / (double)(outputTime->videoRefreshPeriod)); } } } display->lastFrameTime = outputTime->videoTime; // // Here's how the time calculation works: // // outputTime->hostTime is the (estimated) time that the frame we're currently drawing will be displayed. // The value is in units of the "host time base", which appears to mean that it's directly comparable to // the value returned by mach_absolute_time(). However, the relationship to mach_absolute_time() is not // explicitly stated in the docs, so presumably we can't depend on it. // // What the CoreVideo docs *do* say is "the host time base for Core Video and the one for CoreAudio are // identical, and the values returned from either API can be used interchangeably". Hence, we can use the // CoreAudio function AudioConvertHostTimeToNanos() to convert from the host time base to nanoseconds. // // Once we have a system time in nanoseconds, we substract the system base time and convert to // microseconds, which leaves us with a value that can be compared to clock->getCurrentTimeUS(). // display->currentOutputTimeUS = (MWTime(AudioConvertHostTimeToNanos(outputTime->hostTime)) - display->clock->getSystemBaseTimeNS()) / 1000LL; display->refreshDisplay(); display->waitingForRefresh = false; } // Signal waiting threads that refresh is complete display->refreshCond.notify_all(); return kCVReturnSuccess; }
NIDAQDevice::NIDAQDevice(const ParameterValueMap ¶meters) : IODevice(parameters), deviceName(parameters[NAME].str()), requestSemName(generateUniqueID()), responseSemName(generateUniqueID()), controlChannel(boost::interprocess::create_only, requestSemName, responseSemName), sharedMemoryName(generateUniqueID()), sharedMemory(boost::interprocess::create_only, sharedMemoryName), controlMessage(NULL), helperPID(-1), updateInterval(parameters[UPDATE_INTERVAL]), analogInputDataInterval(parameters[ANALOG_INPUT_DATA_INTERVAL]), analogReadTimeout(updateInterval), assumeMultiplexedADC(parameters[ASSUME_MULTIPLEXED_ADC]), analogInputSampleBufferSize(0), analogInputTaskRunning(false), analogOutputDataInterval(parameters[ANALOG_OUTPUT_DATA_INTERVAL]), analogOutputSampleBufferSize(0), analogOutputEnabled(parameters[ANALOG_OUTPUT_ENABLED]), analogOutputTaskRunning(false), digitalInputSampleBufferSize(0), digitalInputTaskRunning(false), digitalOutputSampleBufferSize(0), digitalOutputTasksRunning(false), counterInputCountEdgesTasksRunning(false) { if (updateInterval <= 0) { throw SimpleException(M_IODEVICE_MESSAGE_DOMAIN, "Invalid update interval"); } if (analogInputDataInterval <= 0) { throw SimpleException(M_IODEVICE_MESSAGE_DOMAIN, "Invalid analog input data interval"); } if (updateInterval % analogInputDataInterval != 0) { throw SimpleException(M_IODEVICE_MESSAGE_DOMAIN, "Update interval must be an integer multiple of analog input data interval"); } if (!(parameters[ANALOG_READ_TIMEOUT].empty())) { analogReadTimeout = MWTime(parameters[ANALOG_READ_TIMEOUT]); if (analogReadTimeout < 0) { throw SimpleException(M_IODEVICE_MESSAGE_DOMAIN, "Invalid analog read timeout"); } } if (analogOutputDataInterval <= 0) { throw SimpleException(M_IODEVICE_MESSAGE_DOMAIN, "Invalid analog output data interval"); } }
MovingDots::MovingDots(const ParameterValueMap ¶meters) : StandardDynamicStimulus(parameters), fieldRadius(registerVariable(parameters[FIELD_RADIUS])), fieldCenterX(registerVariable(parameters[FIELD_CENTER_X])), fieldCenterY(registerVariable(parameters[FIELD_CENTER_Y])), dotDensity(registerVariable(parameters[DOT_DENSITY])), dotSize(registerVariable(parameters[DOT_SIZE])), alpha(registerVariable(parameters[ALPHA_MULTIPLIER])), direction(registerVariable(parameters[DIRECTION])), speed(registerVariable(parameters[SPEED])), coherence(registerVariable(parameters[COHERENCE])), lifetime(registerVariable(parameters[LIFETIME])), announceDots(parameters[ANNOUNCE_DOTS]), previousFieldRadius(1.0f), currentFieldRadius(1.0f), previousNumDots(0), currentNumDots(0), previousSpeed(0.0f), currentSpeed(0.0f), previousCoherence(1.0f), currentCoherence(1.0f), previousLifetime(0.0f), currentLifetime(0.0f), dotSizeToPixels(0.0f), previousTime(-1), currentTime(-1) { ParsedColorTrio color(parameters[COLOR]); red = registerVariable(color.getR()); green = registerVariable(color.getG()); blue = registerVariable(color.getB()); if (parameters[RAND_SEED].empty()) { randSeed = Clock::instance()->getSystemTimeNS(); } else { randSeed = MWTime(parameters[RAND_SEED]); } randGen.seed(randSeed); }
void HighPrecisionClock::sleepNS(MWTime time) { wait(mach_absolute_time() + timebase.nanosToAbsolute(std::max(MWTime(0), time))); }