How do you mock the time for boost timers? - c++

If possible, how do you mock the time for the purpose of triggering boost timers in a unit test?
For example, is it possible to achieve something like the following:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
void print(const boost::system::error_code& /*e*/)
{
std::cout << "Hello, world!\n";
}
int main()
{
boost::asio::io_service io; // Possibly another class needed here, or a way of setting the clock to be fake
boost::asio::deadline_timer t(io, boost::posix_time::hours(24));
t.async_wait(&print);
io.poll(); // Nothing should happen - no handlers ready
// PSEUDO-CODE below of what I'd like to happen, jump ahead 24 hours
io.set_time(io.get_time() + boost::posix_time::hours(24));
io.poll(); // The timer should go off
return 0;
}
Update Thank you to all the answers, they have provided excellent insight into the problem. I have provided my own answer (SSCCE), but couldn't have done that without the help provided.

The basic_deadline_timer template has a traits parameter which you can use to provide your own clock. The author of Boost Asio has a blog post showing how to do this. Here's an example from the post:
class offset_time_traits
: public asio::deadline_timer::traits_type
{
public:
static time_type now()
{
return add(asio::deadline_timer::traits_type::now(), offset_);
}
static void set_now(time_type t)
{
offset_ =
subtract(t, asio::deadline_timer::traits_type::now());
}
private:
static duration_type offset_;
};
typedef asio::basic_deadline_timer<
boost::posix_time::ptime, offset_time_traits> offset_timer;
Maybe you can use something like offset_timer throughout your application but only call set_now() when running your tests?

As far as I know, there is no way to emulate time change or to set the time with Boost. Before expanding upon a few techniques that can be used to approach this problem, there are a few points to consider:
Boost.Asio provides timers that use clocks, but does not provide clocks as they are outside of the scope of Boost.Asio. Thus, clock related features, such as setting or emulating, are not within Boost.Asio's capabilities.
Monotonic clocks may be used internally. Thus, a change in a clock (emulated or actual) may not produce the desired effect. For example, boost::asio::steady_timer will not be affected by changes to system time, and the reactor implementation using epoll can take up to 5 minutes before detecting changes to system time, as it is protected from changes to the system clock.
For Boost.Asio timers, changing the expiration time will implicitly cancel asynchronous wait operations per the WaitableTimerService and TimerService requirements. This cancellation causes outstanding asynchronous wait operations to complete as soon as possible, and cancelled operations will have an error code of boost::asio::error::operation_aborted.
Nevertheless, there are two overall techniques to approach this problem based on what is being tested:
Scaling time.
Wrapping types.
Scaling Time
Scaling time preserves the same overall relative flow between multiple timers. For example, a timer with a 1 second expiration should trigger before a timer with a 24 hour expiration. Minimum and maximum durations can also be used for additional control. Furthermore, scaling durations works for timers that are not affected by the system clock, as as the steady_timer.
Here is an example, where a scale of 1 hour = 1 second is applied. Thus, the 24 hour expiration will actual be a 24 second expiration.
Additionally,
namespace bpt = boost::posix_time;
const bpt::time_duration max_duration = bpt::seconds(24);
const boost::chrono::seconds max_sleep(max_duration.total_seconds());
bpt::time_duration scale_time(const bpt::time_duration& duration)
{
// Scale of 1 hour = 1 seconds.
bpt::time_duration value =
bpt::seconds(duration.total_seconds() * bpt::seconds(1).total_seconds() /
bpt::hours(1).total_seconds());
return value < max_duration ? value : max_duration;
}
int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer t(io, scale_time(bpt::hours(24)));
t.async_wait(&print);
io.poll();
boost::this_thread::sleep_for(max_sleep);
io.poll();
}
Wrapping types
There are a few distinct locations where new types can be introduced to obtain some of the desired behavior.
Wrap the deadline_timer.
Create a custom WaitableTimerService.
Create a custom handler.
In all of these cases, it is important to account for the behavior that changing the expiration time will implicitly cancel the asynchronous wait operation.
Wrap the deadline_timer.
Wrapping the deadline_timer requires managing the user's handler internally. If the timer passes the user's handler to the service associated with the timer, then the user handler will be notified when the expiry time changes.
A custom timer could:
Store the WaitHandler provided to async_wait() internally (user_handler_).
When cancel() is invoked, an internal flag is set to indicate that cancellation has occurred (cancelled_).
Aggregate a timer. When an expiry time is set, an internal handler is passed to the aggregated timer's async_wait. Anytime the internal handler is called, it needs to handle the following four cases:
A normal timeout.
An explicit cancellation.
An implicit cancellation from expiry time being changed to a time is not in the future.
An implicit cancellation from expiry time being changed to a time that is in the future.
The internal handler code may look like the following:
void handle_async_wait(const boost::system::error_code& error)
{
// Handle normal and explicit cancellation.
if (error != boost::asio::error::operation_aborted || cancelled_)
{
user_handler_(error);
}
// Otherwise, if the new expiry time is not in the future, then invoke
// the user handler.
if (timer_.expires_from_now() <= boost::posix_time::seconds(0))
{
user_handler_(make_error_code(boost::system::errc::success));
}
// Otherwise, the new expiry time is in the future, so internally wait.
else
{
timer_.async_wait(boost::bind(&custom_timer::handle_async_wait, this,
boost::asio::placeholders::error));
}
}
While this is fairly easy to implement, it requires understanding the timer interface enough to mimic its pre/post-conditions, with the exception of the behavior for which you want to deviate. There may also be a risk factor in testing, as the behaviors need to be mimicked as close as possible. Additionally, this requires changing the type of timer for testing.
int main()
{
boost::asio::io_service io;
// Internal timer set to expire in 24 hours.
custom_timer t(io, boost::posix_time::hours(24));
// Store user handler into user_handler_.
t.async_wait(&print);
io.poll(); // Nothing should happen - no handlers ready
// Modify expiry time. The internal timer's handler will be ready to
// run with an error of operation_aborted.
t.expires_from_now(t.expires_from_now() - boost::posix_time::hours(24));
// The internal handler will be called, and handle the case where the
// expiry time changed to timeout. Thus, print will be called with
// success.
io.poll();
return 0;
}
Create a custom WaitableTimerService
Creating a custom WaitableTimerService is a little bit more complex. Although the documentation states the API, and the pre/post conditions, the implementation requires an understanding some of the internals, such as the io_service implementation and the scheduler interface, which is often a reactor. If the service passes the user's handler to the scheduler, then the user handler will be notified when the expiry time changes. Thus, similar to wrapping a timer, the user handler must be managed internally.
This has the same drawbacks as wrapping a timer: requires changing types and has inherit risk due to potential errors when trying to match the pre/post conditions.
For example:
deadline_timer timer;
is the equivalent of:
basic_deadline_timer<boost::posix_time::ptime> timer;
and would become:
basic_deadline_timer<boost::posix_time::ptime,
boost::asio::time_traits<boost::posix_time::ptime>,
CustomTimerService> timer;
Although this could be mitigated with a typedef:
typedef basic_deadline_timer<
boost::posix_time::ptime,
boost::asio::time_traits<boost::posix_time::ptime>,
CustomTimerService> customer_timer;
Create a custom handler.
A handler class could be used to wrap the actual handler, and provide the same approach as above with an extra degree of freedom. While this requires changing a type, and modifying what is provided to async_wait, it provides flexibility in that the custom handler's API has no pre-existing requirements. This reduced complexity provides a minimal risk solution.
int main()
{
boost::asio::io_service io;
// Internal timer set to expire in 24 hours.
deadline_timer t(io, boost::posix_time::hours(24));
// Create the handler.
expirable_handler handler(t, &print);
t.async_wait(&handler);
io.poll(); // Nothing should happen - no handlers ready
// Cause the handler to be ready to run.
// - Sets the timer's expiry time to negative infinity.
// - The internal handler will be ready to run with an error of
// operation_aborted.
handler.set_to_expire();
// The internal handler will be called, and handle the case where the
// expiry time changed to timeout. Thus, print will be called with
// success.
io.poll();
return 0;
}
All in all, testing asynchronous programs in a traditional manner can be very difficult. With proper encapsulation, it may even be nearly impossible to unit test without conditional builds. Sometimes it helps to shift perspectives and treat the entire asynchronous call chain as a single unit, with all external handlers being the API. If an asynchronous chain is too difficult to test, then I often find that the chain is too difficult to understand and/or maintain, and will mark it as a candidate for refactoring. Additionally, I often have to write helper types that allow my test harness to treat the asynchronous operations in a synchronous manner.

I dont' know about how to fake something like time passing, and I consider it to be overkill to provide your own time service. But here's a thought:
By initializing the timer with a hardcoded 24h, you used something that could be considered a magic constant (meaning: what you should not do). Instead, you could try this:
boost::asio::deadline_timer t(io, getDeadLineForX());
Now, if you stub out the getDeadLineForX function in your test suite, you can pass a sufficiently small deadline to test the timer, and you don't have to wait 24 hours for your test suite to complete.

A SSCCE, based on a link posted by #free_coffee:
#include <boost/asio.hpp>
#include <boost/optional.hpp>
class mock_time_traits
{
typedef boost::asio::deadline_timer::traits_type source_traits;
public:
typedef source_traits::time_type time_type;
typedef source_traits::duration_type duration_type;
// Note this implemenation requires set_now(...) to be called before now()
static time_type now() { return *now_; }
// After modifying the clock, we need to sleep the thread to give the io_service
// the opportunity to poll and notice the change in clock time
static void set_now(time_type t)
{
now_ = t;
boost::this_thread::sleep_for(boost::chrono::milliseconds(2));
}
static time_type add(time_type t, duration_type d) { return source_traits::add(t, d); }
static duration_type subtract(time_type t1, time_type t2) { return source_traits::subtract(t1, t2); }
static bool less_than(time_type t1, time_type t2) { return source_traits::less_than(t1, t2); }
// This function is called by asio to determine how often to check
// if the timer is ready to fire. By manipulating this function, we
// can make sure asio detects changes to now_ in a timely fashion.
static boost::posix_time::time_duration to_posix_duration(duration_type d)
{
return d < boost::posix_time::milliseconds(1) ? d : boost::posix_time::milliseconds(1);
}
private:
static boost::optional<time_type> now_;
};
boost::optional<mock_time_traits::time_type> mock_time_traits::now_;
typedef boost::asio::basic_deadline_timer<
boost::posix_time::ptime, mock_time_traits> mock_deadline_timer;
void handler(const boost::system::error_code &ec)
{
std::cout << "Handler!" << std::endl;
}
int main()
{
mock_time_traits::set_now(boost::posix_time::time_from_string("2013-01-20 1:44:01.000"));
boost::asio::io_service io_service;
mock_deadline_timer timer(io_service, boost::posix_time::seconds(5));
timer.async_wait(handler);
std::cout << "Poll 1" << std::endl;
io_service.poll();
mock_time_traits::set_now(mock_time_traits::now() + boost::posix_time::seconds(6));
std::cout << "Poll 2" << std::endl;
io_service.poll();
std::cout << "Poll 3" << std::endl;
io_service.poll();
return 0;
}
// Output
Poll 1
Poll 2
Handler!
Poll 3
Thankyou to #free_coffee for providing this link to a blog entry from the creator of boost asio. The above is slightly modified (and I believe slightly improved). By not using an offset on the system clock, you gain complete control over the timers: they will not fire until you explicitly set time forward past the timer.
The solution could be improved by making the this_thread::sleep part configurable. Note that the to_posix_duration hack described in [1] needs to use a smaller duration than the sleep.
To me this approach still seems a bit magic, since the time_traits are not well documented, and in particular the hack of to_posix_duration has a whiff of voodoo about it. I guess it just comes down to intimate knowledge of the deadline_timer implementation (which I don't have).

Related

Boost::asio::strand merges multiple handlers into one

I am currently using boost 1.70 and I was trying to implement io service loop to have a custom call between each invoked handle, and I couldn't get it to work. After some examination, I gained suspicion there are multiples handles executed in one call of "run_one" function. So I wrote a test code:
#include <boost/asio/io_service.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/post.hpp>
#include <thread>
#include <mutex>
class StrandPost
{
private:
boost::asio::io_service service_;
boost::asio::io_service::work work_;
boost::asio::io_service::strand strand_;
std::thread module_thread_;
void Run() {
auto run_one = [this]() {
std::cout << " ---- Running one ----" << std::endl;
auto retval = service_.run_one();
return retval;
};
while (run_one());
std::cout << " ---- Ending run ----" << std::endl;
}
public:
StrandPost()
: service_()
, work_(service_)
, strand_(service_)
, module_thread_(&StrandPost::Run, this)
{}
~StrandPost() {
service_.stop();
if (module_thread_.joinable()) {
module_thread_.join();
}
}
void PlanOutput(const std::string& string) {
boost::asio::post(strand_,[string](){
std::cout << string <<std::endl;
});
// boost::asio::post(service_,[string](){
// std::cout << string <<std::endl;
// });
}
};
} // ----- end anonymous namespace -----
int main() {
StrandPost strand;
strand.PlanOutput("First message");
strand.PlanOutput("Second message");
strand.PlanOutput("Third message");
strand.PlanOutput("Fourth message");
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
And the output of that code confirmed my theory, because it was:
---- Running one ----
First message
---- Running one ----
Second message
Third message
Fourth message
---- Running one ----
---- Ending run ----
When using "io_service" directly, it works as expected, but when using "strand", after the first handle, multiple handles are executed as one.
So, the strand effectively merged several handlers into one.
My question is:
Is this bug or is this intentional? Am I doing something wrong?
If this is a bug, is it reported? Because I could not find a mention of this anywhere.
I'm fairly certain this is intentional. The strand itself is a queue of jobs, that only one thread at a time can perform.
When io_service::run_one runs, it causes the thread to run the strand ready queue. I believe the 'only one once' logic isn't passed through to the strand's processing loop. Think of it it this way, the io_service is told to do one handler, but the strand's handler runs several jobs in sequence before returning.
The best fix for your issue is, if you're going to have your own io_service in your class, is don't use the strand at all, and post directly to the io_service. Then you'll have the behavior you desire.
This is, indeed, as intended. The strand_executor_service pops all ready handlers on the same strand:
void strand_executor_service::run_ready_handlers(implementation_type& impl)
{
// Indicate that this strand is executing on the current thread.
call_stack<strand_impl>::context ctx(impl.get());
// Run all ready handlers. No lock is required since the ready queue is
// accessed only within the strand.
boost::system::error_code ec;
while (scheduler_operation* o = impl->ready_queue_.front())
{
impl->ready_queue_.pop();
o->complete(impl.get(), ec, 0);
}
}
It is quite obvious that this can have a great performance improving impact.
Well, its not that easy, since I also need to be guaranteed that handles posted for execution from a given thread will be executed in the order of posting. Preserving order between posts from different threads is irrelevant, however order of posts from a given thread must be preserved, and as far as I know, "io_service" does not guarantee this. But thanks for the answer, looking further into the boost implementation, it looks you are completely right. –
TStancek
6 hours ago
io_service does have the ordering guarantees of a strand (in fact, the strand's guarantees derive from that). In your case, there is - by definition - only one thread, so everything on the service will be in an implicit strand (see Why do I need strand per connection when using boost::asio?).
Summary
You can do without the strand for the example code in your question.
If your situation is more involved and you need the one-by-one message processing control, you would do better to have a task queue that implements this explicitly, instead of depending on implementation details.

How to let a thread wait itself out without using Sleep()?

I want the while loop in the thread to run , wait a second, then run again, so on and so on., but this don't seem to work, how would I fix it?
main(){
bool flag = true;
pthread = CreateThread(NULL, 0, ThreadFun, this, 0, &ThreadIP);
}
ThreadFun(){
while(flag == true)
WaitForSingleObject(pthread,1000);
}
This is one way to do it, I prefer using condition variables over sleeps since they are more responsive and std::async over std::thread (mainly because std::async returns a future which can send information back the the starting thread. Even if that feature is not used in this example).
#include <iostream>
#include <chrono>
#include <future>
#include <condition_variable>
// A very useful primitive to communicate between threads is the condition_variable
// despite its name it isn't a variable perse. It is more of an interthread signal
// saying, hey wake up thread something may have changed that's interesting to you.
// They come with some conditions of their own
// - always use with a lock
// - never wait without a predicate
// (https://www.modernescpp.com/index.php/c-core-guidelines-be-aware-of-the-traps-of-condition-variables)
// - have some state to observe (in this case just a bool)
//
// Since these three things go together I usually pack them in a class
// in this case signal_t which will be used to let thread signal each other
class signal_t
{
public:
// wait for boolean to become true, or until a certain time period has passed
// then return the value of the boolean.
bool wait_for(const std::chrono::steady_clock::duration& duration)
{
std::unique_lock<std::mutex> lock{ m_mtx };
m_cv.wait_for(lock, duration, [&] { return m_signal; });
return m_signal;
}
// wiat until the boolean becomes true, wait infinitely long if needed
void wait()
{
std::unique_lock<std::mutex> lock{ m_mtx };
m_cv.wait(lock, [&] {return m_signal; });
}
// set the signal
void set()
{
std::unique_lock<std::mutex> lock{ m_mtx };
m_signal = true;
m_cv.notify_all();
}
private:
bool m_signal { false };
std::mutex m_mtx;
std::condition_variable m_cv;
};
int main()
{
// create two signals to let mainthread and loopthread communicate
signal_t started; // indicates that loop has really started
signal_t stop; // lets mainthread communicate a stop signal to the loop thread.
// in this example I use a lambda to implement the loop
auto future = std::async(std::launch::async, [&]
{
// signal this thread has been scheduled and has started.
started.set();
do
{
std::cout << ".";
// the stop_wait_for will either wait 500 ms and return false
// or stop immediately when stop signal is set and then return true
// the wait with condition variables is much more responsive
// then implementing a loop with sleep (which will only
// check stop condition every 500ms)
} while (!stop.wait_for(std::chrono::milliseconds(500)));
});
// wait for loop to have started
started.wait();
// give the thread some time to run
std::this_thread::sleep_for(std::chrono::seconds(3));
// then signal the loop to stop
stop.set();
// synchronize with thread stop
future.get();
return 0;
}
While the other answer is a possible way to do it, my answer will mostly answer from a different angle trying to see what could be wrong with your code...
Well, if you don't care to wait up to one second when flag is set to false and you want a delay of at least 1000 ms, then a loop with Sleep could work but you need
an atomic variable (for ex. std::atomic)
or function (for ex. InterlockedCompareExchange)
or a MemoryBarrier
or some other mean of synchronisation to check the flag.
Without proper synchronisation, there is no guarantee that the compiler would read the value from memory and not the cache or a register.
Also using Sleep or similar function from a UI thread would also be suspicious.
For a console application, you could wait some time in the main thread if the purpose of you application is really to works for a given duration. But usually, you probably want to wait until processing is completed. In most cases, you should usually wait that threads you have started have completed.
Another problem with Sleep function is that the thread always has to wake up every few seconds even if there is nothing to do. This can be bad if you want to optimize battery usage. However, on the other hand having a relatively long timeout on function that wait on some signal (handle) might make your code a bit more robust against missed wakeup if your code has some bugs in it.
You also need a delay in some cases where you don't really have anything to wait on but you need to pull some data at regular interval.
A large timeout could also be useful as a kind of watch dog timer. For example, if you expect to have something to do and receive nothing for an extended period, you could somehow report a warning so that user could check if something is not working properly.
I highly recommand you to read a book on multithreading like Concurrency in Action before writing multithread code code.
Without proper understanding of multithreading, it is almost 100% certain that anyone code is bugged. You need to properly understand the C++ memory model (https://en.cppreference.com/w/cpp/language/memory_model) to write correct code.
A thread waiting on itself make no sense. When you wait a thread, you are waiting that it has terminated and obviously if it has terminated, then it cannot be executing your code. You main thread should wait for the background thread to terminate.
I also usually recommand to use C++ threading function over the API as they:
Make your code portable to other system.
Are usually higher level construct (std::async, std::future, std::condition_variable...) than corresponding Win32 API code.

How to compose asynchronous operations?

I'm looking for a way to compose asynchronous operations. The ultimate goal is to execute an asynchronous operation, and either have it run to completion, or return after a user-defined timeout.
For exemplary purposes, assume that I'm looking for a way to combine the following coroutines1:
IAsyncOperation<IBuffer> read(IBuffer buffer, uint32_t count)
{
auto&& result{ co_await socket_.InputStream().ReadAsync(buffer, count, InputStreamOptions::None) };
co_return result;
}
with socket_ being a StreamSocket instance.
And the timeout coroutine:
IAsyncAction timeout()
{
co_await 5s;
}
I'm looking for a way to combine these coroutines in a way, that returns as soon as possible, either once the data has been read, or the timeout has expired.
These are the options I have evaluated so far:
C++20 coroutines: As far as I understand P1056R0, there is currently no library or language feature "to enable creation and composition of coroutines".
Windows Runtime supplied asynchronous task types, ultimately derived from IAsyncInfo: Again, I didn't find any facilities that would allow me to combine the tasks the way I need.
Concurrency Runtime: This looks promising, particularly the when_any function template looks to be exactly what I need.
From that it looks like I need to go with the Concurrency Runtime. However, I'm having a hard time bringing all the pieces together. I'm particularly confused about how to handle exceptions, and whether cancellation of the respective other concurrent task is required.
The question is two-fold:
Is the Concurrency Runtime the only option (UWP application)?
What would an implementation look like?
1 The methods are internal to the application. It is not required to have them return Windows Runtime compatible types.
I think the easiest would be to use the concurrency library. You need to modify your timeout to return the same type as the first method, even if it returns null.
(I realize this is only a partial answer...)
My C++ sucks, but I think this is close...
array<task<IBuffer>, 2> tasks =
{
concurrency::create_task([]{return read(buffer, count).get();}),
concurrency::create_task([]{return modifiedTimeout.get();})
};
concurrency::when_any(begin(tasks), end(tasks)).then([](IBuffer buffer)
{
//do something
});
As suggested by Lee McPherson in another answer, the Concurrency Runtime looks like a viable option. It provides tasks, that can be combined with others, chained up using continuations, as well as seamlessly integrate with the Windows Runtime asynchronous model (see Creating Asynchronous Operations in C++ for UWP Apps). As a bonus, including the <pplawait.h> header provides adapters for concurrency::task class template instantiations to be used as C++20 coroutine awaitables.
I wasn't able to answer all of the questions, but this is what I eventually came up with. For simplicity (and ease of verification) I'm using Sleep in place of the actual read operation, and return an int instead of an IBuffer.
Composition of tasks
The ConcRT provides several ways to combine tasks. Given the requirements concurrency::when_any can be used to create a task that returns, when any of the supplied tasks completes. When only 2 tasks are supplied as input, there's also a convenience operator (operator||) available.
Exception propagation
Exceptions raised from either of the input tasks do not count as a successful completion. When used with the when_any task, throwing an exception will not suffice the wait condition. As a consequence, exceptions cannot be used to break out of combined tasks. To deal with this I opted to return a std::optional, and raise appropriate exceptions in a then continuation.
Task cancellation
This is still a mystery to me. It appears that once a task satisfies the wait condition of the when_any task, there is no requirement to cancel the respective other outstanding tasks. Once those complete (successfully or otherwise), they are silently dealt with.
Following is the code, using the simplifications mentioned earlier. It creates a task consisting of the actual workload and a timeout task, both returning a std::optional. The then continuation examines the return value, and throws an exception in case there isn't one (i.e. the timeout_task finished first).
#include <Windows.h>
#include <cstdint>
#include <iostream>
#include <optional>
#include <ppltasks.h>
#include <stdexcept>
using namespace concurrency;
task<int> read_with_timeout(uint32_t read_duration, uint32_t timeout)
{
auto&& read_task
{
create_task([read_duration]
{
::Sleep(read_duration);
return std::optional<int>{42};
})
};
auto&& timeout_task
{
create_task([timeout]
{
::Sleep(timeout);
return std::optional<int>{};
})
};
auto&& task
{
(read_task || timeout_task)
.then([](std::optional<int> result)
{
if (!result.has_value())
{
throw std::runtime_error("timeout");
}
return result.value();
})
};
return task;
}
The following test code
int main()
{
try
{
auto res1{ read_with_timeout(3000, 5000).get() };
std::cout << "Succeeded. Result = " << res1 << std::endl;
auto res2{ read_with_timeout(5000, 3000).get() };
std::cout << "Succeeded. Result = " << res2 << std::endl;
}
catch( std::runtime_error const& e )
{
std::cout << "Failed. Exception = " << e.what() << std::endl;
}
}
produces this output:
Succeeded. Result = 42
Failed. Exception = timeout

Ensuring that only one instance of a function is running?

I'm just getting into concurrent programming. Most probably my issue is very common, but since I can't find a good name for it, I can't google it.
I have a C++ UWP application where I try to apply MVVM pattern, but I guess that the pattern or even being UWP is not relevant.
First, I have a service interface that exposes an operation:
struct IService
{
virtual task<int> Operation() = 0;
};
Of course, I provide a concrete implementation, but it is not relevant for this discussion. The operation is potentially long-running: it makes an HTTP request.
Then I have a class that uses the service (again, irrelevant details omitted):
class ViewModel
{
unique_ptr<IService> service;
public:
task<void> Refresh();
};
I use coroutines:
task<void> ViewModel::Refresh()
{
auto result = co_await service->Operation();
// use result to update UI
}
The Refresh function is invoked on timer every minute, or in response to a user request. What I want is: if a Refresh operation is already in progress when a new one is started or requested, then abandon the second one and just wait for the first one to finish (or time out). In other words, I don't want to queue all the calls to Refresh - if a call is already in progress, I prefer to skip a call until the next timer tick.
My attempt (probably very naive) was:
mutex refresh;
task<void> ViewModel::Refresh()
{
unique_lock<mutex> lock(refresh, try_to_lock);
if (!lock)
{
// lock.release(); commented out as harmless but useless => irrelevant
co_return;
}
auto result = co_await service->Operation();
// use result to update UI
}
Edit after the original post: I commented out the line in the code snippet above, as it makes no difference. The issue is still the same.
But of course an assertion fails: unlock of unowned mutex. I guess that the problem is the unlock of mutex by unique_lock destructor, which happens in the continuation of the coroutine and on a different thread (other than the one it was originally locked on).
Using Visual C++ 2017.
use std::atomic_bool:
std::atomic_bool isRunning = false;
if (isRunning.exchange(true, std::memory_order_acq_rel) == false){
try{
auto result = co_await Refresh();
isRunning.store(false, std::memory_order_release);
//use result
}
catch(...){
isRunning.store(false, std::memory_order_release);
throw;
}
}
Two possible improvements : wrap isRunning.store in a RAII class and use std::shared_ptr<std::atomic_bool> if the lifetime if the atomic_bool is scoped.

How to use C++11 <thread> designing a system which pulls data from sources

This question comes from:
C++11 thread doesn't work with virtual member function
As suggested in a comment, my question in previous post may not the right one to ask, so here is the original question:
I want to make a capturing system, which will query a few sources in a constant/dynamic frequency (varies by sources, say 10 times / sec), and pull data to each's queues. while the sources are not fixed, they may add/remove during run time.
and there is a monitor which pulls from queues at a constant freq and display the data.
So what is the best design pattern or structure for this problem.
I'm trying to make a list for all the sources pullers, and each puller holds a thread, and a specified pulling function (somehow the pulling function may interact with the puller, say if the source is drain, it will ask to stop the pulling process on that thread.)
Unless the operation where you query a source is blocking (or you have lots of them), you don't need to use threads for this. We could start with a Producer which will work with either synchronous or asynchronous (threaded) dispatch:
template <typename OutputType>
class Producer
{
std::list<OutputType> output;
protected:
int poll_interval; // seconds? milliseconds?
virtual OutputType query() = 0;
public:
virtual ~Producer();
int next_poll_interval() const { return poll_interval; }
void poll() { output.push_back(this->query()); }
std::size_t size() { return output.size(); }
// whatever accessors you need for the queue here:
// pop_front, swap entire list, etc.
};
Now we can derive from this Producer and just implement the query method in each subtype. You can set poll_interval in the constructor and leave it alone, or change it on every call to query. There's your general producer component, with no dependency on the dispatch mechanism.
template <typename OutputType>
class ThreadDispatcher
{
Producer<OutputType> *producer;
bool shutdown;
std::thread thread;
static void loop(ThreadDispatcher *self)
{
Producer<OutputType> *producer = self->producer;
while (!self->shutdown)
{
producer->poll();
// some mechanism to pass the produced values back to the owner
auto delay = // assume millis for sake of argument
std::chrono::milliseconds(producer->next_poll_interval());
std::this_thread::sleep_for(delay);
}
}
public:
explicit ThreadDispatcher(Producer<OutputType> *p)
: producer(p), shutdown(false), thread(loop, this)
{
}
~ThreadDispatcher()
{
shutdown = true;
thread.join();
}
// again, the accessors you need for reading produced values go here
// Producer::output isn't synchronised, so you can't expose it directly
// to the calling thread
};
This is a quick sketch of a simple dispatcher that would run your producer in a thread, polling it however often you ask it to. Note that passing produced values back to the owner isn't shown, because I don't know how you want to access them.
Also note I haven't synchronized access to the shutdown flag - it should probably be atomic, but it might be implicitly synchronized by whatever you choose to do with the produced values.
With this organization, it'd also be easy to write a synchronous dispatcher to query multiple producers in a single thread, for example from a select/poll loop, or using something like Boost.Asio and a deadline timer per producer.