0

I'm looking to implement a generic temporary retry mechanism (retries only a set number of times) in C. I'm looking for similar functionality to the GNU TEMP_FAILURE_RETRY macro.

What I have so far:

#define TEMP_RETRY_COUNT 10
#define TEMP_RETRY( exp )               \
  ({                                    \
    int _attemptc_ = TEMP_RETRY_COUNT;  \
    bool _resultb_;                     \
    while ( _attemptc_-- )              \
      if ( _resultb_ = exp ) break;     \
    _resultb_;                          \
  })

Works just fine. I'm trying to suppress the warnings the compiler warnings now and looking for something cleaner:

bleh.c: In function ‘main’:
bleh.c:38:3: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
   if ( TEMP_RETRY( bleh() ) )
   ^
bleh.c:46:3: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
   TEMP_RETRY( bleh() );

Thank you for any replies! It needn't be a macro. Also, exp can be presumed to return a boolean (or equivalent).

Shreyas
  • 667
  • 2
  • 7
  • 20
  • 2
    how about just adding the parens that the compiler suggests? That should eliminate the warning message. for instance: `if ( (TEMP_RETRY( bleh() )) )` – user3629249 Aug 30 '18 at 17:52
  • 2
    `if ( __RESULT__ = exp )` --> `if ( (__RESULT__ = exp) )` – user3386109 Aug 30 '18 at 17:53
  • 1
    @user3386109 Thanks :) (couldn't figure out where it wanted parentheses) – Shreyas Aug 30 '18 at 17:54
  • 4
    What makes you think that using lots of "_" in your identifiers is a good idea? That kind of identifiers is reserved and therefor you can rely on nobody using them? – Yunnosch Aug 30 '18 at 18:02
  • @Yunnosch true, especially `__RESULT__`; I've definitely seen that one before. – Shreyas Aug 30 '18 at 18:03

1 Answers1

2

Silly me:

#define TEMP_RETRY_COUNT 10
#define TEMP_RETRY( exp )               \
  ({                                    \
    int _attemptc_ = TEMP_RETRY_COUNT;  \
    bool _resultb_;                     \
    while ( _attemptc_-- )              \
      if ( (_resultb_ = exp) ) break;   \
    _resultb_;                          \
  })
Shreyas
  • 667
  • 2
  • 7
  • 20
  • Are you sure this compiles? Doesn't seem to for me. `error C2143: syntax error : missing ')' before '{'` and `error C2143: syntax error : missing ';' before '{'` See also answer to https://stackoverflow.com/questions/8302547/temp-failure-retry-and-use-gnu which has a simple `do` loop. – Richard Chambers Aug 30 '18 at 18:28
  • @RichardChambers Is that the Microsoft compiler? I'm sure there'd be a way to fix that - I'll check soon. I tested warning-free on gcc version 4.8.5 – Shreyas Aug 30 '18 at 19:06
  • 2
    @RichardChambers The `({ })` syntax is a gcc extension known as a [statement expression](https://stackoverflow.com/questions/4475786/why-is-this-valid-c-123-evaluates-to-123/4475790#4475790). – user3386109 Aug 30 '18 at 19:54
  • 1
    The standard protocol for expression arguments to macros is to enclose the argument in parentheses when it is used in the expansion — `if ((_resultb_ = (exp))) break;` — which prevents a variety of misinterpretations. Personally, and in general, I prefer an explicit test — `if ((_resultb_ = (exp)) != 0) break;` — but many don't agree. In this case, your `_resultb_` is a boolean; you might not need the explicit test in the same way. – Jonathan Leffler Aug 30 '18 at 20:02
  • @user3386109 Looks like Visual Studio doesn't support that syntax of http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html even in VS 2017. I have had a time or two when that would have been helpful. – Richard Chambers Aug 30 '18 at 20:10