Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

Cancellation of a task in execute()

Ali_Turkmen
Beginner
393 Views
Hello,

I have an application that does calculations on some data received continuously. There are several types of data and one instance of a calculation class for each data type. So the calculations of different types must be concurrent while for a single type, the data must be calculated in FIFO order, if there is a calculation going for a type of data then the upcoming data of this type must be stored and calculated one by one. Here enter the lovely, spectacular tbb::task and tbb::task_list. I create tasks, store them in task_list and spawn the first one in the list when calculation is over. So the next calculation begins.
But I have an issue. Sometimes calculation lasts too long and the stored data become too large. For these moments I have to cancel the calculations of this type of data, so I use cancel_group_execution(). But the execution of task continues. Because I think cancel_group_execution() method never forces the thread that runs the task to abort or something like that. How can I solve my problem?

Thanks.
0 Kudos
9 Replies
RafSchietekat
Valued Contributor III
393 Views

Evaluate task_group::is_canceling() or is_current_task_group_canceling() from time to time. I'm not sure if what you're doing with task_list is correct, though: you would spawn the entire task_list, not just the first one.

0 Kudos
Ali_Turkmen
Beginner
393 Views
Well, I do not use task_group in my implementation and I do not store tasks in task_list to spawn them all at once. Please take a look at my small example (CPPTester.cpp) of my application I told about first post.

The reference sheet says, under task cancellation ,
A task is a quantum of work that is cancelled or executes to completion. A cancelled
task skips its method execute() if that method has not yet started. Otherwise
cancellation has no direct effect on the task. A task can poll task::is_cancelled() to
see if cancellation was requested after it started running.

So is not there any way that I can cancel a task if its execute() method has started?
0 Kudos
Alexey-Kukanov
Employee
393 Views
As Raf and the reference recommend you, in the execute() method of a task you can poll if it is_cancelled(), and act appropriately.
0 Kudos
RafSchietekat
Valued Contributor III
393 Views
Of course you can use task_list as just your own container if you wish.

task::is_cancelled() is a convenient way of inquiring about the current context, which is a task_group.

Interesting mix of single and double l in cancelled/canceling... I always thought one was British and the other American? :-)
0 Kudos
Ali_Turkmen
Beginner
393 Views
here is an example:

[cpp]class CustomTask : public task
{
	task * execute()
	{
		cout << "Enter Thread Execute..."<< endl;
	//	Sleep(10000); 
		// OR
		 while(true);
		cout << "Exit Thread Execute..." << endl;
		return 0;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{

	cout << "sdfsdf"<< endl;

	CustomTask * ct = new(task::allocate_root()) CustomTask();
	ct->increment_ref_count();
	task::spawn(*ct);
	ct->wait_for_all();	
	system("PAUSE");
	ct->cancel_group_execution();
	cout<< "Is canceled : "<is_cancelled() << endl;
	system("PAUSE");
	return 0;
}
[/cpp]


is_cancelled returns true but execute() method is never terminated if already started. So I assume there is no way to cancel or terminate a running execute() method. Right?
0 Kudos
RafSchietekat
Valued Contributor III
393 Views
Not safely.
0 Kudos
Ali_Turkmen
Beginner
393 Views

So there is an unsafe way. What is it? This cancalation thing is so important to me that if I do not use tbb:task thenI will have to write my own task based threading structure with abunch of _beginthreadex(), TeminateThread(), CloseHandle()etc.

Please tell me.

0 Kudos
jimdempseyatthecove
Honored Contributor III
393 Views
Ali,

I think the problem lies in you are constructing the TBB task as if it were a pThread thread.

For your simple example above, consider adding a bool member variable to CustomTask called cancel. spawn(*ct) resets cancel. You set cancel when you wish the task to cancel, the while(true) loop on line 8 is replaced with while(!cancel). Note, make cancel a volatile bool atomic.

Or make a member function cancel()

Either route will provide for an orderly exit of the task.

Also, consider using a concurrent FIFOqueue or ring buffer in place of the task list. This queue/buffer will persist after exit from the ct->execute(). Meaning you can resume later after reclaiming resources.

Jim Dempsey
0 Kudos
Alexey-Kukanov
Employee
393 Views

right, the execute method is never terminated/cancelled *externally* once started. What we told you is to poll is_cancelled() from inside the method, and exit it if you got the cancellation signal.

The code you posted in #5 is wrong in a lot of aspects. The main problem is, as Jim pointed out, that you use TBB tasks as if they were threads. Just don't do that; if you need threads use std::thread instead.

0 Kudos
Reply