www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - A naive attempt at a refcounted class proxy

reply "aldanor" <i.s.smirnov gmail.com> writes:
This discussion: 
http://forum.dlang.org/thread/bqtcdpsopxmnfbjyrrzf forum.dlang.org 
-- led me wondering if it would be possible to create some 
crippled version of a class proxy that is based on RefCounted and 
came up with something like this:

struct Box(T) if (is(T == class)) {
      disable this();

     this(Args...)(Args args) {
         _payload._refCounted.initialize(new T(args));
     }

     private {
         struct _Box(T) {
             private T _instance;

             ~this() {
                 destroy(_instance);
             }
         }
         RefCounted!(_Box!T) _payload;
     }

     ~this() {
     }

     auto opDispatch(string name, Args...)(Args args) {
         return mixin("_payload._instance.%s(args)".format(name));
     }
}

which lets you create Box!SomeClass(args) and it will be 
refcounted unless you escape references and do other weird stuff.

It actually sort of seems to work at first glance, at least it 
seems like it does... But with my D experience being fairly 
limited I wonder what the potential pitfalls would be?

Full source code with example and stdout:
https://gist.github.com/aldanor/d5fb5e45ddf3dd2cb642
Jan 13 2015
parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Tue, 13 Jan 2015 16:17:51 +0000
aldanor via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 This discussion:=20
 http://forum.dlang.org/thread/bqtcdpsopxmnfbjyrrzf forum.dlang.org=20
 -- led me wondering if it would be possible to create some=20
 crippled version of a class proxy that is based on RefCounted and=20
 came up with something like this:
=20
 struct Box(T) if (is(T =3D=3D class)) {
       disable this();
=20
      this(Args...)(Args args) {
          _payload._refCounted.initialize(new T(args));
      }
=20
      private {
          struct _Box(T) {
              private T _instance;
=20
              ~this() {
                  destroy(_instance);
              }
          }
          RefCounted!(_Box!T) _payload;
      }
=20
      ~this() {
      }
=20
      auto opDispatch(string name, Args...)(Args args) {
          return mixin("_payload._instance.%s(args)".format(name));
      }
 }
=20
 which lets you create Box!SomeClass(args) and it will be=20
 refcounted unless you escape references and do other weird stuff.
=20
 It actually sort of seems to work at first glance, at least it=20
 seems like it does... But with my D experience being fairly=20
 limited I wonder what the potential pitfalls would be?
=20
 Full source code with example and stdout:
 https://gist.github.com/aldanor/d5fb5e45ddf3dd2cb642
it's not that hard to make a boxed class. what is really hard is to make functions that expects the class itself to accept it's boxed variant too and behave correctly with it. either you have to unbox it (and then hope that it will not leak), or write two set of functions, for "real" class and for boxed one. and then you may want to inherit from your class and pass that inherited class to one of the functions... and now you have three sets. and so on... as structs can't be inherited, there is no such problem for structs.
Jan 13 2015
parent reply "aldanor" <i.s.smirnov gmail.com> writes:
On Tuesday, 13 January 2015 at 16:43:09 UTC, ketmar via 
Digitalmars-d-learn wrote:
 On Tue, 13 Jan 2015 16:17:51 +0000
 aldanor via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:

 This discussion: 
 http://forum.dlang.org/thread/bqtcdpsopxmnfbjyrrzf forum.dlang.org 
 -- led me wondering if it would be possible to create some 
 crippled version of a class proxy that is based on RefCounted 
 and came up with something like this:
 
 struct Box(T) if (is(T == class)) {
       disable this();
 
      this(Args...)(Args args) {
          _payload._refCounted.initialize(new T(args));
      }
 
      private {
          struct _Box(T) {
              private T _instance;
 
              ~this() {
                  destroy(_instance);
              }
          }
          RefCounted!(_Box!T) _payload;
      }
 
      ~this() {
      }
 
      auto opDispatch(string name, Args...)(Args args) {
          return 
 mixin("_payload._instance.%s(args)".format(name));
      }
 }
 
 which lets you create Box!SomeClass(args) and it will be 
 refcounted unless you escape references and do other weird 
 stuff.
 
 It actually sort of seems to work at first glance, at least it 
 seems like it does... But with my D experience being fairly 
 limited I wonder what the potential pitfalls would be?
 
 Full source code with example and stdout:
 https://gist.github.com/aldanor/d5fb5e45ddf3dd2cb642
it's not that hard to make a boxed class. what is really hard is to make functions that expects the class itself to accept it's boxed variant too and behave correctly with it. either you have to unbox it (and then hope that it will not leak), or write two set of functions, for "real" class and for boxed one. and then you may want to inherit from your class and pass that inherited class to one of the functions... and now you have three sets. and so on... as structs can't be inherited, there is no such problem for structs.
That's completely valid. Where it would work though, I think, is if all classes are private/package and only expect/return boxed classes and never the references. This way you sort of get multiple inheritance (for the internal implementation) without polymorphism, but with value semantics and ref counting for the outward interface.
Jan 13 2015
next sibling parent reply "aldanor" <i.s.smirnov gmail.com> writes:
On Tuesday, 13 January 2015 at 18:12:45 UTC, aldanor wrote:
 On Tuesday, 13 January 2015 at 16:43:09 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Tue, 13 Jan 2015 16:17:51 +0000
 aldanor via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:

 This discussion: 
 http://forum.dlang.org/thread/bqtcdpsopxmnfbjyrrzf forum.dlang.org 
 -- led me wondering if it would be possible to create some 
 crippled version of a class proxy that is based on RefCounted 
 and came up with something like this:
 
 struct Box(T) if (is(T == class)) {
      disable this();
 
     this(Args...)(Args args) {
         _payload._refCounted.initialize(new T(args));
     }
 
     private {
         struct _Box(T) {
             private T _instance;
 
             ~this() {
                 destroy(_instance);
             }
         }
         RefCounted!(_Box!T) _payload;
     }
 
     ~this() {
     }
 
     auto opDispatch(string name, Args...)(Args args) {
         return 
 mixin("_payload._instance.%s(args)".format(name));
     }
 }
 
 which lets you create Box!SomeClass(args) and it will be 
 refcounted unless you escape references and do other weird 
 stuff.
 
 It actually sort of seems to work at first glance, at least 
 it seems like it does... But with my D experience being 
 fairly limited I wonder what the potential pitfalls would be?
 
 Full source code with example and stdout:
 https://gist.github.com/aldanor/d5fb5e45ddf3dd2cb642
it's not that hard to make a boxed class. what is really hard is to make functions that expects the class itself to accept it's boxed variant too and behave correctly with it. either you have to unbox it (and then hope that it will not leak), or write two set of functions, for "real" class and for boxed one. and then you may want to inherit from your class and pass that inherited class to one of the functions... and now you have three sets. and so on... as structs can't be inherited, there is no such problem for structs.
That's completely valid. Where it would work though, I think, is if all classes are private/package and only expect/return boxed classes and never the references. This way you sort of get multiple inheritance (for the internal implementation) without polymorphism, but with value semantics and ref counting for the outward interface.
// thanks ketmar for answering another one of my stupid questions on n.g. :)
Jan 13 2015
parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Tue, 13 Jan 2015 18:14:40 +0000
aldanor via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 // thanks ketmar for answering another one of my stupid questions=20
 on n.g. :)
ah, 'cmon, your questions aren't stupid at all! ;-)
Jan 13 2015
prev sibling parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Tue, 13 Jan 2015 18:12:44 +0000
aldanor via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 On Tuesday, 13 January 2015 at 16:43:09 UTC, ketmar via=20
 Digitalmars-d-learn wrote:
 On Tue, 13 Jan 2015 16:17:51 +0000
 aldanor via Digitalmars-d-learn=20
 <digitalmars-d-learn puremagic.com>
 wrote:

 This discussion:=20
 http://forum.dlang.org/thread/bqtcdpsopxmnfbjyrrzf forum.dlang.org=20
 -- led me wondering if it would be possible to create some=20
 crippled version of a class proxy that is based on RefCounted=20
 and came up with something like this:
=20
 struct Box(T) if (is(T =3D=3D class)) {
       disable this();
=20
      this(Args...)(Args args) {
          _payload._refCounted.initialize(new T(args));
      }
=20
      private {
          struct _Box(T) {
              private T _instance;
=20
              ~this() {
                  destroy(_instance);
              }
          }
          RefCounted!(_Box!T) _payload;
      }
=20
      ~this() {
      }
=20
      auto opDispatch(string name, Args...)(Args args) {
          return=20
 mixin("_payload._instance.%s(args)".format(name));
      }
 }
=20
 which lets you create Box!SomeClass(args) and it will be=20
 refcounted unless you escape references and do other weird=20
 stuff.
=20
 It actually sort of seems to work at first glance, at least it=20
 seems like it does... But with my D experience being fairly=20
 limited I wonder what the potential pitfalls would be?
=20
 Full source code with example and stdout:
 https://gist.github.com/aldanor/d5fb5e45ddf3dd2cb642
it's not that hard to make a boxed class. what is really hard=20 is to make functions that expects the class itself to accept it's=20 boxed variant too and behave correctly with it. either you have to unbox it (and then hope that it will not=20 leak), or write two set of functions, for "real" class and for boxed one.=20 and then you may want to inherit from your class and pass that=20 inherited class to one of the functions... and now you have three sets.=20 and so on... as structs can't be inherited, there is no such problem for=20 structs.
=20 That's completely valid. Where it would work though, I think, is=20 if all classes are private/package and only expect/return boxed=20 classes and never the references. This way you sort of get=20 multiple inheritance (for the internal implementation) without=20 polymorphism, but with value semantics and ref counting for the=20 outward interface.
and then you can go with structures in the first place, i think. remember that you have that k00l `alias this` trick for them!
Jan 13 2015
parent reply "aldanor" <i.s.smirnov gmail.com> writes:
On Tuesday, 13 January 2015 at 18:19:42 UTC, ketmar via
Digitalmars-d-learn wrote:
 and then you can go with structures in the first place, i think.
 remember that you have that k00l `alias this` trick for them!
Which doesn't always help in case of multiple inheritance :( e.g. the blasted hdf c++ class hierarchy example.
Jan 13 2015
parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Tue, 13 Jan 2015 18:36:15 +0000
aldanor via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 On Tuesday, 13 January 2015 at 18:19:42 UTC, ketmar via
 Digitalmars-d-learn wrote:
 and then you can go with structures in the first place, i think.
 remember that you have that k00l `alias this` trick for them!
Which doesn't always help in case of multiple inheritance :( e.g. the blasted hdf c++ class hierarchy example.
multiple `alias this` may help here... to some extent. ;-)
Jan 13 2015
parent reply "Francesco Cattoglio" <francesco.cattoglio gmail.com> writes:
On Tuesday, 13 January 2015 at 18:52:25 UTC, ketmar via 
Digitalmars-d-learn wrote:
 On Tue, 13 Jan 2015 18:36:15 +0000
 aldanor via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:

 On Tuesday, 13 January 2015 at 18:19:42 UTC, ketmar via
 Digitalmars-d-learn wrote:
 and then you can go with structures in the first place, i 
 think.
 remember that you have that k00l `alias this` trick for them!
Which doesn't always help in case of multiple inheritance :( e.g. the blasted hdf c++ class hierarchy example.
multiple `alias this` may help here... to some extent. ;-)
Are they even enabled in dmd already? 2.65 still reports the "there can only be one alias this" error.
Jan 15 2015
parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Thu, 15 Jan 2015 11:48:23 +0000
Francesco Cattoglio via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:

 On Tuesday, 13 January 2015 at 18:52:25 UTC, ketmar via=20
 Digitalmars-d-learn wrote:
 On Tue, 13 Jan 2015 18:36:15 +0000
 aldanor via Digitalmars-d-learn=20
 <digitalmars-d-learn puremagic.com>
 wrote:

 On Tuesday, 13 January 2015 at 18:19:42 UTC, ketmar via
 Digitalmars-d-learn wrote:
 and then you can go with structures in the first place, i=20
 think.
 remember that you have that k00l `alias this` trick for them!
Which doesn't always help in case of multiple inheritance :(=20 e.g. the blasted hdf c++ class hierarchy example.
multiple `alias this` may help here... to some extent. ;-)
=20 Are they even enabled in dmd already? 2.65 still reports the=20 "there can only be one alias this" error.
the PR is approved for inclusion, so eventually it will be in 2.067. at least i hope it will. sorry, i tend to forget that not everybody using HEAD builds with custom patches applied. ;-)
Jan 15 2015