www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - RAII

reply Arun Chandrasekaran <aruncxy gmail.com> writes:
I'm trying to write an RAII wrapper on Linux.

I understand struct in D doesn't have default constructor (for 
.init reasons).
I don't want to use `scope`.

Is there an elegant way to achieve this in D?

```
import core.sys.posix.pthread;
import core.sys.posix.sys.types;

/// Makes pthread_mutexattr_t cleanup easy when using exceptions
struct mutexattr_wrapper
{
     /// Constructor
     this(bool _)
     {
         if (pthread_mutexattr_init(&m_attr) != 0 ||
             pthread_mutexattr_setpshared(&m_attr, 
PTHREAD_PROCESS_SHARED)!= 0)
           // may be I will add few more methods here
           throw custom_exception("pthread_mutexattr_xxxx failed");
     }

     /// Destructor
     ~this() {  pthread_mutexattr_destroy(&m_attr);  }

     /// This allows using mutexattr_wrapper as pthread_mutexattr_t
     alias m_attr this;

     pthread_mutexattr_t m_attr;
}
```
Feb 23
next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
Arun Chandrasekaran wrote:

 I'm trying to write an RAII wrapper on Linux.

 I understand struct in D doesn't have default constructor (for .init 
 reasons).
 I don't want to use `scope`.

 Is there an elegant way to achieve this in D?
why not static method or free function that returns struct? due to NRVO[0] it won't even be copied. auto lock = MyWrapper(); `MyWrapper()` may return voldemort type, so user won't create your struct accidentally. [0] https://dlang.org/glossary.html#nrvo
Feb 23
next sibling parent reply kinke <noone nowhere.com> writes:
On Thursday, 23 February 2017 at 09:57:09 UTC, ketmar wrote:
 Arun Chandrasekaran wrote:
 Is there an elegant way to achieve this in D?
why not static method or free function that returns struct? due to NRVO[0] it won't even be copied.
That's not elegant. You need a factory function for each type containing one of these structs then.
Feb 23
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 23 February 2017 at 10:48:38 UTC, kinke wrote:
 That's not elegant. You need a factory function for each type 
 containing one of these structs then.
A constructor is just a factory function with a special name... it is almost equal amount of work.
Feb 23
parent reply kinke <noone nowhere.com> writes:
On Thursday, 23 February 2017 at 14:24:14 UTC, Adam D. Ruppe 
wrote:
 On Thursday, 23 February 2017 at 10:48:38 UTC, kinke wrote:
 That's not elegant. You need a factory function for each type 
 containing one of these structs then.
A constructor is just a factory function with a special name... it is almost equal amount of work.
Sorry but this is just completely wrong. RAII is all about me NOT having to call special functions all over the place. struct S { this() { /* initialize */ } } S[123] myArray; // hooray, no need to invoke a factory in a loop struct Container { S s; // hooray, implicit this() automatically calls s.this() }
Feb 23
parent kinke <noone nowhere.com> writes:
On Thursday, 23 February 2017 at 18:46:58 UTC, kinke wrote:
 A constructor is just a factory function with a special name...
Wrt. the special name, that's obviously extremely useful for generic templates (containers etc.).
Feb 23
prev sibling parent reply Arun Chandrasekaran <aruncxy gmail.com> writes:
On Thursday, 23 February 2017 at 09:57:09 UTC, ketmar wrote:
 Arun Chandrasekaran wrote:

 I'm trying to write an RAII wrapper on Linux.

 I understand struct in D doesn't have default constructor (for 
 .init reasons).
 I don't want to use `scope`.

 Is there an elegant way to achieve this in D?
why not static method or free function that returns struct? due to NRVO[0] it won't even be copied. auto lock = MyWrapper(); `MyWrapper()` may return voldemort type, so user won't create your struct accidentally. [0] https://dlang.org/glossary.html#nrvo
Thanks for your help. NRVO looks interesting. However this may not be RAII after all. Or may be too much of C++ has spoiled me. I am not familiar enough with D to appreciate/question the language design choice. I'll accept this and move forward and see how my code evolves. Nevertheless, I'm still learning something new. :)
Feb 23
parent ketmar <ketmar ketmar.no-ip.org> writes:
Arun Chandrasekaran wrote:

 On Thursday, 23 February 2017 at 09:57:09 UTC, ketmar wrote:

 Thanks for your help. NRVO looks interesting. However this may not be 
 RAII after all. Or may be too much of C++ has spoiled me. I am not 
 familiar enough with D to appreciate/question the language design 
 choice. I'll accept this and move forward and see how my code 
 evolves. Nevertheless, I'm still learning something new. :)
also, why structs at all? there are another ways! ;-) void doWithLock (scope void delegate () action) { lockSomething(); scope(exit) unlockSomething(); action(); } no, wait, this is not so limiting as it may look! void foo () { int i = 42; doWithLock({ writeln("i=", i); // yay, 42! }); } this looks *almost* like `synchronized(obj) { ... }`! and if we'll ever press D devs to allow us to omit "()" when the only argument is arg-less lambda... it will be indistinguishable from built-in! ;-)
Feb 23
prev sibling next sibling parent Adrian Matoga <dlang.spam matoga.info> writes:
On Thursday, 23 February 2017 at 09:52:26 UTC, Arun 
Chandrasekaran wrote:
 I'm trying to write an RAII wrapper on Linux.

 I understand struct in D doesn't have default constructor (for 
 .init reasons).
 I don't want to use `scope`.

 Is there an elegant way to achieve this in D?
static opCall() is the way to emulate an argumentless struct constructor. You still need to call it explicitly, though: ``` import std.stdio : writefln; struct Foo { int a; static Foo opCall() { Foo foo; foo.a = 42; return foo; } ~this() { writefln("destroyed with a=%d", a); } disable this(this); disable void opAssign(Foo); } void main() { auto foo1 = Foo(); // ok Foo foo2; // == Foo.init } ```
Feb 23
prev sibling parent reply cym13 <cpicard openmailbox.org> writes:
On Thursday, 23 February 2017 at 09:52:26 UTC, Arun 
Chandrasekaran wrote:
 I'm trying to write an RAII wrapper on Linux.

 I understand struct in D doesn't have default constructor (for 
 .init reasons).
 I don't want to use `scope`.

 Is there an elegant way to achieve this in D?

 ```
 import core.sys.posix.pthread;
 import core.sys.posix.sys.types;

 /// Makes pthread_mutexattr_t cleanup easy when using exceptions
 struct mutexattr_wrapper
 {
     /// Constructor
     this(bool _)
     {
         if (pthread_mutexattr_init(&m_attr) != 0 ||
             pthread_mutexattr_setpshared(&m_attr, 
 PTHREAD_PROCESS_SHARED)!= 0)
           // may be I will add few more methods here
           throw custom_exception("pthread_mutexattr_xxxx 
 failed");
     }

     /// Destructor
     ~this() {  pthread_mutexattr_destroy(&m_attr);  }

     /// This allows using mutexattr_wrapper as 
 pthread_mutexattr_t
     alias m_attr this;

     pthread_mutexattr_t m_attr;
 }
 ```
It reminds me of https://w0rp.com/blog/post/an-raii-constructor-by-another-na e-is-just-as-sweet/ which isn't what you want but may be interesting anyway.
Feb 23
parent Arun Chandrasekaran <aruncxy gmail.com> writes:
On Thursday, 23 February 2017 at 21:05:48 UTC, cym13 wrote:
 It reminds me of 
 https://w0rp.com/blog/post/an-raii-constructor-by-another-na
e-is-just-as-sweet/ which isn't what you want but may be interesting anyway.
It is interesting, indeed, thanks.
Feb 23