TEST(TimeTicks, HighResNow) { const int kTargetGranularityUs = 10000; // 10ms bool success = false; int retries = 100; // Arbitrary. TimeDelta delta; while (!success && retries--) { TimeTicks ticks_start = TimeTicks::HighResNow(); // Loop until we can detect that the clock has changed. Non-HighRes timers // will increment in chunks, e.g. 10ms. By spinning until we see a clock // change, we detect the minimum time between measurements. do { delta = TimeTicks::HighResNow() - ticks_start; } while (delta.ToMilliseconds() == 0); if (delta.ToMicroseconds() <= kTargetGranularityUs) success = true; } // In high resolution mode, we expect to see the clock increment // in intervals less than 10ms. EXPECT_TRUE(success); }
// static Time Time::Now() { if(initial_time == 0) { InitializeClock(); } // 高精度计数器实现计时, 能够得到比10-15ms小的超时. 仅通过 // CurrentWallclockMicroseconds(), 无法得到细粒度的定时器. // // 使用时, 初始化时钟(initial_time)和计数器(initial_ctr). 通过 // 和初始时钟比较能得到消逝的时钟数, 然后就能得出时间差. // // 为避免误差, 计数器定期的和系统时钟同步. while(true) { TimeTicks ticks = TimeTicks::Now(); // 计算自开始以来的时间计数. TimeDelta elapsed = ticks - initial_ticks; // 检查是否需要同步时钟. if(elapsed.InMilliseconds() > kMaxMillisecondsToAvoidDrift) { InitializeClock(); continue; } return Time(elapsed + Time(initial_time)); } }
bool LeastSquaresVelocityTrackerStrategy::GetEstimator( uint32_t id, Estimator* out_estimator) const { out_estimator->Clear(); // Iterate over movement samples in reverse time order and collect samples. float x[kHistorySize]; float y[kHistorySize]; float w[kHistorySize]; float time[kHistorySize]; uint32_t m = 0; uint32_t index = index_; const base::TimeDelta horizon = base::TimeDelta::FromMilliseconds(kHorizonMS); const Movement& newest_movement = movements_[index_]; do { const Movement& movement = movements_[index]; if (!movement.id_bits.has_bit(id)) break; TimeDelta age = newest_movement.event_time - movement.event_time; if (age > horizon) break; const PointerXY& position = movement.GetPointerXY(id); x[m] = position.x; y[m] = position.y; w[m] = ChooseWeight(index); time[m] = -static_cast<float>(age.InSecondsF()); index = (index == 0 ? kHistorySize : index) - 1; } while (++m < kHistorySize); if (m == 0) return false; // no data // Calculate a least squares polynomial fit. uint32_t degree = degree_; if (degree > m - 1) degree = m - 1; if (degree >= 1) { float xdet, ydet; uint32_t n = degree + 1; if (SolveLeastSquares(time, x, w, m, n, out_estimator->xcoeff, &xdet) && SolveLeastSquares(time, y, w, m, n, out_estimator->ycoeff, &ydet)) { out_estimator->time = newest_movement.event_time; out_estimator->degree = degree; out_estimator->confidence = xdet * ydet; return true; } } // No velocity data available for this pointer, but we do have its current // position. out_estimator->xcoeff[0] = x[0]; out_estimator->ycoeff[0] = y[0]; out_estimator->time = newest_movement.event_time; out_estimator->degree = 0; out_estimator->confidence = 1; return true; }
void SvgWindow::onPaint(Painter* p) { Time startTime = Time::now(); p->setSource(Argb32(0xFFFFFFFF)); p->fillAll(); p->save(); svgDocument.render(p); p->restore(); p->flush(PAINTER_FLUSH_SYNC); Time endTime = Time::now(); TimeDelta frameDelta = endTime - startTime; TimeDelta fpsDelta = endTime - fpsTime; if (fpsDelta.getMillisecondsD() >= 1000.0) { fpsTotal = fpsCounter; fpsCounter = 0.0f; fpsTime = endTime; StringW text; text.format("FPS: %g, Time: %g", fpsTotal, frameDelta.getMillisecondsD()); setWindowTitle(text); } else { fpsCounter++; } p->resetTransform(); }
void MessagePumpLibevent::Run(Delegate* delegate) { //DCHECK(keep_running_) << "Quit must have been called outside of Run!"; assert(keep_running_); // event_base_loopexit() + EVLOOP_ONCE is leaky, see http://crbug.com/25641. // Instead, make our own timer and reuse it on each call to event_base_loop(). std::unique_ptr<event> timer_event(new event); for (;;) { bool did_work = delegate->DoWork(); if (!keep_running_) break; event_base_loop(event_base_, EVLOOP_NONBLOCK); did_work |= processed_io_events_; processed_io_events_ = false; if (!keep_running_) break; did_work |= delegate->DoDelayedWork(&delayed_work_time_); if (!keep_running_) break; if (did_work) continue; did_work = delegate->DoIdleWork(); if (!keep_running_) break; if (did_work) continue; // EVLOOP_ONCE tells libevent to only block once, // but to service all pending events when it wakes up. if (delayed_work_time_.is_null()) { event_base_loop(event_base_, EVLOOP_ONCE); } else { TimeDelta delay = delayed_work_time_ - TimeTicks::Now(); if (delay > TimeDelta()) { struct timeval poll_tv; poll_tv.tv_sec = (long)delay.InSeconds(); poll_tv.tv_usec = delay.InMicroseconds() % Time::kMicrosecondsPerSecond; event_set(timer_event.get(), -1, 0, timer_callback, event_base_); event_base_set(event_base_, timer_event.get()); event_add(timer_event.get(), &poll_tv); event_base_loop(event_base_, EVLOOP_ONCE); event_del(timer_event.get()); } else { delayed_work_time_ = TimeTicks(); } } } keep_running_ = true; }
void cubeMoved() { if (!started) { return; } SystemTime nowTime = SystemTime::now(); unsigned changeFlags = motion[cube].update(); auto tilt = motion[cube].tilt; auto accel = cube.accel(); // LOG ("Accel.x %d Accel.y: %d Accel.z %d\n", (signed int)accel.x, (signed int)accel.y, (signed int)accel.z); signed int move; switch (moveToCheck) { case 0: // left move = accel.x + 64; break; case 1: // right move = accel.x - 64; break; case 2: // up move = accel.y + 64; break; case 3: move = accel.y - 64; break; case 4: move = accel.z + 64; break; } move = abs(move); // Cube Face Up, Fip To the "Left" is -X axis if (move < 3 && !moveSuccess) { moveSuccess = true; LOG ("MOVE SUCCESS %d\n", move); TimeDelta delta = nowTime - startTime; changeTime = delta.milliseconds(); LOG ("DELTA TIME: %d\n", changeTime); finished = true; } }
// TimeTicks Unittest TEST(TimeTicks, Delta) { TimeTicks ticks_start = TimeTicks::Now(); nbase::Thread::Sleep(10); TimeTicks ticks_stop = TimeTicks::Now(); TimeDelta delta = ticks_stop - ticks_start; EXPECT_GE(delta.ToMilliseconds(), 9); EXPECT_GE(delta.ToMicroseconds(), 9000); EXPECT_EQ(delta.ToSeconds(), 0); }
int PlayGame::updateTime(TimeDelta delta) { if(countdown) { //LOG("Doing countdown\n"); countdownSecs += delta.seconds(); //LOG("delta.seconds() = %f\n", delta.seconds()); if((int) countdownSecs >= 3) { //LOG("countdownSecs = %f\n", countdownSecs); countdown = 0; startgame = 1; for(int i=0; i < CUBE_ALLOCATION; ++i) { if(cubeStates[i] == QUESTIONER) { myQuestioners[i]->countdownOver(); } } } else { for(int i=0; i < CUBE_ALLOCATION; ++i) { if(cubeStates[i] == QUESTIONER) { myGameDrawer->drawCountdown(i, (int) countdownSecs); } } } } if(startgame) { //LOG("Doing startgame\n"); ending = PlayGame::endGame(delta); if(ending) { startgame = 0; } } //LOG("ended = %d\n",ended); if(ended) { return 1; } return 0; }
bool ShakeGame::update(TimeDelta timeStep) { timeElapsed += timeStep.seconds(); if (timeElapsed <= howLong) { BaseGame::update(timeStep); return false; } else { LOG("Elapsed %f\n", timeElapsed); CalcPlaces(); AudioTracker::stop(); return true; } }
bool WaitableEvent::TimedWait(const TimeDelta& max_time) { DCHECK(max_time >= TimeDelta::FromMicroseconds(0)); // 这里需要小心. TimeDelta精度是微秒, 但这里只需要毫秒值. 如果剩余5.5ms, 应该 // 延迟5ms还是6ms呢? 为避免过早的执行延迟任务, 应该是6ms. double timeout = ceil(max_time.InMillisecondsF()); DWORD result = WaitForSingleObject(handle_, static_cast<DWORD>(timeout)); switch(result) { case WAIT_OBJECT_0: return true; case WAIT_TIMEOUT: return false; } // 这里发生失败是最不可预见的. 帮助用户知道是否发生过失败. NOTREACHED() << "WaitForSingleObject failed"; return false; }
void SampleModePrefUI::SetSampleInterval(const TimeDelta& delta) { TString button_text; if (delta.InHours() > 0) { button_text = StringUtility::IntToString(delta.InHours()); button_text += kScaleStr[HOUR]; } else if (delta.InMinutes() > 0) { button_text = StringUtility::IntToString(delta.InMinutes()); button_text += kScaleStr[MINUTE]; } else if (delta.InSeconds() > 0) { button_text = StringUtility::IntToString( static_cast<int>(delta.InSeconds())); button_text += kScaleStr[SECOND]; } sample_interval_button_->SetText(button_text.c_str()); }
void ConditionVariable::TimedWait(const TimeDelta& max_time) { Event* waiting_event; HANDLE handle; { AutoLock auto_lock(internal_lock_); if (RUNNING != run_state_) return; // Destruction in progress. waiting_event = GetEventForWaiting(); handle = waiting_event->handle(); DCHECK(handle); } // Release internal_lock. { AutoUnlock unlock(user_lock_); // Release caller's lock WaitForSingleObject(handle, static_cast<DWORD>(max_time.InMilliseconds())); // Minimize spurious signal creation window by recycling asap. AutoLock auto_lock(internal_lock_); RecycleEvent(waiting_event); // Release internal_lock_ } // Reacquire callers lock to depth at entry. }
bool WaitableEvent::WaitTimeout(const TimeDelta& timeout) { const Time end_time(Time::Now() + timeout); const bool finite_time = timeout.ToInternalValue() >= 0; kernel_->lock_.Lock(); if (kernel_->signaled_) { if (!kernel_->manual_reset_) { // In this case we were signaled when we had no waiters. Now that // someone has waited upon us, we can automatically reset. kernel_->signaled_ = false; } kernel_->lock_.Unlock(); return true; } SyncWaiter sw; sw.lock()->Lock(); Enqueue(&sw); kernel_->lock_.Unlock(); // We are violating locking order here by holding the SyncWaiter lock but not // the WaitableEvent lock. However, this is safe because we don't lock @lock_ // again before unlocking it. for (;;) { const Time current_time(Time::Now()); if (sw.fired() || (finite_time && current_time >= end_time)) { const bool return_value = sw.fired(); // We can't acquire @lock_ before releasing the SyncWaiter lock (because // of locking order), however, in between the two a signal could be fired // and @sw would accept it, however we will still return false, so the // signal would be lost on an auto-reset WaitableEvent. Thus we call // Disable which makes sw::Fire return false. sw.Disable(); sw.lock()->Unlock(); kernel_->lock_.Lock(); kernel_->Dequeue(&sw, &sw); kernel_->lock_.Unlock(); return return_value; } if (finite_time) { const TimeDelta max_wait(end_time - current_time); sw.cv()->TimedWait(max_wait); } else { sw.cv()->Wait(); } } }
void X11UIEventLoopImpl::waitForWork() { int fd = _engine->_fd; int fdSize = Math::max(fd, _engine->_wakeUpPipe[0]) + 1; fd_set fdSet; struct timeval tval; struct timeval* ptval = NULL; FD_ZERO(&fdSet); FD_SET(fd, &fdSet); FD_SET(_engine->_wakeUpPipe[0], &fdSet); if (_delayedWorkTime.isNull()) { // There are no scheduled tasks, so ptval is NULL and this tells to select() // that it should wait infinite time. } else { TimeDelta delay = _delayedWorkTime - Time::now(); if (delay > TimeDelta()) { // Go to sleep. X11 will wake us to process X events and we also set // interval to wake up to run planned tasks (usually Timers). int64_t udelay = delay.getMicroseconds(); tval.tv_sec = (int)(udelay / 1000000); tval.tv_usec = (int)(udelay % 1000000); if (tval.tv_usec <= 100) tval.tv_usec = 100; ptval = &tval; } else { // It looks like delayedWorkTime indicates a time in the past, so we // need to call doDelayedWork now. _delayedWorkTime = Time(); return; } } int ret = ::select(fdSize, &fdSet, NULL, NULL, ptval); if (ret < 0) { Logger::error("Fog::X11UIEventLoopImpl", "waitForWork", "Failed to call select(), errno=%d.", errno); } if (ret > 0) { if (FD_ISSET(_engine->_wakeUpPipe[0], &fdSet)) { // Dummy c, the actual value is out of our interest. char c; if (::read(_engine->_wakeUpPipe[0], &c, sizeof(char)) != sizeof(char)) { Logger::error("Fog::X11UIEventLoopImpl", "waitForWork()", "Failed to read from wake-up pipe."); } _wakeUpSent.cmpXchg(1, 0); } } }
void main() { // subscribe to events Events::neighborAdd.set(onNeighborAdd); Events::neighborRemove.set(onNeighborRemove); Events::cubeTouch.set(onTouch); Events::cubeAccelChange.set(onAccelChange); for(CubeID cid : CubeSet::connected()) { vbuf[cid].attach(cid); motion[cid].attach(cid); activateCube(cid); } AudioTracker::setVolume(0.2f * AudioChannel::MAX_VOLUME); //if (inRunMode) LOG("run mode\n"); //else LOG("set mode\n"); // run loop while(1) { System::paint(); if (count > 1800 /*&& countDown*/) { LOG("in count conditional \n"); SystemTime curTime = SystemTime::now(); TimeDelta timePast = curTime - startTime; if (timePast > totalTime) { if (!musicInitialized) { musicInitialized = true; AudioTracker::play(Music); alarm = true; //countDown = false; } } convertedSec = timePast.seconds(); convertedMin = convertedSec / 60; displayHour = convertedMin / 60; displayMin = (int)convertedMin % (int)60; displaySec = convertedSec - (convertedMin * 60); count = 0; } //LOG_FLOAT(displaySec); count++; //if (inRunMode) LOG("run mode\n"); //else LOG("set mode\n"); for(CubeID cid : CubeSet::connected()) { activeCubes.mark(cid); String<128> str; if (inRunMode) { if (alarm) { if (cid == 0) str << "0:\n"; else if (cid == 1) str << ":00\n"; drawText(cid, str, 1, 1); } else { if (cid == 0) str << Fixed(hours-displayHour, 3) << ":\n"; else if (cid == 1) str << ":" << Fixed(minutes-displayMin, 3) << "\n"; drawText(cid, str, 1, 1) ; } } else { if (cid == 0) str << "Hours: " << Fixed(hours, 3) << "\n"; else if (cid == 1) str << "Minutes: " << Fixed(minutes, 3) << "\n"; drawText(cid, str, 1, 1) ; } } } }
void main() { const CubeID cube(0); static VideoBuffer vid; vid.attach(cube); /* * Blank the screen. This also blanks the one-pixel region between * the bottom of the fractal and the top of the elapsed time indicator * below. */ vid.initMode(SOLID_MODE); vid.colormap[0] = RGB565::fromRGB(0xFFFFFF); System::paint(); /* * We use STAMP mode in a special way here, to do (slow) true-color * rendering: The framebuffer is simply set up as an identity mapping * that shows each of the 16 colors in our colormap. Now we can put * a row of 16 pixels directly into the colormap, and render the screen * using 1024 of these little 16x1 pixel "frames". * * Clearly this is really slow, and this technique is unlikely to be * frequently useful, but it's a fun parlour trick :) */ SystemTime startTime = SystemTime::now(); vid.initMode(STAMP); vid.stamp.disableKey(); auto &fb = vid.stamp.initFB<16,1>(); for (unsigned i = 0; i < 16; i++) fb.plot(vec(i, 0U), i); for (unsigned y = 0; y < LCD_height - 9; y++) for (unsigned x = 0; x < LCD_width; x += 16) { /* * Render 16 pixels at a time, into a buffer in RAM. */ static RGB565 pixels[16]; for (unsigned i = 0; i < 16; i++) pixels[i] = calculateMandelbrot(vec(x+i, y)); /* * Now copy to VRAM and start painting. By waiting until * now to call finish(), we're allowing the calculation above * to run concurrently with the cube's paint operation. * * Note that our "frames" are actually just tiny pieces of the * screen, so we need to avoid the default frame rate limits * in order to render at an at all reasonable rate. This is * where paintUnlimited() comes into play. */ System::finish(); vid.stamp.setBox(vec(x,y), vec(16,1)); vid.colormap.set(pixels); System::paintUnlimited(); } /* * Use BG0_ROM mode to draw the elapsed time at the bottom of the screen. */ TimeDelta elapsed = SystemTime::now() - startTime; String<16> message; message << (elapsed.milliseconds() / 1000) << "." << Fixed(elapsed.milliseconds() % 1000, 3) << " sec"; LOG("Elapsed time: %s\n", message.c_str()); vid.initMode(BG0_ROM); vid.bg0rom.text(vec(1,0), message); vid.setWindow(LCD_height - 8, 8); // Kill time (efficiently) while (1) System::paint(); }
void Questioner::runGame(TimeDelta myDelta) { if(panning) { timePanning += myDelta.milliseconds(); if(timePanning > TIME_TO_CORRECT && !corrQuestAns) { corrQuestAns = 1; currQuestion.updateToCorrect(); } currPan = doPanning(targetPan,timePanning); if(currPan == targetPan) { prevQuestion.clean(); prevQuestion = currQuestion; currQuestion = newQuestion; panning = 0; } } else if(currQuestion.answered()) { yCurrQuestion = yCurrQuestion - 6; if(yCurrQuestion < 0) { yCurrQuestion += 18; } newQuestion = Question(myGameDrawer, myCube, yCurrQuestion); targetPan = currPan - vec(0,48); if(currPan.y < 0) { targetPan.y = targetPan.y += 144; currPan.y = currPan.y += 144; } timePanning = 0; panning = 1; corrQuestAns = 0; int correct = currQuestion.wasRight(); if(!correct) { if(longestStreak < currStreak) { longestStreak = currStreak; } currStreak = 0; } else { currStreak += correct; //LOG("currStreak = %d questioner with cubeID = %d\n",currStreak, (int)myCube); totalCorrect += correct; if(!(currStreak % 5)) { extraTime = 1; } } totalAsked++; } //LOG("Questioner about to return runGame()\n"); }
static void paintWrapper() { // clear the palette newCubes.clear(); lostCubes.clear(); reconnectedCubes.clear(); dirtyCubes.clear(); if(previousLearningTask != currentLearningTask){ previousLearningTask++; } // fire events System::paint(); // dynamically load assets just-in-time if (!(newCubes | reconnectedCubes).empty()) { AudioTracker::pause(); playSfx(SfxConnect); loader.start(config); while(!loader.isComplete()) { for(CubeID cid : (newCubes | reconnectedCubes)) { vbuf[cid].bg0rom.hBargraph( vec(0, 4), loader.cubeProgress(cid, 128), BG0ROMDrawable::ORANGE, 8 ); } // fire events while we wait System::paint(); } loader.finish(); AudioTracker::resume(); } // // repaint cubes (will this paint right? If not, try repainting all of them) // for(CubeID cid : dirtyCubes) { // activateCube(cid); // } //If the shaken timer flag is too old, turn it off again here. if(distractTime.isValid() && (currentLearningTask==2)) { TimeDelta timeSinceShook = SystemTime::now() - distractTime; double duration = timeSinceShook.milliseconds() / 1000; if((duration > 11) && isDistracted) { currentBackgrounds[2] = 3; currentBackgrounds[1] = 1; isDistracted = false; } } //update art to new task int j = 0; for(CubeID cid : CubeSet::connected()) { vbuf[cid].attach(cid); activateCube(cid); cbs [j] = cid; j++; } // also, handle lost cubes, if you so desire :) }