Exemplo n.º 1
0
static uint32_t PeriodicTask_TimerRunner(uint32_t interval, void * param)
{
    TaskHandle handle = (TaskHandle) param;
    if(!handle->valid)
        return 0;
    if(handle->enabled)
        handle->function(handle->param);
    return 1;
}
void BackgroundProcessingPool::threadFunction()
{
	setThreadName("BackgrProcPool");

	MemoryTracker memory_tracker;
	memory_tracker.setMetric(CurrentMetrics::MemoryTrackingInBackgroundProcessingPool);
	current_memory_tracker = &memory_tracker;

	std::mt19937 rng(reinterpret_cast<intptr_t>(&rng));
	std::this_thread::sleep_for(std::chrono::duration<double>(std::uniform_real_distribution<double>(0, sleep_seconds_random_part)(rng)));

	while (!shutdown)
	{
		bool done_work = false;
		TaskHandle task;

		try
		{
			Poco::Timestamp min_time;

			{
				std::unique_lock<std::mutex> lock(tasks_mutex);

				if (!tasks.empty())
				{
					for (const auto & time_handle : tasks)
					{
						if (!time_handle.second->removed)
						{
							min_time = time_handle.first;
							task = time_handle.second;
							break;
						}
					}
				}
			}

			if (shutdown)
				break;

			if (!task)
			{
				std::unique_lock<std::mutex> lock(tasks_mutex);
				wake_event.wait_for(lock,
					std::chrono::duration<double>(sleep_seconds
						+ std::uniform_real_distribution<double>(0, sleep_seconds_random_part)(rng)));
				continue;
			}

			/// No tasks ready for execution.
			Poco::Timestamp current_time;
			if (min_time > current_time)
			{
				std::unique_lock<std::mutex> lock(tasks_mutex);
				wake_event.wait_for(lock, std::chrono::microseconds(
					min_time - current_time + std::uniform_int_distribution<uint64_t>(0, sleep_seconds_random_part * 1000000)(rng)));
			}

			Poco::ScopedReadRWLock rlock(task->rwlock);

			if (task->removed)
				continue;

			{
				CurrentMetrics::Increment metric_increment{CurrentMetrics::BackgroundPoolTask};
				done_work = task->function();
			}
		}
		catch (...)
		{
			tryLogCurrentException(__PRETTY_FUNCTION__);
		}

		if (shutdown)
			break;

		/// If task has done work, it could be executed again immediately.
		/// If not, add delay before next run.
		Poco::Timestamp next_time_to_execute = Poco::Timestamp() + (done_work ? 0 : sleep_seconds * 1000000);

		{
			std::unique_lock<std::mutex> lock(tasks_mutex);

			if (task->removed)
				continue;

			tasks.erase(task->iterator);
			task->iterator = tasks.emplace(next_time_to_execute, task);
		}
	}

	current_memory_tracker = nullptr;
}