News for hackers. Stuff that matters.
Re:Memory – Part 4: Intersec’s custom allocators by epistasis on Tuesday October 01, 2013 @09:34AM (#6475971)
Yes, I wish that cleanup was a portable C feature! Glad to see that GNU is trying something here, as it would serve as a prototype for standardization. Perhaps in a future version of C...
Re:Memory – Part 4: Intersec’s custom allocators by qznc on Tuesday October 01, 2013 @09:41AM (#6476027)
There is an extended version of C, which is has this feature and is nearly as widely ported as C. They aptly named it C++.
Re:Memory – Part 4: Intersec’s custom allocators by epistasis on Tuesday October 01, 2013 @09:49AM (#6476076)
C++ has an IMHO worse version of this feature, that requires a custom type, and that only allows a single function to be called for that type.

This is more like Go's defer, and is far more appropriate for my use cases.

Re:Memory – Part 4: Intersec’s custom allocators by vidarh on Tuesday October 01, 2013 @11:30AM (#6476800)
I haven't written much C++ in quite a few years - mostly do Ruby these days, so I'm sure I'm making some terribly embarrassing faux pas or other with the example below. But you don't need more than the C++ functionality to compose your own variations if you want more flexibility.

For example:

  #include <vector>
  #include <iostream>

  class Scope {

  private:
    typedef std::vector<void (*)()> FV;
    FV fv;
  public:
    void on_return(void (* f)()) {
      fv.push_back(f);
    }

    ~Scope() {
      for (FV::iterator it = fv.begin(); it != fv.end(); ++it) {
        (*it)();
      }
    }
  };

  void foo() {
    std::cout << "Hello ";
  }

  void bar() {
    std::cout << "World" << std::endl;
  }

  int main() {
    Scope scope;

    scope.on_return(foo);
    scope.on_return(bar);

    std::cout << "Hi" << std::endl;
  }

With C++11 lambda syntax you can do quite a bit better.

Expanding that into something providing at least most of what Go's "defer" does shouldn't be too hard.

Re:Memory – Part 4: Intersec’s custom allocators by stormbrew on Tuesday October 01, 2013 @04:28PM (#6478882)
Better would be to just have the Scope class take a single function to run and establish multiple stack entries for them. This would be my version:

  #include <cstdio>

  template <typename tFunc>
  class ScopeFunc {
  private:
    tFunc mFunc;

  public:
    ScopeFunc(tFunc func) : mFunc(func) {}

    ~ScopeFunc() {
      mFunc();
    }
  };

  template <typename tFunc>
  ScopeFunc<tFunc> on_return(tFunc func)
  {
    return ScopeFunc<tFunc>(func);
  }

  int main() {
    auto first = on_return([]() { std::puts("first"); });
    auto second = on_return([]() { std::puts("second"); });

    std::puts("Hello");
  }
Note that this is C++11, using lambdas. Also that the output will be reversed from your expectation since it's a lifo, but that's probably actually what you want for real deferred behaviour and not text output.

It also optimizes nicely, which yours may not because the loop unrolling may be complicated and there's a higher chance of aliasing of the function pointers in the vector:

  0000000000400600 <main>:
    400600:	53                   	push   %rbx
    400601:	bf e4 07 40 00       	mov    $0x4007e4,%edi
    400606:	e8 b5 ff ff ff       	callq  4005c0 <puts@plt>
    40060b:	bf ea 07 40 00       	mov    $0x4007ea,%edi
    400610:	e8 ab ff ff ff       	callq  4005c0 <puts@plt>
    400615:	bf f1 07 40 00       	mov    $0x4007f1,%edi
    40061a:	e8 a1 ff ff ff       	callq  4005c0 <puts@plt>
    40061f:	31 c0                	xor    %eax,%eax
    400621:	5b                   	pop    %rbx
    400622:	c3                   	retq
Re:Memory – Part 4: Intersec’s custom allocators by epistasis on Tuesday October 01, 2013 @11:54AM (#6476958)
Good idea, this definitely accomplishes the same functionality, but it's done at runtime, rather than the compiler knowing all the functions at compile time. Perhaps a minor difference for most cases, though...

I would still prefer a C extension... Perhaps I should just use Go these days, though ironically all these memory allocation policies are useless in a GC language.

Re:Memory – Part 4: Intersec’s custom allocators by stormbrew on Tuesday October 01, 2013 @04:30PM (#6478891)
You underestimate the compiler. This formulation might be tricky, but the version I just posted (adjacent to this post) definitely leaves the compiler knowing exactly what's going to be called when the function exits.
Re:Memory – Part 4: Intersec’s custom allocators by eliasmacpherson on Tuesday October 01, 2013 @10:34AM (#6476418)
Then "they" later discovered the name was no longer apt and it should have been called ++C.
Re:Memory – Part 4: Intersec’s custom allocators by yk on Tuesday October 01, 2013 @11:20AM (#6476732)
C++ is the correct name, you write a few thousand lines C code and then write class LargeObject in the first line. So C++.
Re:Memory – Part 4: Intersec’s custom allocators by eliasmacpherson on Tuesday October 01, 2013 @01:10PM (#6477492)
I'm concerned that would create a temporary variable, I'll try and decipher the ISO spec to verify. Is LargeObject POD?
Re:Memory – Part 4: Intersec’s custom allocators by z3phyr on Tuesday October 01, 2013 @10:50AM (#6476534)
Would C++ completely replace C, EVER? On top of that extensions like Unified Parallel C and Cello come up!
Re:Memory – Part 4: Intersec’s custom allocators by qznc on Wednesday October 02, 2013 @03:01AM (#6481095)
No. The C vs C++ question is simple language vs comprehensive language. A simple language might be preferred for various reasons. For example, code is easier to review, which is Linus Torvalds argument. Bindings to other languages are easier to create. Compiler is simpler, which might be important for embedded and high-reliability jobs.