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

wait timeouts?

jamuraa
Beginner
751 Views
I was looking through the documentation while coding something using Thread Building Blocks that I hadn't really considered before, when I noticed that none of the mutexes or the concurrent containers have a timeout methods, which will wait on a locked structure for a certain amount of time before giving up. It seems like a common extension in other threading libraries, so I was confused at the lack of it here. Am I just missing some part of the library that supports this? Alternatively, what is the preferred way to wait on a lock for N seconds and then go do some other 'maintenance' work that needs to be done periodically? Spinning on try_acquire() / *_if_present() seems quite inefficient.

0 Kudos
4 Replies
ARCH_R_Intel
Employee
751 Views

Timeouts are deliberately missing by design, but we should consider adding them. You posted at a good time because we're trying to draw up feature requests for TBB >2.1.

The initial design of TBB targeted a paradigm of task-based programming for parallel speedup. It is what I think of as "classical" parallel algorithms like parallel_for, parallel_reduce, etc.The containers and mutexes were designed with that in mind; i.e., to avoid race conditions.Blocking was expected to be short, otherwise the program would not scale. Therefore timeouts were not a priority.

However, it's clear that TBB is used in contexts beyond classical parallel algorithms, and in those contexts timeoutscan be appropriate. Indeed, there is one timeout already in TBB: function tbb::tbb_this_thread::thread_sleep sleeps for a specific time duration.

In the current TBB, the best way to periodically attend to an event would be to create a separate tbb::tbb_thread and have it do the periodic work, and sleep for each period.

0 Kudos
Wooyoung_K_Intel
Employee
751 Views

Hi,

After some good discussion about timed_mutex in TBB, we decided to post a blog article (http://softwareblogs.intel.com/2008/09/17/pondering-timed-mutex/) to see how people, in particular, C++ developers and TBB users, think of the idea. Please let us know what you think.

thanks a lot

0 Kudos
Dmitry_Vyukov
Valued Contributor I
751 Views
MADwkim3:

After some good discussion about timed_mutex in TBB, we decided to post a blog article (http://softwareblogs.intel.com/2008/09/17/pondering-timed-mutex/) to see how people, in particular, C++ developers and TBB users, think of the idea. Please let us know what you think.




Personally I can't remember when I was using timed lock for something else than some temporal hack.

"Can we still call it spin_mutex after we add wait/time-out to it?"
I think, yes. The main feature and advantage of spin-mutex is lightweight release and absence of heavyweight signaling. If you will add timed wait, those properties will still hold.

"Secondly, platforms differ in the degree to which they support timed mutexes"
I think that Win32's CRITICAL_SECTION must be considered as NON supporting timed waits. And it's a significant precedent wrt utility of timed mutexes.

"Andrey Marochko suggested self-restarting servers as a use case -- if a server cannot acquire a mutex for a pre-set period of time, it may assume that an unrecoverable error has occurred and restart itself."
My personal opinion is that timed mutexes have nothing to do with self-reviving servers. Server can deadlock/livelock in any point in the code, not only on mutex acquisition. So self-reviving servers usually implemented with watchdog timers and keepalives.

0 Kudos
Dmitry_Vyukov
Valued Contributor I
751 Views

As for the following implementation:

template
bool try_acquire_with_timeout( Mutex& mutex, typename Mutex::scoped_lock& lock, const size_t interval_in_milli /* in milliseconds */)
{
internal::AtomicBackoff bo;
TBB_ASSERT( interval>0, NULL );
size_t interval_in_micro = interval_in_milli * 1000; /* convert it to usec */
tick_count::interval_t i_100( 0.0001 /* seconds */); // 100 micro seconds == 0.1 milli seconds = 0.1*10.0E-3
do {
if( lock.try_acquire( mutex ) )
return true;
 if( !bo.bounded_pause() ) {
this_tbb_thread::sleep(i_100); // sleep for 100 micro seconds
interval_in_micro -= 100;
bo.reset();
}
} while ( interval_in_micro>0 ) ;
return false;
}

The moment I'm concerned with it "this_tbb_thread::sleep(i_100)".
AFAIK in some circumstances Windows will put thread to sleep for scheduling granularity, i.e. 15 ms. Such implementation can be very non-reactive. I think it's better to call few times 'SwitchToThread()' and then 'Sleep(0)'.

Btw, this way user can implement timed lock manually, with any backoff strategy he wants.


0 Kudos
Reply