On Monday, 25 January 2016 at 21:22:13 UTC, Joseph Rushton Wakeling wrote:
On Monday, 25 January 2016 at 20:26:12 UTC, Era Scarecrow wrote:
What about an alternative allocator? Specifically I'm thinking in C's equivalent which is alloca (allocates directly on the stack with the rest of the variables). If the constructor is a function then that won't work; but if it's inlined then it should work.

I have been wondering about how allocators could help to deal with these problems. Could you put forward a minimal example of how you would see it working?

Most likely alloca would have to be built into the compiler. Here's a crash course in how the stack memory management works. sp=stack pointer, bp=base pointer (more relevant pre 386).

When you prepare to enter a function (or block) the bp register is backed up, the sp is saved in the bp register, then you add your arguments, then the function is entered. After the function is entered it adds to the sp register which give it a block of space for all known local variables at once; then does any assignments it needs to. When you leave the function/block you simply replace the sp register with your backup the bp register. Once you return you restore the old bp register.

 So something close to this:
[code]
  ...
  push bp
  push calling_argument(s)
  call func
  sub sp, -N //size of total arguments pushed
  pop bp //completely done with function call.
  ...


  func: mov bp, sp
  add sp, +N //size of local variables
  // setup variables
  // code

  // cleanup/return
  mov sp, bp
  ret
[/code]

Technically alloca simply returns the current sp, then adds to it the number of bytes you requested. This means you have to run it at the function stack where you want to use it (and not in a called function, otherwise corruption). So inlined functions where alloca's data would remain would be a must. Then it comes down to a simple:

[code]
struct RNG {
  int *state; //add assert to functions that this isn't null
  this(int seed) {
    state = alloca(sizeof(int));
    *state = seed;
  }
}
[/code]

I suppose the alternate is an option to skip/throw-away some numbers that should've been consumed (assuming you want to keep using the same seed), or seeding each per use.

I'm not sure I follow what you mean here or why you think this would work? Could you give a concrete example?

certainly.

[code]
struct RNG {
  ...

  void skip(int x) {assert(x>0); while(x--) popfront();}
}

RNG rnd = RND(seed);
rnd.take(10).writeln;  //loosely based on talk examples
rnd.skip(10);          //skips the 'consumed' numbers.
rnd.take(10).writeln;  //won't have identical output

[/code]

Reply via email to