fork download
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. struct MultiCallToken
  5. {
  6. private:
  7. bool inUse = false;
  8.  
  9. friend class MultiCallGuard;
  10. };
  11.  
  12. // guards against multiple calls
  13. class MultiCallGuard
  14. {
  15. public:
  16. ~MultiCallGuard()
  17. {
  18. if(token && free)
  19. {
  20. token->inUse = false;
  21. }
  22. }
  23.  
  24. operator bool()
  25. {
  26. if(token->inUse)
  27. return false;
  28.  
  29. return token->inUse = free = true;
  30. }
  31.  
  32. MultiCallGuard(const MultiCallGuard&) = delete;
  33. MultiCallGuard& operator=(const MultiCallGuard&) = delete;
  34. MultiCallGuard(MultiCallGuard&& g) : token(g.token), free(g.free)
  35. {
  36. g.token = nullptr;
  37. }
  38.  
  39. MultiCallGuard& operator=(MultiCallGuard&& g)
  40. {
  41. token = g.token;
  42. free = g.free;
  43. g.token = nullptr;
  44. }
  45.  
  46. private:
  47. MultiCallGuard(MultiCallToken& token) : token(&token), free(false) {}
  48.  
  49. MultiCallToken* token;
  50. bool free;
  51.  
  52. friend MultiCallGuard guard(MultiCallToken&);
  53. };
  54.  
  55. MultiCallGuard guard(MultiCallToken& t)
  56. {
  57. MultiCallGuard g(t);
  58. return g;
  59. }
  60.  
  61. MultiCallToken fooToken;
  62. MultiCallToken barToken;
  63.  
  64. void bar();
  65.  
  66. void foo()
  67. {
  68. if(auto g = guard(fooToken))
  69. {
  70. cout << "foo called\n";
  71.  
  72. bar();
  73. }
  74. }
  75.  
  76. void bar()
  77. {
  78. if(auto g = guard(barToken))
  79. {
  80. cout << "bar called\n";
  81.  
  82. foo();
  83. }
  84. }
  85.  
  86. int main()
  87. {
  88. cout << ">> explicit call to foo:\n";
  89.  
  90. foo();
  91.  
  92. cout << "\n>> explicit call to bar\n";
  93.  
  94. bar();
  95.  
  96. return 0;
  97. }
Success #stdin #stdout 0s 3456KB
stdin
Standard input is empty
stdout
>> explicit call to foo:
foo called
bar called

>> explicit call to bar
bar called
foo called