mardi 21 avril 2015

Is it possible to override C++11 lambda/closure destructor?

I am playing with C++11 lambda/closure feature, trying to write a semi-coroutine (generator) function.

The following codes are my experiment. They works as expected (GCC 4.9/Linux).

I have read several on-line articles introducing C++ lambda/closure, now I understand the lambda function as a functor or function object.

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

I need this function because, some coroutines may request certain system resources when I call the function constructing and returning the closure object (which represents a coroutine). But if the caller function decide to cancel / kill the operation, there should be a mechanism to inform the coroutine object to take some action. The ideal place to put code will be in the destructor, but I cannot find how.

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;
}

Aucun commentaire:

Enregistrer un commentaire