Skip to content

Commit 66e65a2

Browse files
committed
Merge pull request #4 from External/feature/retry_for
Feature to retry_for a given amount of time
2 parents c39f064 + 3e7eefb commit 66e65a2

File tree

4 files changed

+112
-1
lines changed

4 files changed

+112
-1
lines changed

pre/retry_for.hpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#ifndef PRE_RETRY_FOR_HPP
2+
#define PRE_RETRY_FOR_HPP
3+
4+
#include <cassert>
5+
#include <functional>
6+
#include <chrono>
7+
#include <thread>
8+
9+
namespace pre {
10+
11+
12+
inline namespace retry_v1 {
13+
14+
/**
15+
* \brief Sometimes you need to retry some operations, as it's normal that they may fail.
16+
* Typically an IO error is not always a real error, as the media may
17+
* be known to be instable (e.g. airwaves communication, speaking over
18+
* serial line when remote device is busy...)
19+
*
20+
* Typically if there are many retries tried out without any pause in between, the
21+
* operation may still fail, as the main reason for something not to reply is to be
22+
* busy. Therefore this function allows you to specify blackout time as well as a
23+
* complete retry time.
24+
*
25+
* **Preconditions**: blackout_step must be a multiple of total_time.
26+
*
27+
* \param total_time Total time allowed for retrying.
28+
* \param time_step Wait time between retries.
29+
* \param retried_func Callback retried returning true on success, false on error.
30+
*
31+
* \return Whether the callback succeeded or not.
32+
*/
33+
template< class Rep, class Period >
34+
inline bool retry_for(
35+
const std::chrono::duration<Rep, Period>& total_time,
36+
const std::chrono::duration<Rep, Period>& time_step,
37+
std::function<bool (void)> retried_func) {
38+
assert(time_step.count()!=0);
39+
assert(total_time.count() >= time_step.count());
40+
41+
size_t iterations = total_time.count() / time_step.count();
42+
for(size_t p=0; p <iterations; p++) {
43+
if(retried_func()) { return true; }
44+
std::this_thread::sleep_for(time_step);
45+
}
46+
return false;
47+
}
48+
49+
/**
50+
* \brief Equivalent to :
51+
* sleep_for(initial_blackout); pre::retry_for(total_time, time_step, retried_func);
52+
*
53+
* Please see [pre::retry_for](@ref pre::retry_for(const std::chrono::duration<Rep, Period>&,
54+
* const std::chrono::duration<Rep, Period>& , std::function<bool (void)>)).
55+
*/
56+
template< class Rep, class Period >
57+
inline bool retry_for(
58+
const std::chrono::duration<Rep, Period>& total_time,
59+
const std::chrono::duration<Rep, Period>& time_step,
60+
const std::chrono::duration<Rep, Period>& initial_blackout,
61+
std::function<bool (void)> retried_func) {
62+
std::this_thread::sleep_for(initial_blackout);
63+
return retry_for(total_time, time_step, retried_func);
64+
}
65+
66+
}
67+
68+
}
69+
70+
#endif

pre/variant/get_trait.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ namespace pre { namespace variant {
3838

3939
template< class U >
4040
Result operator()(const U&) const {
41-
return typename TraitMetafunction<U>::type{};
41+
return TraitMetafunction<U>::type::value;
4242
}
4343

4444

test/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ function(add_unit_test)
1919

2020
endfunction(add_unit_test)
2121

22+
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
23+
# Disable auto_ptr errors
24+
add_definitions(-Wno-deprecated-declarations)
25+
endif()
26+
2227
## Multithreading support
2328
find_package(Threads REQUIRED)
2429

@@ -67,3 +72,6 @@ add_unit_test(NAME function_traits_test
6772
${Boost_LIBRARIES}
6873
${platform_specific_lib})
6974

75+
add_unit_test(NAME retry_for
76+
LIBS ${CMAKE_THREAD_LIBS_INIT}
77+
${Boost_LIBRARIES})

test/retry_for.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#define BOOST_TEST_MODULE retry_for_test
2+
#include <boost/test/included/unit_test.hpp>
3+
4+
#include <pre/retry_for.hpp>
5+
#include <pre/chrono/chrono_suffixes.hpp>
6+
7+
BOOST_AUTO_TEST_CASE (retry_for_testing) {
8+
using namespace pre::chrono::std;
9+
10+
size_t times = 0;
11+
auto im_happy_only_after_5times = [&times]() {
12+
++times;
13+
std::cout << times << ": I'm " << ((times >= 5) ? "happy" : "unhappy") << std::endl;
14+
return (times >= 5);
15+
};
16+
17+
18+
{
19+
times = 0;
20+
auto start = std::chrono::steady_clock::now();
21+
pre::retry_for(5_sec, 1_sec, im_happy_only_after_5times);
22+
23+
BOOST_REQUIRE((std::chrono::steady_clock::now() - start) > 4_sec);
24+
}
25+
26+
{
27+
times = 0;
28+
auto start = std::chrono::steady_clock::now();
29+
pre::retry_for(5_ms, 1_ms, 200_ms, im_happy_only_after_5times);
30+
31+
BOOST_REQUIRE((std::chrono::steady_clock::now() - start) > 200_ms);
32+
}
33+
}

0 commit comments

Comments
 (0)