Exemple #1
0
void spring_time::sleep(bool forceThreadSleep)
{
	if (forceThreadSleep) {
		spring::this_thread::sleep_for(chrono::nanoseconds(toNanoSecsi()));
		return;
	}


	// for very short time intervals use a yielding loop (yield is ~5x more accurate than sleep(), check the UnitTest)
	if (toMicroSecsi() < (avgThreadSleepTimeMicroSecs + avgThreadYieldTimeMicroSecs * 5)) {
		const spring_time s = gettime();

		while ((gettime() - s) < *this)
			thread_yield();

		return;
	}

	// expected wakeup time
	const spring_time t0 = gettime() + *this;

	spring::this_thread::sleep_for(chrono::nanoseconds(toNanoSecsi()));

	const spring_time t1 = gettime();
	const spring_time dt = t1 - t0;

	if (t1 >= t0) {
		// yes, it's not 100% thread correct, but it's okay when 1 of 1 million writes is dropped
		int avg = avgThreadSleepTimeMicroSecs.load();
		int newAvg = mix<float>(avg, dt.toMicroSecsf(), 0.1f);
		avgThreadSleepTimeMicroSecs.store(newAvg);
	}
}
Exemple #2
0
void CTimeProfiler::AddTime(const std::string& name, const spring_time time, const bool showGraph)
{
	auto pi = profile.find(name);
	if (pi != profile.end()) {
		// profile already exists
		//FIXME use atomic ints
		auto& p = pi->second;
		p.total   += time;
		p.current += time;
		p.frames[currentPosition] += time;
		if (p.maxLag < time.toMilliSecsf()) {
			p.maxLag     = time.toMilliSecsf();
			p.newLagPeak = true;
		}
	} else {
		boost::unique_lock<boost::mutex> ulk(m, boost::defer_lock);
		while (!ulk.try_lock()) {}

		// create a new profile
		auto& p = profile[name];
		p.total   = time;
		p.current = time;
		p.maxLag  = time.toMilliSecsf();
		p.percent = 0;
		memset(p.frames, 0, TimeRecord::frames_size * sizeof(unsigned));
		static UnsyncedRNG rand;
		rand.Seed(spring_tomsecs(spring_gettime()));
		p.color.x = rand.RandFloat();
		p.color.y = rand.RandFloat();
		p.color.z = rand.RandFloat();
		p.showGraph = showGraph;
	}
}
void spring_time::sleep()
{
	// for very short time intervals use a yielding loop (yield is ~5x more accurate than sleep(), check the UnitTest)
	if (toMilliSecsf() < (avgThreadSleepTimeMilliSecs + avgThreadYieldTimeMilliSecs * 5.0f)) {
		const spring_time s = gettime();

		while ((gettime() - s) < *this)
			thread_yield();

		return;
	}

	// expected wakeup time
	const spring_time t0 = gettime() + *this;

	#if defined(SPRINGTIME_USING_STD_SLEEP)
		this_thread::sleep_for(chrono::nanoseconds(toNanoSecsi()));
	#else
		boost::this_thread::sleep(boost::posix_time::microseconds(std::ceil(toNanoSecsf() * 1e-3)));
	#endif

	const spring_time t1 = gettime();
	const spring_time dt = t1 - t0;

	if (t1 >= t0) {
		boost::mutex::scoped_lock lock(sleepTimeMutex);
		avgThreadSleepTimeMilliSecs = mix(avgThreadSleepTimeMilliSecs, dt.toMilliSecsf(), 0.1f);
	}
}
static void thread_yield()
{
	const spring_time t0 = spring_time::gettime();
	this_thread::yield();
	const spring_time t1 = spring_time::gettime();
	const spring_time dt = t1 - t0;

	if (t1 >= t0) {
		boost::mutex::scoped_lock lock(yieldTimeMutex);
		avgThreadYieldTimeMilliSecs = mix(avgThreadYieldTimeMilliSecs, dt.toMilliSecsf(), 0.1f);
	}
}
Exemple #5
0
static void thread_yield()
{
	const spring_time t0 = spring_time::gettime();
	this_thread::yield();
	const spring_time t1 = spring_time::gettime();
	const spring_time dt = t1 - t0;

	if (t1 >= t0) {
		// yes, it's not 100% thread correct, but it's okay when 1 of 1 million writes is dropped
		int avg = avgThreadYieldTimeMicroSecs.load();
		int newAvg = mix<float>(avg, dt.toMicroSecsf(), 0.1f);
		avgThreadYieldTimeMicroSecs.store(newAvg);
	}
}
Exemple #6
0
std::int64_t CPathManager::Finalize() {
	const spring_time t0 = spring_gettime();

	{
		// maxResPF only runs on the main thread, so can be unsafe
		maxResPF = pfMemPool.alloc<CPathFinder>(false);
		medResPE = peMemPool.alloc<CPathEstimator>(maxResPF, MEDRES_PE_BLOCKSIZE, "pe",  mapInfo->map.name);
		lowResPE = peMemPool.alloc<CPathEstimator>(medResPE, LOWRES_PE_BLOCKSIZE, "pe2", mapInfo->map.name);

		// make cached path data checksum part of synced state
		// so that when any client has a corrupted / incorrect
		// cache it desyncs from the start, not minutes later
		{ SyncedUint tmp(GetPathCheckSum()); }
	}

	const spring_time dt = spring_gettime() - t0;
	return (dt.toMilliSecsi());
}
Exemple #7
0
static void DrawTimeSlice(std::deque<TimeSlice>& frames, const spring_time curTime, const spring_time maxHist, const float drawArea[4])
{
	// remove old entries
	while (!frames.empty() && (curTime - frames.front().second) > maxHist) {
		frames.pop_front();
	}

	const float y1 = drawArea[1];
	const float y2 = drawArea[3];

	// render
	CVertexArray* va = GetVertexArray();
	va->Initialize();
	for (TimeSlice& ts: frames) {
		float x1 = (ts.first % maxHist).toSecsf() / maxHist.toSecsf();
		float x2 = (ts.second % maxHist).toSecsf() / maxHist.toSecsf();
		x2 = std::max(x1 + globalRendering->pixelX, x2);

		x1 = drawArea[0] + x1 * (drawArea[2] - drawArea[0]);
		x2 = drawArea[0] + x2 * (drawArea[2] - drawArea[0]);

		va->AddVertex0(x1, y1, 0.0f);
		va->AddVertex0(x1, y2, 0.0f);
		va->AddVertex0(x2, y2, 0.0f);
		va->AddVertex0(x2, y1, 0.0f);

		const float mx1 = x1 + 3 * globalRendering->pixelX;
		const float mx2 = x2 - 3 * globalRendering->pixelX;
		if (mx1 < mx2) {
			va->AddVertex0(mx1, y1 + 3 * globalRendering->pixelX, 0.0f);
			va->AddVertex0(mx1, y2 - 3 * globalRendering->pixelX, 0.0f);
			va->AddVertex0(mx2, y2 - 3 * globalRendering->pixelX, 0.0f);
			va->AddVertex0(mx2, y1 + 3 * globalRendering->pixelX, 0.0f);
		}
	}

	va->DrawArray0(GL_QUADS);
}
Exemple #8
0
void SmoothController::ScreenEdgeMove(float3 move)
{
	if (flipped) {
		move.x = -move.x;
		move.y = -move.y;
	}
	move *= math::sqrt(move.z) * 200.0f;

	const float3 thisMove(move.x * pixelSize * 2.0f * scrollSpeed, 0.0f, -move.y * pixelSize * 2.0f * scrollSpeed);

	static spring_time lastScreenMove = spring_gettime();
	const spring_time timeDiff = spring_gettime() - lastScreenMove;
	lastScreenMove = spring_gettime();

	if (thisMove.x != 0 || thisMove.z != 0) {
		// user want to move with mouse on screen edge
		lastSource = ScreenEdge;
		Move(thisMove, timeDiff.toMilliSecsf());
	} else if (lastSource == ScreenEdge) {
		// last move order was given by screen edge, so call Move() to break
		Move(thisMove, timeDiff.toMilliSecsf());
	}
}
Exemple #9
0
void CTimeProfiler::Update()
{
	//FIXME non-locking threadsafe
	boost::unique_lock<boost::mutex> ulk(m, boost::defer_lock);
	while (!ulk.try_lock()) {}

	++currentPosition;
	currentPosition &= TimeRecord::frames_size-1;
	for (auto& pi: profile) {
		pi.second.frames[currentPosition] = spring_notime;
	}

	const spring_time curTime = spring_gettime();
	const float timeDiff = spring_diffmsecs(curTime, lastBigUpdate);
	if (timeDiff > 500.0f) // twice every second
	{
		for (auto& pi: profile) {
			auto& p = pi.second;
			p.percent = spring_tomsecs(p.current) / timeDiff;
			p.current = spring_notime;
			p.newLagPeak = false;
			p.newPeak = false;
			if(p.percent > p.peak) {
				p.peak = p.percent;
				p.newPeak = true;
			}
		}
		lastBigUpdate = curTime;
	}

	if (curTime.toSecsi() % 6 == 0) {
		for (auto& pi: profile) {
			auto& p = pi.second;
			p.maxLag *= 0.5f;
		}
	}
}
Exemple #10
0
void linux_signal::wait_for(spring_time t)
{
	int m; // cur gen
	const int g = gen.load(); // our gen
	sleepers++;

	struct timespec linux_t;
	linux_t.tv_sec  = 0;
	linux_t.tv_nsec = t.toNanoSecsi();

	const spring_time endTimer = spring_now() + t;

	while (((g - (m = mtx)) >= 0) && (spring_now() < endTimer)) {
		syscall(SYS_futex, &mtx, FUTEX_WAIT_PRIVATE, m, &linux_t, NULL, 0);
	}
	sleepers--;
}