예제 #1
0
TEST(WebTaskRunnerTest, CancellationCheckerTest) {
  scheduler::FakeWebTaskRunner taskRunner;

  int count = 0;
  TaskHandle handle = taskRunner.postCancellableTask(
      BLINK_FROM_HERE, WTF::bind(&increment, WTF::unretained(&count)));
  EXPECT_EQ(0, count);

  // TaskHandle::isActive should detect the deletion of posted task.
  auto queue = taskRunner.takePendingTasksForTesting();
  ASSERT_EQ(1u, queue.size());
  EXPECT_FALSE(queue[0].IsCancelled());
  EXPECT_TRUE(handle.isActive());
  queue.clear();
  EXPECT_FALSE(handle.isActive());
  EXPECT_EQ(0, count);

  count = 0;
  CancellationTestHelper helper;
  handle = taskRunner.postCancellableTask(
      BLINK_FROM_HERE, WTF::bind(&CancellationTestHelper::incrementCounter,
                                 helper.createWeakPtr()));
  EXPECT_EQ(0, helper.counter());

  // The cancellation of the posted task should be propagated to TaskHandle.
  queue = taskRunner.takePendingTasksForTesting();
  ASSERT_EQ(1u, queue.size());
  EXPECT_FALSE(queue[0].IsCancelled());
  EXPECT_TRUE(handle.isActive());
  helper.revokeWeakPtrs();
  EXPECT_TRUE(queue[0].IsCancelled());
  EXPECT_FALSE(handle.isActive());
}
예제 #2
0
파일: platform.c 프로젝트: aeturnus/zs3d
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;
}
예제 #3
0
void ParticleSource::emit(const U64 deltaTimeUS, std::shared_ptr<ParticleData> p) {
    ParticleData& data = *p;

    const F32 dt = Time::MicrosecondsToSeconds<F32>(deltaTimeUS);
    const U32 maxNewParticles = to_U32(dt * _emitRate);
    const U32 startID = data.aliveCount();
    const U32 endID = std::min(startID + maxNewParticles, data.totalCount() - 1);

    TaskHandle generateTask = CreateTask(_context.context(), DELEGATE_CBK<void, const Task&>());
    for (std::shared_ptr<ParticleGenerator>& gen : _particleGenerators) {
        gen->generate(generateTask, deltaTimeUS, data, startID, endID);
    }
    generateTask.startTask().wait();

    for (U32 i = startID; i < endID; ++i) {
        p->wake(i);
    }
}
예제 #4
0
void TaskAllocator::ReleaseTask( TaskHandle& task_handle )
{
    ASSERT( task_handle != INVALID_TASK_HANDLE );

    // Make task available to others.
    task_handle.m_task->Clear();

    // Calculate pool marker as difference between pointers:
    size_t pool_marker = task_handle.m_task - m_taskPool;
    m_poolMarkers[ pool_marker ].Store( 0, MemoryOrder::Release );

    // Invalidate pointer to avoid using released task!
    task_handle.Invalidate();
}
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;
}
예제 #6
0
TEST(WebTaskRunnerTest, PostCancellableTaskTest) {
  scheduler::FakeWebTaskRunner taskRunner;

  // Run without cancellation.
  int count = 0;
  TaskHandle handle = taskRunner.postCancellableTask(
      BLINK_FROM_HERE, WTF::bind(&increment, WTF::unretained(&count)));
  EXPECT_EQ(0, count);
  EXPECT_TRUE(handle.isActive());
  taskRunner.runUntilIdle();
  EXPECT_EQ(1, count);
  EXPECT_FALSE(handle.isActive());

  count = 0;
  handle = taskRunner.postDelayedCancellableTask(
      BLINK_FROM_HERE, WTF::bind(&increment, WTF::unretained(&count)), 1);
  EXPECT_EQ(0, count);
  EXPECT_TRUE(handle.isActive());
  taskRunner.runUntilIdle();
  EXPECT_EQ(1, count);
  EXPECT_FALSE(handle.isActive());

  // Cancel a task.
  count = 0;
  handle = taskRunner.postCancellableTask(
      BLINK_FROM_HERE, WTF::bind(&increment, WTF::unretained(&count)));
  handle.cancel();
  EXPECT_EQ(0, count);
  EXPECT_FALSE(handle.isActive());
  taskRunner.runUntilIdle();
  EXPECT_EQ(0, count);

  // The task should be cancelled when the handle is dropped.
  {
    count = 0;
    TaskHandle handle2 = taskRunner.postCancellableTask(
        BLINK_FROM_HERE, WTF::bind(&increment, WTF::unretained(&count)));
    EXPECT_TRUE(handle2.isActive());
  }
  EXPECT_EQ(0, count);
  taskRunner.runUntilIdle();
  EXPECT_EQ(0, count);

  // The task should be cancelled when another TaskHandle is assigned on it.
  count = 0;
  handle = taskRunner.postCancellableTask(
      BLINK_FROM_HERE, WTF::bind(&increment, WTF::unretained(&count)));
  handle = taskRunner.postCancellableTask(BLINK_FROM_HERE, WTF::bind([] {}));
  EXPECT_EQ(0, count);
  taskRunner.runUntilIdle();
  EXPECT_EQ(0, count);

  // Self assign should be nop.
  count = 0;
  handle = taskRunner.postCancellableTask(
      BLINK_FROM_HERE, WTF::bind(&increment, WTF::unretained(&count)));
#if COMPILER(CLANG)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wself-move"
  handle = std::move(handle);
#pragma GCC diagnostic pop
#else
  handle = std::move(handle);
#endif  // COMPILER(CLANG)
  EXPECT_EQ(0, count);
  taskRunner.runUntilIdle();
  EXPECT_EQ(1, count);

  // handle->isActive() should switch to false before the task starts running.
  bool isActive = false;
  handle = taskRunner.postCancellableTask(
      BLINK_FROM_HERE, WTF::bind(&getIsActive, WTF::unretained(&isActive),
                                 WTF::unretained(&handle)));
  EXPECT_TRUE(handle.isActive());
  taskRunner.runUntilIdle();
  EXPECT_FALSE(isActive);
  EXPECT_FALSE(handle.isActive());
}