Is it possible to override the lambda / close destructor of C ++ 11?

I play with the C ++ 11 lambda / close function, trying to write a half-cortin (generator) function.

Below are my codes. They work as expected (GCC 4.9 / Linux).

I have read several online articles that introduce C ++ lambda / clos, now I understand a lambda function as a functor or function object.

My question is: where can I put the destructor code for the closure object? How can I override the default destructor?

I need this function because some coroutines can request certain system resources when I call the function construct and return a closure object (representing the coroutine). But if the caller’s function decides to cancel / kill the operation, a mechanism must be installed to inform the coroutine object to take any action. The ideal place to put the code would be in the destructor, but I cannot find how to do it.

Any suggestions?

#include <iostream>
#include <functional>
#include <time.h>

#define CONCAT01(a, b)                      a##b
#define CONCAT02(a, b)                      CONCAT01(a, b)
#define YIELD()                             \
  do {                                      \
    CONCAT02(ENTRY, __LINE__):              \
    if (EP == && CONCAT02(ENTRY, __LINE__)) \
      EP = 0;                               \
    else                                    \
    {                                       \
      EP = && CONCAT02(ENTRY, __LINE__);    \
      return true;                          \
    }                                       \
  } while (0)

using namespace std;

typedef std::function<bool(void)> coroutine;

coroutine add(int a, int b, int * ret)
{
  timespec start;
  clock_gettime(CLOCK_REALTIME, &start);

  return [=]() mutable -> bool
  {
    timespec now;
    while(1) {
      clock_gettime(CLOCK_REALTIME, &now);
      if (now.tv_sec - start.tv_sec > 1)
        break;

      return true;
    }
    * ret = a + b;
    cout << "add " << a << " " << b << " equals: " << a + b << endl;
    return false;
  };
}

coroutine sum(int a, int b, int c, int * ret)
{
  void* EP = 0;
  coroutine co = 0;
  int tmp = 0;

  return [=] () mutable -> bool
  {
    if (EP) goto *EP;

    co = add(a, b, &tmp);
    while(co())
      YIELD();

    co = add(tmp, c, ret);
    while(co())
      YIELD();

    return false;
  };
}

int main()
{
  int ret;
  coroutine c = sum(1, 2, 4, &ret);
  while (c())
    {
      sleep(1);
      cout << "wakeup" << endl;
    }

  cout << "final: " << ret << endl;

  return 0;
}
+4
source share
1 answer

Here is the object with the task and the task of destruction:

template<class F, class D>
struct coroutine {
  F f;
  D d;
  template<class...Args>
  std::result_of_t<F&(Args...)>
  operator()(Args&&...args){
    return f(std::forward<Args>(args)...);
  }
  ~coroutine() {
    d();
  }
};

a factory for him:

template<class F, class D>
coroutine< std::decay_t<F>, std::decay_t<D> >
make_coroutine( F&& f, D&& d ) {
  return {std::forward<F>(f), std::forward<D>(d)};
}

Some helper macros:

#define COROUTINE_STATE ED=(void*)0
#define START_COROUTINE if (ED) goto *ED
#define FINISH_COROUTINE return false

auto add(int a, int b, int * ret) {
  timespec start;
  clock_gettime(CLOCK_REALTIME, &start);

  return make_coroutine([=]() mutable
  {
    timespec now;
    while(true) {
      clock_gettime(CLOCK_REALTIME, &now);
      if (now.tv_sec - start.tv_sec > 1)
        break;

      return true;
    }
    *ret = a + b;
    cout << "add " << a << " " << b << " equals: " << a + b << endl;
    return false;
  },
  []{
    cout << "adder destroyed\n";
  });
}
auto sum(int a, int b, int c, int * ret)
{
  std::function<bool()> co;
  int tmp = 0;

  return make_coroutine([=,COROUTINE_STATE] () mutable
    {
      START_COROUTINE;
      co = add(a, b, &tmp);
      while(co())
        YIELD();

      co = add(tmp, c, ret);
      while(co())
        YIELD();

      FINISH_COROUTINE;
    },
    []{
      std::cout << "winter is coming\n";
    }
  );
}

, - "", ED.

COROUTINE_STATE, ED. START_COROUTINE; , YIELD(), , FINISH_COROUTINE;, .

- . co, , co, , =.

, , "" FINISH_COROUTINE; somesuch. : , ED :

template<class F>
struct coroutine {
  void** ED = nullptr;
  F f;
  template<class...Args>
  std::result_of_t< F&(void**,Args...) >
  operator()(Args&&...args){
    return f(ED, std::forward<Args>(args)...);
  }
  ~coroutine() {
    void* end = 0;
    f(&end);
  }
};
template<class F>
coroutine<std::decay_t<F>>
make_coroutine(F&& f){return {std::forward<F>{f}};}
#define START_COROUTINE [=](void** ED)mutable{\
  if (ED){if (*ED)goto *ED;\
  else goto Cleanup;}
#define END_COROUTINE_BODY return false; Cleanup:
#define END_COROUTINE_CLEANUP }
#define END_COROUTINE END_COROUTINE_BODY; END_COROUTINE_CLEANUP

auto sum(int a, int b, int c, int * ret)
{
  std::function<bool()> co = 0;
  int tmp = 0;

  return
  START_COROUTINE
    co = add(a, b, &tmp);
    while(co())
      YIELD();

    co = add(tmp, c, ret);
    while(co())
      YIELD();
  END_COROUTINE_BODY
    std::cout << "winter is coming\n";
  END_COROUTINE_CLEANUP;
}

- . ED , nullptr, , " ". , .

, std::function. , ( ), , .

, coroutine, , std::function<bool(). .

+4

Source: https://habr.com/ru/post/1583781/


All Articles