Accurate Sleep with cancellation - c++

I need to implement a delay or sleep function that is accurate and consistent, and must be able to be cancelled.
Here's my code:
bool cancel_flag(false);
void My_Sleep(unsigned int duration)
{
static const size_t SLEEP_INTERVAL = 10U; // 10 milliseconds
while ((!cancel_flag) && (duration > SLEEP_INTERVAL))
{
Sleep(duration);
duration -= SLEEP_INTERVAL;
}
if ((!cancel_flag) && (duration > 0U))
{
Sleep(duration);
}
}
The above function is run in a worker thread. The main thread is able to change the value of the "cancel_flag" in order to abort (cancel) the sleeping.
At my shop, we have different results when the duration is 10 seconds (10000 ms). Some PCs are showing a sleep duration of 10 seconds, other PCs are showing 16 seconds.
Articles about the Sleep() function say that it is bound to the windows interrupt and when the duration elapses, the thread is rescheduled (may not be run immediately). The function above may be encountering a propagation of time error due to rescheduling and interrupt latency.
The Windows Timestamp Project describes another technique of waiting on a timer object. My understanding is that this technique doesn't provide a means of cancellation (by another, main, thread).
Question:
1. How can I improve my implementation for a thread delay or sleep, that can be cancelled by another task, and is more consistent?
Can a sleeping AFX thread be terminated?
(What happens when a main thread terminates a sleeping AFX thread?)
What happens when a main thread terminates a thread that has called WaitForSingleObject?
Accuracy should be around 10ms, as in 10 seconds + 10ms.
Results should be consistent across various PCs (all running Windows 7 or 10).
Background
PCs that have correct timings are running Windows 7, at 2.9 GHz.
The PCs that have incorrect timings are running Windows 7, at 3.1 GHz and have fewer simultaneous tasks and applications running.
Application is developed using Visual Studio 2017, and MFC framework (using AFX for thread creation).

You shouldn't be implementing this at all.
In C++11 all basic necessary utilities for multithreading are implemented in the standard.
If you do not use C++11 - then switch to C++11 or higher - in the unfortunate case that you cannot, then use Boost which has the same features.
Basically, what you want to do with this functionality is covered by std::condition_variable. You can put a thread into waiting mode by using function wait (it accepts a condition function necessary for leaving the wait), wait_for and wait_until (same as wait but with total waiting time limit) as well as notify_one and notify_all methods that wake the sleeping threads (one or all) and make them check the awakening condition and proceed with their tasks.
Check out std::conditional_variable in the reference. Just google it and you'll find enough information about it with examples.
In case you do not trust std::conditional_variable implementation for some reason, you can still utilize it for mini waits and awakening.

How can I improve my implementation for a thread delay or sleep, that
can be cancelled by another task, and is more consistent?
High precision sleep has been discussed here before. I have used a waitable timer approach similar to what's described here.
Can a sleeping AFX thread be terminated? (What happens when a main
thread terminates a sleeping AFX thread?)
I assume you mean terminate with TerminateThread? AFX threads are simply wrappers around standard Windows threads. There is nothing special or magical about them that would differentiate their behavior. So what would happen is a bunch of bad stuff:
If the target thread owns a critical section, the critical section will not be released.
If the target thread is allocating memory from the heap, the heap lock will not be released.
If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.
You should never have to do this if you have access to all the source code of the application.
What happens when a main thread terminates a thread that has called
WaitForSingleObject?
See previous bullet. CreateEvent and WaitForSingleObject are actually a recommended way of cleanly terminating threads.

Related

Does Sleep(n) with n>0 relinquish CPU time to other threads

Using VC++ 13 under windows, the on-line help states that using Sleep(0) relinquishes the remainder of the current threads time slice to any other thread of equal priority. Is this also the case for other values? e.g. if I use Sleep(1000) are 1000ms of CPU time for the core on which the current thread is running likely to be usable by another thread? I imagine this is hardware and implementation specific, so to narrow it assume Intel I5 or better, Windows 7 or 8.
The reason for asking is I have a thread pool class, and I'm using an additional monitor thread to report progress, allow the user to abort long processes, etc...
Yes, zero has the special meaning only in the regard to signal there is no minimal time to wait. Normally it could be interpreted like "I want to sleep for no-time" which doesn't make much sense. It means "I want to give chance to other thread to run."
If it's non-zero, thread is guaranteed not to be returned to for the amount of time specified, of course within the clock resolution. When thread gets suspended it gets a suspended status in the system and is not considered during scheduling. With 0 it doesn't change it's status, so it remains ready to run, and the function might return immediately.
Also, I don't think it is hardware related, this is purely system level thing.
MSDN: Sleep function
A value of zero causes the thread to relinquish the remainder of its time slice to any other thread that is ready to run. If there are no other threads ready to run, the function returns immediately, and the thread continues execution.
The special XP case is described as follows:
Windows XP: A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution. This behavior changed starting with Windows Server 2003.
MSDN states that the reminder of the threads time slice is relinquished to any other thread of equal priority. This is somewhat meaningless because a thread of higher priority would have been scheduled prior to the thread calling Sleep(0) and a thread with lower priority would cause the Sleep(0) to return immediately without giving anything away. Therefore Sleep(0) only has impact to threads of equal priority by default.
Purpose of Sleep(0): It triggers the scheduler to re-schedule while putting the calling thread at the end of the queue. If the queue does not have any other processes of the same priority, the call will return immediately. If there are other threads, the delay is undetermined. Note: The Windows scheduler is not a single thread, it is spread all over the OS (Details: How does a scheduler regain control when wanted?).
The detailed behavior depends on the systems timer resolution setting (How to get the current Windows system-wide timer resolution). This setting also influences the threads time slice, it varies with the system timer resolution.
The system timer resolution defines the heartbeat of the system. This causes thread quanta to have specific values. The timer resolution granularity also determines the resolution of Sleep(period). Consequently, the accuracy of sleep periods is determined by the systems heartbeat. However, a high resolution timer setting increases the power consumption.
A Sleep(period) with period > 0 triggers the scheduler and prohibits scheduling of the calling thread for at least the requested period.
Consequently the calling threads time slice is interrupted. It ends immediately.
Yes, Sleep(period) with period > 0 relinquishes CPU time to other threads (if any applicable).
(Further reading: Few words about timer resolution, How to get an accurate 1ms Timer Tick under WinXP, and Limits of Windows Queue Timers).

Event respond faster than semaphore?

In a project I run into a case like this (On windows 7),
When several threads are busy (all my CPU cores are busy working), there'll be delay for a thread
to receive a semaphore (which is increased from 0 to 1). It may be as long as 1.5ms.
I solve this by cache a little things and increase the semaphore value earlier.
So to me, it seems signaling a semaphore is slow, it's not immediately received by threads (especially when CPU are busy), but if you signal it earlier before some thread begin to wait on it,, there' be no delay.
I once thought event is just a semaphore with maximum value of 1,,, well, now having met this case, I'm beginning to wonder if event is faster than semaphore at noticing threads to 'wake up'.
Sorry, I tried, but didn't come out with a demo,, I'm not very good at threading yet.
EDIT:
Is it true that Event is faster than Semaphore on Windows?
1.5 milliseconds is not explained by just the overhead between different multithreading primitives.
To simplify, Threads have three states
blocked
runnable
running
If a thread is waiting on a semaphore or an event, then it's blocked. When the event is signalled, it becomes runnable.
So the real question is, "When does a runnable thread actually run?" This varies according to scheduler algorithms, etc, but obviously it needs to run on a core, and that means nothing else can be "running" on that core at the same time. The scheduler will normally 'remove' the current running thread from a core when one of the following happens
it waits on a semaphore/event, and so becomes 'blocked'
It's been running continually for a certain time (time-based, or round-robin scheduling)
A higher priority thread becomes runnable.
The 1.5 milliseconds is probably round-robin, or time-based scheduling. Your thread is runnable but just hasn't started yet. If the thread must start, and should boot out the current thread, then you can try to increase it's priority via SetThreadPriority
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686277(v=vs.85).aspx
If a thread is waiting on a semaphore and it gets signaled, the thread will in my limited testing, become running in ~10us on a box that is not overloaded.
Signaling, and subsequent dispatching onto a core, will take longer if:
The signaled thread is in another process than any thread is preempts.
Running the signaled thread requires a thread running on another core to be preempted.
The box is already overloaded with higher-priority threads.
1.5ms must represent an extreme case where your box is very busy.
In such a case, replacing the semaphore with an event is unlikely to result in any significant improvement to overall signaling latency because the bulk of the work/delay required by the inter-thread signaling is tied up the in scheduling/dispatching, which is required in either case.

Can Windows totally stop a thread if it's sleeping too often?

I have a rare heisenbug in a multi-threaded application where the main thread, and only this thread, will just do nothing. As it's an heisenbug it's really hard to understand why this is happening.
The main thread is basically just looping. In the loop, it check several concurrent priority queues which contain tasks ordered by time to be executed. It pop a task, see if it's time to execute it. If it's time, it will just schedule it into TBB's task scheduler (using a root task which is the parent of all other tasks). If it's not time, the task is pushed again in the priority queue.
That's for one cycle. At the end of the cycle, the main thread is put to sleep for a very short time that I expect will be longer in practice but it's not really a problem, I just don't want it to use too much resources when not necessary.
Litterally:
static const auto TIME_SCHEDULED_TASKS_SPAWN_FREQUENCY = microseconds(250);
while( !m_task_scheduler.is_exiting() ) // check if the application should exit
{
m_clock_scheduler.spawn_realtime_tasks(); // here we spawn tasks if it's time
this_thread::sleep_for( TIME_SCHEDULED_TASKS_SPAWN_FREQUENCY );
}
m_clock_scheduler.clear_tasks();
m_root_task.wait_for_all();
I have a special task that just log a "TICK" message each second. It is automatically rescheduling until the end of the program. However, when the heisenbug appear, I can see the "TICK" disappearing and the application not doing anything else than the work that occurs in non-main threads. So it appear that only the main thread is touched.
The problem can come from different places, maybe in the scheduling logic, but then it's also the only thread that have a sleep call. That sleep is a boost::this_thread::sleep_for().
My question is: Is it possible that Windows (7 64bit) consider the main thread to be sleeping often and decide that it should sleep for a longer period of time than asked or be definitely ended?
I expect that it is not possible but I would like to be sure. I didn't find any precision on this in online documentation so far.
Update:
I have a friend who can reproduce the bug systematically (on Windows Vista, Core 2 Duo). I sent him a version without sleep and another with the main loop reimplemented using condition_variable so that each time a task is pushed in the queue the condition_variable awaken the main thread (but still have a minimum time of spawning).
The version without sleep works (but is slower) - so the problem seem to be related even if I don't know the real source.
The version using condition_variable works - which would indicate that it's the sleep call that don't work correctly?
So, apparently I fixed the bug, but I still don't know why the specific sleep call can sometime block.
UPDATE:
It was actually a bug triggered by Boost code. I hunted the bug and reported it and it have been fixed. I didn't check the previous versions but it is fixed in Boost 1.55
Is it possible that Windows (7 64bit) consider the main thread to be sleeping often and decide that it should sleep for a longer period of time than asked or be definitely ended?
NO. This does not happen. MSDN does not indicate that this could happen. Empirically, I have many Windows apps with periodic intervals ranging from ms to hours. The effect you suggest does not happen - it would be disastrous for my apps.
Given the well-known granularity issues with Sleep() calls for very short intervals, a sleeping thread will become ready upon the expiry of the interval. If there is a CPU core available, (ie. the cores are not all in use running higher-priority threads), the newly-ready thread will become running.
The OS will not extend the interval of Sleep() because of any historical/statistical data associated with the thread states - I don't think it keeps any such data.

What happens when pthreads wait in mutex_lock/cond_wait?

I have a program that should get the maximum out of my cpu.
It is multithreaded via pthreads that do their job well apart from the fact that they "only" get my cores to about 60% load which is not enough in my opinion.
I am searching for the reason and am asking myself (and hereby you) if the blocking functions mutex_lock/cond_wait are candidates?
What happens when a thread cannot run on in such a function?
Does pthread switch to another thread it handles or
does the thread yield its time to the system and if the latter is the case, can I change this behavior?
Regards,
Nobody
More Information
The setting is one mainthread that fills the taskpool and countless workers that fetch jobs from there and wait on a conditional that is signaled via broadcast when a serialized calculation is done. They go on with the values from this calculation until they are done, deliver their mail and fetch the next job...
On a typical modern pthreads implementation, each thread is managed by the kernel not unlike a separate process. Any blocking call like pthread_mutex_lock or pthread_cond_wait (but also, say, read) will yield its time to the system. The system will then find another eligible thread to schedule, whether in your process or another process, and run it.
If your program is only taking 60% of the CPU, it is more likely blocked on I/O than on pthread operations, unless you have done something way too granular with your pthread operations.
If a thread is waiting on a mutex/condition, it doesn't use resources (well, uses just a tiny amount). Whenever the thread enters waiting state, control switches to other threads. When the mutex is released (or condition variable signalled), the thread wakes up and may acquire the mutex (if no other thread grabs it first), and continue to run. If however some other thread acquires the mutex (this can happen if several threads are waiting for it), the thread returns to sleeping state.

pthread sleep linux

I am creating a program with multiple threads using pthreads.
Is sleep() causing the process (all the threads) to stop executing or just the thread where I am calling sleep?
Just the thread. The POSIX documentation for sleep() says:
The sleep() function shall cause the calling thread to be suspended from execution...
Try this,
#include <unistd.h>
usleep(microseconds);
I usually use nanosleep and it works fine.
Nanosleep supends the execution of the calling thread. I have had the same doubt because in some man pages sleep refers to the entire process.
In practice, there are few cases where you just want to sleep for a small delay (milliseconds). For Linux, read time(7), and see also this answer. For a delay of more than a second, see sleep(3), for a small delay, see nanosleep(2). (A counter example might be a RasPerryPi running some embedded Linux and driving a robot; in such case you might indeed read from some hardware device every tenth of seconds). Of course what is sleeping is just a single kernel-scheduled task (so a process or thread).
It is likely that you want to code some event loop. In such a case, you probably want something like poll(2) or select(2), or you want to use condition variables (read a Pthread tutorial about pthread_cond_init etc...) associated with mutexes.
Threads are expensive resources (since each needs a call stack, often of a megabyte at least). You should prefer having one or a few event loops instead of having thousands of threads.
If you are coding for Linux, read also Advanced Linux Programming and syscalls(2) and pthreads(7).
Posix sleep function is not thread safe.
https://clang.llvm.org/extra/clang-tidy/checks/concurrency/mt-unsafe.html
sleep() function does not cease a specific thread, but it stops the whole process for the specified amount of time. For stopping the execution of a particular thread, we can use one pthread condition object and use pthread_cond_timedwait() function for making the thread wait for a specific amount of time. Each thread will have its own condition object and it will never receive a signal from any other thread.