Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Copyable stack delegates, implemented with structs and classes

Part of DelegateCategory

Description

Some examples of how to copy a stack's local variables. Useful if you don't want to modify the original local variables, or if you want to return a stack delegates.

Example

/* This shows two different ways of creating a pseudo-copied stack delegate.
 *
 * The struct method is more efficient.  However, it is a bit harder to write & understand.
 * Also, it requires that you build a delegate by hand using a union, and that may not be
 * portable across all platforms or compilers.
 *
 * The class method is easier to understand and should be totally portable.  However,
 * it is less efficient because of the overhead inherent in a class.
 */

import std.c.stdio;

int RunDelegate(int delegate() d, int count) {
  assert(count > 0);

  int ret;
  for(int i=0; i<count; i++) {
    ret = d();
/*    printf("RunDelegate: cycle %d of %d returned %d\n", i+1,count,ret); */
  }
  return ret;
}


int main() {
  int delegate() d1 = getS(2);
  int delegate() d2 = getS(3);
  int delegate() d3 = getC(2);
  int delegate() d4 = getC(3);

  printf("main: RunDelegate(d1,4) returned %d\n", RunDelegate(d1,4));
  printf("main: RunDelegate(d1,4) returned %d\n", RunDelegate(d1,4));
  printf("main: RunDelegate(d2,4) returned %d\n", RunDelegate(d2,4));
  printf("main: RunDelegate(d2,4) returned %d\n", RunDelegate(d2,4));
  printf("main: RunDelegate(d3,4) returned %d\n", RunDelegate(d3,4));
  printf("main: RunDelegate(d3,4) returned %d\n", RunDelegate(d3,4));
  printf("main: RunDelegate(d4,4) returned %d\n", RunDelegate(d4,4));
  printf("main: RunDelegate(d4,4) returned %d\n", RunDelegate(d4,4));

  return 0;
}

/* both getS() and getC() return stack-copy style delegates.  In each case,
 * the delegate stores the argument to the function, and a counter.  Each time
 * that the delegate is called, the counter is multiplied by the argument, and
 * the result is returned.
 *
 * The end result is that, if you create a delegate with an argument of x and you
 * call it y times, then the y-th time it will return
 *     x^y
 */

/* getS() returns the delegate using the struct method;
 * getC() returns the delegate using the class method.
 */

struct GetS_Data {
  int base;
  int counter;
};

union delegate_union {
  int delegate() dg;
  struct {
    void *ptr;
    int function(void*) func;
  };
};

int delegate() getS(int base) {
  GetS_Data *data = new GetS_Data[1];
  data.base = base;
  data.counter = 1;

  delegate_union u;
  u.func = function int(void *arg) {
             GetS_Data *data = cast(GetS_Data*)arg;
             data.counter *= data.base;
             return data.counter;
           };
  u.ptr = data;

  return u.dg;
}


class GetC_Data {
  int counter;
  int base;

  this(int base) {
    this.base = base;
    this.counter = 1;
  }

  int func() {
    counter *= base;
    return counter;
  }
}

int delegate() getC(int base) {
  GetC_Data data = new GetC_Data(base);
  return &data.func;
}

Source

Link http://www.dsource.org/tutorials/index.php?show_example=110
Posted by Anonymous
Date/Time Mon Jul 26, 2004 5:56 pm