digitalmars.D - Libraries, users, DLLs
- antiAlias (18/18) Aug 08 2004 Currently, D libraries are predominantly linked in a static fashion. I h...
- Lars Ivar Igesund (13/36) Aug 09 2004 I have to say that I agree. DLL's are supposed to be the glorious way
- Matthew (3/39) Aug 08 2004 If someone could right a brief - 2 page? - treatise on the current state...
- pragma (45/81) Aug 09 2004 Honestly, I've already surmounted a huge number of issues regarding D DL...
- antiAlias (78/165) Aug 19 2004 What you suggest sounds really promising Eric, and it would certainly he...
- Matthew (39/217) Aug 19 2004 Kris,
- antiAlias (73/304) Aug 19 2004 I agree that #1 (the shared GC) is a primary issue. On the face of it, w...
- Matthew (8/337) Aug 19 2004 It sounds promising. I'd like to hear more fine details, though.
- pragma (49/75) Aug 20 2004 I'll work on a more detailed treatment as soon as time permits. I'll ha...
- Matthew (29/110) Aug 21 2004 I've read it once, but want to take some time to think before I respond ...
- antiAlias (72/206) Aug 21 2004 Matthew;
- Matthew (29/110) Aug 21 2004 I've read it once, but want to take some time to think before I respond ...
- pragma (6/14) Aug 21 2004 I like the idea, but it represents quite a paradigm shift for D. Also, ...
- Matthew (16/96) Aug 21 2004 Ok. This is an issue that will run and run, I think. At least for a mont...
- pragma (40/58) Aug 21 2004 I'll take an oversimplified example from my D-Servlet Pages project.
Currently, D libraries are predominantly linked in a static fashion. I have a fairly substantial OO library that I'd really like to distribute as a dll/shared-lib, but there are apparently a number of issues that stop one doing so. I may have all of this completely wrong, and I'm really looking for guidance more that anything else: 1) each DLL has its own GC. Crossing DLL boundaries is a problem for memory allocations, especially for OO libraries (new doesn't work; some methods allocate within the DLL but the reference is held by the client instead; etc). 2) as I understand it, Exceptions do not cross DLL boundaries correctly One of the goals of providing a library is "ease of use" for the end user. I don't wish to make anyone jump through hoops just to use an OO class from a DLL, yet the library really needs to be shareable (there's potentially a very large number of small bound clients, so one would hope to avoid static-binding where possible). Can someone point me in the right direction? Or can we get some support from the compiler, if it's necessary? After all, a new language is a tough sell without good, easy to use libraries ... right?
Aug 08 2004
antiAlias wrote:Currently, D libraries are predominantly linked in a static fashion. I have a fairly substantial OO library that I'd really like to distribute as a dll/shared-lib, but there are apparently a number of issues that stop one doing so. I may have all of this completely wrong, and I'm really looking for guidance more that anything else: 1) each DLL has its own GC. Crossing DLL boundaries is a problem for memory allocations, especially for OO libraries (new doesn't work; some methods allocate within the DLL but the reference is held by the client instead; etc). 2) as I understand it, Exceptions do not cross DLL boundaries correctly One of the goals of providing a library is "ease of use" for the end user. I don't wish to make anyone jump through hoops just to use an OO class from a DLL, yet the library really needs to be shareable (there's potentially a very large number of small bound clients, so one would hope to avoid static-binding where possible). Can someone point me in the right direction? Or can we get some support from the compiler, if it's necessary? After all, a new language is a tough sell without good, easy to use libraries ... right?I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), but being rather difficult to use correctly and safely seems to keep most people from actually creating any. At the very least, strategies for how to overcome the problems mentioned above, should be collected (at the Wiki, I suppose). Maybe it's possible to make tools that can create the factories, stubs, etc automatically, but it sure would be nice to be able to use them the easy way. I would like to come with suggestions for how to 'fix' the DLL's, but I don't think I really have the know-how to even suggest. I *do* know though, that I would like to not have to use reference-counting. Lars Ivar Igesund
Aug 09 2004
"Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:cf73n3$b1l$2 digitaldaemon.com...antiAlias wrote:If someone could right a brief - 2 page? - treatise on the current state, and their perceived problems, I'd be happy to take a look at start to digest the problem.Currently, D libraries are predominantly linked in a static fashion. I have a fairly substantial OO library that I'd really like to distribute as a dll/shared-lib, but there are apparently a number of issues that stop one doing so. I may have all of this completely wrong, and I'm really looking for guidance more that anything else: 1) each DLL has its own GC. Crossing DLL boundaries is a problem for memory allocations, especially for OO libraries (new doesn't work; some methods allocate within the DLL but the reference is held by the client instead; etc). 2) as I understand it, Exceptions do not cross DLL boundaries correctly One of the goals of providing a library is "ease of use" for the end user. I don't wish to make anyone jump through hoops just to use an OO class from a DLL, yet the library really needs to be shareable (there's potentially a very large number of small bound clients, so one would hope to avoid static-binding where possible). Can someone point me in the right direction? Or can we get some support from the compiler, if it's necessary? After all, a new language is a tough sell without good, easy to use libraries ... right?I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), but being rather difficult to use correctly and safely seems to keep most people from actually creating any. At the very least, strategies for how to overcome the problems mentioned above, should be collected (at the Wiki, I suppose). Maybe it's possible to make tools that can create the factories, stubs, etc automatically, but it sure would be nice to be able to use them the easy way. I would like to come with suggestions for how to 'fix' the DLL's, but I don't think I really have the know-how to even suggest. I *do* know though, that I would like to not have to use reference-counting. Lars Ivar Igesund
Aug 08 2004
In article <cf73n3$b1l$2 digitaldaemon.com>, Lars Ivar Igesund says...antiAlias wrote:Honestly, I've already surmounted a huge number of issues regarding D DLL's in my time writing DSP. I've had to devise some workarounds including, but not limited to: object proxies, pointer lists and event messaging to signal dll unloads. I like your suggestion that solutions should be up on the Wiki, and I may publish my findings there. :) Like everyone in this thread, I want more from D with regard to how libraries are handled. Here's my $0.02: What is really missing is giving the DLL's a larger role in the eyes of the garbage collector. Having a separate GC on each library works well when having D inter-operate with different languages, but within a 100% D project it can become a hinderance. Without close and careful management of where a given D object "lives", releasing a DLL mid-process can be disasterous. However, this isn't any different from what we've already come to know about C and C++, its just something we would all rather live without (what with D already making strides to overcome other problems in C++). Two years ago, I put down development of my own GC-based runtime library for C++ I came across this issue and devised some solutions for it, but was unable to implement it as my GC engine had some impossible-to-debug quirks with it. For all that effort, I did learn some rather invaluable lessons about the impact a collector has on a language. Hooking a GC into another dll isn't that hard to do, as long as one is willing to take on the notion of D-platform-dependent libraries. Ultimately, I realized that the problem regarding Dll's and GC engines is easy provided you can answer one question: Does a given pointer represent a pointer to code on a given DLL, or to a valid root in a given DLL? From this we can deduce the rest of the information we need to do everything else dynamically. If a DLL has no vtables or delegates pointing to it's code, and no pointers elsewhere to any other roots within the DLL, then there are no dependencies on that DLL and it may be dismissed. This leads up to the notion that DLL's themselves may be managed by utilizing the gc. A DLL can be treated as a collectable object, provided that its root pointers and _entire code space_ are set as roots to be scanned by the hosting process's garbage collector. Such A DLL can be unloaded from the process in a manner analagous to collection of a typical object (i.e. lazy destruction and release of resources). The result is something that is almost totally transparent to the language, provided that phobos is given some additional support (outside of std.loader) for DLLs. Careful object management and prodding the GC should be enough to get a library to release/unload/close whenever needed. By constrast an explicit and immediate unload of a DLL requires far more plumbing and participation on behalf of the library developer and library user alike. Collectable DLL's, IMO are the way forward for D. - PragmaCurrently, D libraries are predominantly linked in a static fashion. I have a fairly substantial OO library that I'd really like to distribute as a dll/shared-lib, but there are apparently a number of issues that stop one doing so. I may have all of this completely wrong, and I'm really looking for guidance more that anything else: 1) each DLL has its own GC. Crossing DLL boundaries is a problem for memory allocations, especially for OO libraries (new doesn't work; some methods allocate within the DLL but the reference is held by the client instead; etc). 2) as I understand it, Exceptions do not cross DLL boundaries correctly One of the goals of providing a library is "ease of use" for the end user. I don't wish to make anyone jump through hoops just to use an OO class from a DLL, yet the library really needs to be shareable (there's potentially a very large number of small bound clients, so one would hope to avoid static-binding where possible). Can someone point me in the right direction? Or can we get some support from the compiler, if it's necessary? After all, a new language is a tough sell without good, easy to use libraries ... right?I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), but being rather difficult to use correctly and safely seems to keep most people from actually creating any. At the very least, strategies for how to overcome the problems mentioned above, should be collected (at the Wiki, I suppose). Maybe it's possible to make tools that can create the factories, stubs, etc automatically, but it sure would be nice to be able to use them the easy way. I would like to come with suggestions for how to 'fix' the DLL's, but I don't think I really have the know-how to even suggest. I *do* know though, that I would like to not have to use reference-counting. Lars Ivar Igesund
Aug 09 2004
What you suggest sounds really promising Eric, and it would certainly help tremendously with what I'm doing. So, what am I doing, specifically? Well, Mango has a clustering package, used for the caching, queuing, and execution of D classes across a LAN. Naturally, the classes passed around at runtime must be known at compile-time. Within a cluster, the server (storage) nodes get around this problem by maintaining such classes in serialized form only. That is, they deliberately avoid instantiating an instance (otherwise they'd need to be compiled with every single possible class that might be stored). The cluster-clients, on the other hand, do need to know about each class ~ since they will receive and operate upon concrete class instances. These classes must be known at compile time. For certain applications this is not a restriction of any kind. In fact, it may actually be viewed as security benefit. However, most software systems evolve rather dynamically, and rebooting an entire operational network to get some new class-instances configured into the cluster is just not practical. That's where DLL's (or shared libs) step in. In particular, the clustering package would benefit greatly if the mobile classes involved were packaged as discrete dll's. That way, it would be easy to ship them around the cluster too (as files), and they'd 'attach' to client nodes as appropriate. This is very similar in approach to how servlets are loaded dynamically into a running server (and reloaded when they are seen to change). The other factor involved in such an approach is this: these mobile classes often need to use resources outside of their own codebase (think Mango classes, or a database, or whatever). One does not want to bloat the mobile dll's with such artifacts ~ they should be bound when said dll is loaded instead. That is, the Mango library itself should be a dll. Being able to do this cleanly, elegantly, efficiently, and robustly is important. I think something needs to be done to bring D up-to-date in this respect. How about it? "pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in message news:cf80ak$m3v$1 digitaldaemon.com...In article <cf73n3$b1l$2 digitaldaemon.com>, Lars Ivar Igesund says...haveantiAlias wrote:Currently, D libraries are predominantly linked in a static fashion. Ionea fairly substantial OO library that I'd really like to distribute as a dll/shared-lib, but there are apparently a number of issues that stoplookingdoing so. I may have all of this completely wrong, and I'm reallymemoryfor guidance more that anything else: 1) each DLL has its own GC. Crossing DLL boundaries is a problem formethodsallocations, especially for OO libraries (new doesn't work; someinstead;allocate within the DLL but the reference is held by the clientuser. Ietc). 2) as I understand it, Exceptions do not cross DLL boundaries correctly One of the goals of providing a library is "ease of use" for the endfrom adon't wish to make anyone jump through hoops just to use an OO classaDLL, yet the library really needs to be shareable (there's potentiallydirection?very large number of small bound clients, so one would hope to avoid static-binding where possible). Can someone point me in the rightall,Or can we get some support from the compiler, if it's necessary? AfterDLL's inHonestly, I've already surmounted a huge number of issues regarding Da new language is a tough sell without good, easy to use libraries ... right?I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), but being rather difficult to use correctly and safely seems to keep most people from actually creating any. At the very least, strategies for how to overcome the problems mentioned above, should be collected (at the Wiki, I suppose). Maybe it's possible to make tools that can create the factories, stubs, etc automatically, but it sure would be nice to be able to use them the easy way. I would like to come with suggestions for how to 'fix' the DLL's, but I don't think I really have the know-how to even suggest. I *do* know though, that I would like to not have to use reference-counting. Lars Ivar Igesundmy time writing DSP. I've had to devise some workarounds including, butnotlimited to: object proxies, pointer lists and event messaging to signaldllunloads. I like your suggestion that solutions should be up on the Wiki,and Imay publish my findings there. :) Like everyone in this thread, I wantmorefrom D with regard to how libraries are handled. Here's my $0.02: What is really missing is giving the DLL's a larger role in the eyes ofthegarbage collector. Having a separate GC on each library works well whenhavingD inter-operate with different languages, but within a 100% D project itcanbecome a hinderance. Without close and careful management of where agiven Dobject "lives", releasing a DLL mid-process can be disasterous. However,thisisn't any different from what we've already come to know about C and C++,itsjust something we would all rather live without (what with D alreadymakingstrides to overcome other problems in C++). Two years ago, I put down development of my own GC-based runtime libraryfor C++I came across this issue and devised some solutions for it, but wasunable toimplement it as my GC engine had some impossible-to-debug quirks with it.Forall that effort, I did learn some rather invaluable lessons about theimpact acollector has on a language. Hooking a GC into another dll isn't that hard to do, as long as one iswillingto take on the notion of D-platform-dependent libraries. Ultimately, Irealizedthat the problem regarding Dll's and GC engines is easy provided you cananswerone question: Does a given pointer represent a pointer to code on a given DLL, or to avalidroot in a given DLL? From this we can deduce the rest of the information we need to doeverythingelse dynamically. If a DLL has no vtables or delegates pointing to it'scode,and no pointers elsewhere to any other roots within the DLL, then thereare nodependencies on that DLL and it may be dismissed. This leads up to thenotionthat DLL's themselves may be managed by utilizing the gc. A DLL can be treated as a collectable object, provided that its rootpointersand _entire code space_ are set as roots to be scanned by the hostingprocess'sgarbage collector. Such A DLL can be unloaded from the process in amanneranalagous to collection of a typical object (i.e. lazy destruction andreleaseof resources). The result is something that is almost totally transparent to thelanguage,provided that phobos is given some additional support (outside ofstd.loader)for DLLs. Careful object management and prodding the GC should be enoughto geta library to release/unload/close whenever needed. By constrast an explicit and immediate unload of a DLL requires far more plumbing and participation on behalf of the library developer and libraryuseralike. Collectable DLL's, IMO are the way forward for D. - Pragma
Aug 19 2004
Kris, ... cough ... splutter ... sorry. Mr Alias From your description of your requirements I would say that it's _possible_ that you can implement what you need by using interfaces, and being _very_ careful with your memory management, but I don't fancy your (or anyone else's) chances of making such an infrastructure simply, robustly and flexibly. For my money, I don't think D's got any kind of acceptable answer to this issue atm. Nomenclatural definition: I use the term "link unit" a lot. I'm sure you'll grok the full extent of the concept when I say that an exes and dynamic libs are link-units, and static libs are not. Another way to think of it is link units define a complete symbol name space. (For more on this and other fascinating issues, please feel free to preorder a copy of "Imperfect C++" from http://www.amazon.com/exec/obidos/tg/detail/-/0321228774/ <g>) I see four issues with DLLs and D. I'm interested to hear whether I've missed any and, especially, what ideas people have for solving these issues in a "Spirit of D" way (i.e. without all the clodhopping nonsense that is the Java/.NET infrastructure): 1. Sharing/managing GC - I think this is the most important in the short/medium term 2. Being able to talk _classes_ not just _interfaces_ between link units. We can get a long way with interfaces, methinks, once GC sharing is handled, but still it'd be nice to work with classes as well, if simply achievable. 3. Versioning, i.e. avoiding DLL Hell 4. Security. Is there something simple and efficient that nonetheless addresses those handled by the heaving leviathan that is .NET? Ancilary issues: 1. Serialisation as a part of the language?? (Germane) thoughts everyone? Cheers -- Matthew Wilson Author: "Imperfect C++", Addison-Wesley, 2004 (http://www.imperfectcplusplus.com) Contributing editor, C/C++ Users Journal (http://www.synesis.com.au/articles.html#columns) Director, Synesis Software (www.synesis.com.au) STLSoft moderator (http://www.stlsoft.org) "Youth ages, Immaturity is outgrown, Ignorance can be educated, drunkeness sobered. But stupid lasts forever", Aristophenes ----------------------------------------------------- "antiAlias" <fu bar.com> wrote in message news:cg3pmt$2q32$1 digitaldaemon.com...What you suggest sounds really promising Eric, and it would certainly help tremendously with what I'm doing. So, what am I doing, specifically? Well, Mango has a clustering package, used for the caching, queuing, and execution of D classes across a LAN. Naturally, the classes passed around at runtime must be known at compile-time. Within a cluster, the server (storage) nodes get around this problem by maintaining such classes in serialized form only. That is, they deliberately avoid instantiating an instance (otherwise they'd need to be compiled with every single possible class that might be stored). The cluster-clients, on the other hand, do need to know about each class ~ since they will receive and operate upon concrete class instances. These classes must be known at compile time. For certain applications this is not a restriction of any kind. In fact, it may actually be viewed as security benefit. However, most software systems evolve rather dynamically, and rebooting an entire operational network to get some new class-instances configured into the cluster is just not practical. That's where DLL's (or shared libs) step in. In particular, the clustering package would benefit greatly if the mobile classes involved were packaged as discrete dll's. That way, it would be easy to ship them around the cluster too (as files), and they'd 'attach' to client nodes as appropriate. This is very similar in approach to how servlets are loaded dynamically into a running server (and reloaded when they are seen to change). The other factor involved in such an approach is this: these mobile classes often need to use resources outside of their own codebase (think Mango classes, or a database, or whatever). One does not want to bloat the mobile dll's with such artifacts ~ they should be bound when said dll is loaded instead. That is, the Mango library itself should be a dll. Being able to do this cleanly, elegantly, efficiently, and robustly is important. I think something needs to be done to bring D up-to-date in this respect. How about it? "pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in message news:cf80ak$m3v$1 digitaldaemon.com...In article <cf73n3$b1l$2 digitaldaemon.com>, Lars Ivar Igesund says...haveantiAlias wrote:Currently, D libraries are predominantly linked in a static fashion. Ionea fairly substantial OO library that I'd really like to distribute as a dll/shared-lib, but there are apparently a number of issues that stoplookingdoing so. I may have all of this completely wrong, and I'm reallymemoryfor guidance more that anything else: 1) each DLL has its own GC. Crossing DLL boundaries is a problem formethodsallocations, especially for OO libraries (new doesn't work; someinstead;allocate within the DLL but the reference is held by the clientuser. Ietc). 2) as I understand it, Exceptions do not cross DLL boundaries correctly One of the goals of providing a library is "ease of use" for the endfrom adon't wish to make anyone jump through hoops just to use an OO classaDLL, yet the library really needs to be shareable (there's potentiallydirection?very large number of small bound clients, so one would hope to avoid static-binding where possible). Can someone point me in the rightall,Or can we get some support from the compiler, if it's necessary? AfterDLL's inHonestly, I've already surmounted a huge number of issues regarding Da new language is a tough sell without good, easy to use libraries ... right?I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), but being rather difficult to use correctly and safely seems to keep most people from actually creating any. At the very least, strategies for how to overcome the problems mentioned above, should be collected (at the Wiki, I suppose). Maybe it's possible to make tools that can create the factories, stubs, etc automatically, but it sure would be nice to be able to use them the easy way. I would like to come with suggestions for how to 'fix' the DLL's, but I don't think I really have the know-how to even suggest. I *do* know though, that I would like to not have to use reference-counting. Lars Ivar Igesundmy time writing DSP. I've had to devise some workarounds including, butnotlimited to: object proxies, pointer lists and event messaging to signaldllunloads. I like your suggestion that solutions should be up on the Wiki,and Imay publish my findings there. :) Like everyone in this thread, I wantmorefrom D with regard to how libraries are handled. Here's my $0.02: What is really missing is giving the DLL's a larger role in the eyes ofthegarbage collector. Having a separate GC on each library works well whenhavingD inter-operate with different languages, but within a 100% D project itcanbecome a hinderance. Without close and careful management of where agiven Dobject "lives", releasing a DLL mid-process can be disasterous. However,thisisn't any different from what we've already come to know about C and C++,itsjust something we would all rather live without (what with D alreadymakingstrides to overcome other problems in C++). Two years ago, I put down development of my own GC-based runtime libraryfor C++I came across this issue and devised some solutions for it, but wasunable toimplement it as my GC engine had some impossible-to-debug quirks with it.Forall that effort, I did learn some rather invaluable lessons about theimpact acollector has on a language. Hooking a GC into another dll isn't that hard to do, as long as one iswillingto take on the notion of D-platform-dependent libraries. Ultimately, Irealizedthat the problem regarding Dll's and GC engines is easy provided you cananswerone question: Does a given pointer represent a pointer to code on a given DLL, or to avalidroot in a given DLL? From this we can deduce the rest of the information we need to doeverythingelse dynamically. If a DLL has no vtables or delegates pointing to it'scode,and no pointers elsewhere to any other roots within the DLL, then thereare nodependencies on that DLL and it may be dismissed. This leads up to thenotionthat DLL's themselves may be managed by utilizing the gc. A DLL can be treated as a collectable object, provided that its rootpointersand _entire code space_ are set as roots to be scanned by the hostingprocess'sgarbage collector. Such A DLL can be unloaded from the process in amanneranalagous to collection of a typical object (i.e. lazy destruction andreleaseof resources). The result is something that is almost totally transparent to thelanguage,provided that phobos is given some additional support (outside ofstd.loader)for DLLs. Careful object management and prodding the GC should be enoughto geta library to release/unload/close whenever needed. By constrast an explicit and immediate unload of a DLL requires far more plumbing and participation on behalf of the library developer and libraryuseralike. Collectable DLL's, IMO are the way forward for D. - Pragma
Aug 19 2004
Eric describes (below) sounds really attractive. Other than that, what about the exception-boundary issue? "Matthew" <admin.hat stlsoft.dot.org> wrote in message news:cg3ul4$2sq0$1 digitaldaemon.com...Kris, ... cough ... splutter ... sorry. Mr Alias From your description of your requirements I would say that it's_possible_ that you can implement what you need byusing interfaces, and being _very_ careful with your memory management,but I don't fancy your (or anyone else's)chances of making such an infrastructure simply, robustly and flexibly.For my money, I don't think D's got any kind ofacceptable answer to this issue atm. Nomenclatural definition: I use the term "link unit" a lot. I'm sureyou'll grok the full extent of the concept when Isay that an exes and dynamic libs are link-units, and static libs are not.Another way to think of it is link unitsdefine a complete symbol name space. (For more on this and otherfascinating issues, please feel free to preorder a copyof "Imperfect C++" fromhttp://www.amazon.com/exec/obidos/tg/detail/-/0321228774/ <g>)I see four issues with DLLs and D. I'm interested to hear whether I'vemissed any and, especially, what ideas peoplehave for solving these issues in a "Spirit of D" way (i.e. without all theclodhopping nonsense that is the Java/.NETinfrastructure): 1. Sharing/managing GC - I think this is the most important in theshort/medium term2. Being able to talk _classes_ not just _interfaces_ between link units.We can get a long way with interfaces,methinks, once GC sharing is handled, but still it'd be nice to work withclasses as well, if simply achievable.3. Versioning, i.e. avoiding DLL Hell 4. Security. Is there something simple and efficient that nonethelessaddresses those handled by the heaving leviathanthat is .NET? Ancilary issues: 1. Serialisation as a part of the language?? (Germane) thoughts everyone? Cheers -- Matthew Wilson Author: "Imperfect C++", Addison-Wesley, 2004 (http://www.imperfectcplusplus.com) Contributing editor, C/C++ Users Journal (http://www.synesis.com.au/articles.html#columns) Director, Synesis Software (www.synesis.com.au) STLSoft moderator (http://www.stlsoft.org) "Youth ages, Immaturity is outgrown, Ignorance can be educated, drunkenesssobered. But stupid lasts forever",Aristophenes ----------------------------------------------------- "antiAlias" <fu bar.com> wrote in messagenews:cg3pmt$2q32$1 digitaldaemon.com...helpWhat you suggest sounds really promising Eric, and it would certainlydeliberatelytremendously with what I'm doing. So, what am I doing, specifically? Well, Mango has a clustering package, used for the caching, queuing, and execution of D classes across a LAN. Naturally, the classes passed around at runtime must be known at compile-time. Within a cluster, the server (storage) nodes get around this problem by maintaining such classes in serialized form only. That is, theywithavoid instantiating an instance (otherwise they'd need to be compiled~every single possible class that might be stored). The cluster-clients, on the other hand, do need to know about each classnotsince they will receive and operate upon concrete class instances. These classes must be known at compile time. For certain applications this issecuritya restriction of any kind. In fact, it may actually be viewed asanbenefit. However, most software systems evolve rather dynamically, and rebootingintoentire operational network to get some new class-instances configuredclusteringthe cluster is just not practical. That's where DLL's (or shared libs) step in. In particular, thepackagedpackage would benefit greatly if the mobile classes involved wereappropriate.as discrete dll's. That way, it would be easy to ship them around the cluster too (as files), and they'd 'attach' to client nodes asintoThis is very similar in approach to how servlets are loaded dynamicallyclassesa running server (and reloaded when they are seen to change). The other factor involved in such an approach is this: these mobilemobileoften need to use resources outside of their own codebase (think Mango classes, or a database, or whatever). One does not want to bloat thethisdll's with such artifacts ~ they should be bound when said dll is loaded instead. That is, the Mango library itself should be a dll. Being able to do this cleanly, elegantly, efficiently, and robustly is important. I think something needs to be done to bring D up-to-date ininrespect. How about it? "pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrotefashion. Imessage news:cf80ak$m3v$1 digitaldaemon.com...In article <cf73n3$b1l$2 digitaldaemon.com>, Lars Ivar Igesund says...antiAlias wrote:Currently, D libraries are predominantly linked in a staticas ahavea fairly substantial OO library that I'd really like to distributestopdll/shared-lib, but there are apparently a number of issues thatforonelookingdoing so. I may have all of this completely wrong, and I'm reallyfor guidance more that anything else: 1) each DLL has its own GC. Crossing DLL boundaries is a problemcorrectlymemorymethodsallocations, especially for OO libraries (new doesn't work; someinstead;allocate within the DLL but the reference is held by the clientetc). 2) as I understand it, Exceptions do not cross DLL boundariesendOne of the goals of providing a library is "ease of use" for theclassuser. Idon't wish to make anyone jump through hoops just to use an OOpotentiallyfrom aDLL, yet the library really needs to be shareable (there'savoidavery large number of small bound clients, so one would hope toAfterdirection?static-binding where possible). Can someone point me in the rightOr can we get some support from the compiler, if it's necessary?...all,a new language is a tough sell without good, easy to use librariesbeingright?I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), butpeoplerather difficult to use correctly and safely seems to keep mostmentionedfrom actually creating any. At the very least, strategies for how to overcome the problemspossibleabove, should be collected (at the Wiki, I suppose). Maybe it'sautomatically,to make tools that can create the factories, stubs, etcIbut it sure would be nice to be able to use them the easy way. I would like to come with suggestions for how to 'fix' the DLL's, butbutDLL's indon't think I really have the know-how to even suggest. I *do* know though, that I would like to not have to use reference-counting. Lars Ivar IgesundHonestly, I've already surmounted a huge number of issues regarding Dmy time writing DSP. I've had to devise some workarounds including,signalnotlimited to: object proxies, pointer lists and event messaging toWiki,dllunloads. I like your suggestion that solutions should be up on thewantand Imay publish my findings there. :) Like everyone in this thread, Iofmorefrom D with regard to how libraries are handled. Here's my $0.02: What is really missing is giving the DLL's a larger role in the eyeswhenthegarbage collector. Having a separate GC on each library works wellithavingD inter-operate with different languages, but within a 100% D projectHowever,canbecome a hinderance. Without close and careful management of where agiven Dobject "lives", releasing a DLL mid-process can be disasterous.C++,thisisn't any different from what we've already come to know about C andlibraryitsjust something we would all rather live without (what with D alreadymakingstrides to overcome other problems in C++). Two years ago, I put down development of my own GC-based runtimeit.for C++I came across this issue and devised some solutions for it, but wasunable toimplement it as my GC engine had some impossible-to-debug quirks withIForall that effort, I did learn some rather invaluable lessons about theimpact acollector has on a language. Hooking a GC into another dll isn't that hard to do, as long as one iswillingto take on the notion of D-platform-dependent libraries. Ultimately,canrealizedthat the problem regarding Dll's and GC engines is easy provided youaanswerone question: Does a given pointer represent a pointer to code on a given DLL, or toit'svalidroot in a given DLL? From this we can deduce the rest of the information we need to doeverythingelse dynamically. If a DLL has no vtables or delegates pointing totherecode,and no pointers elsewhere to any other roots within the DLL, thentheare nodependencies on that DLL and it may be dismissed. This leads up toenoughnotionthat DLL's themselves may be managed by utilizing the gc. A DLL can be treated as a collectable object, provided that its rootpointersand _entire code space_ are set as roots to be scanned by the hostingprocess'sgarbage collector. Such A DLL can be unloaded from the process in amanneranalagous to collection of a typical object (i.e. lazy destruction andreleaseof resources). The result is something that is almost totally transparent to thelanguage,provided that phobos is given some additional support (outside ofstd.loader)for DLLs. Careful object management and prodding the GC should bemoreto geta library to release/unload/close whenever needed. By constrast an explicit and immediate unload of a DLL requires farlibraryplumbing and participation on behalf of the library developer anduseralike. Collectable DLL's, IMO are the way forward for D. - Pragma
Aug 19 2004
"antiAlias" <fu bar.com> wrote in message news:cg408a$2tge$1 digitaldaemon.com...Eric describes (below) sounds really attractive.It sounds promising. I'd like to hear more fine details, though. I'd also like to hear if his ideas would require changes to std.loader (as I'm itching for an excuse to rewrite that stillborn obscenity). I'd also like to hear Walter's opinions on the matter. I think this issue is of sufficient import to be a 1.0 prerequesite, don't you?Other than that, what about the exception-boundary issue?Well, D's going to have an ABI, and since all exceptions are going to co-exist memorywise (when the GC's linearised/homogenised), what's the prob?"Matthew" <admin.hat stlsoft.dot.org> wrote in message news:cg3ul4$2sq0$1 digitaldaemon.com...Kris, ... cough ... splutter ... sorry. Mr Alias From your description of your requirements I would say that it's_possible_ that you can implement what you need byusing interfaces, and being _very_ careful with your memory management,but I don't fancy your (or anyone else's)chances of making such an infrastructure simply, robustly and flexibly.For my money, I don't think D's got any kind ofacceptable answer to this issue atm. Nomenclatural definition: I use the term "link unit" a lot. I'm sureyou'll grok the full extent of the concept when Isay that an exes and dynamic libs are link-units, and static libs are not.Another way to think of it is link unitsdefine a complete symbol name space. (For more on this and otherfascinating issues, please feel free to preorder a copyof "Imperfect C++" fromhttp://www.amazon.com/exec/obidos/tg/detail/-/0321228774/ <g>)I see four issues with DLLs and D. I'm interested to hear whether I'vemissed any and, especially, what ideas peoplehave for solving these issues in a "Spirit of D" way (i.e. without all theclodhopping nonsense that is the Java/.NETinfrastructure): 1. Sharing/managing GC - I think this is the most important in theshort/medium term2. Being able to talk _classes_ not just _interfaces_ between link units.We can get a long way with interfaces,methinks, once GC sharing is handled, but still it'd be nice to work withclasses as well, if simply achievable.3. Versioning, i.e. avoiding DLL Hell 4. Security. Is there something simple and efficient that nonethelessaddresses those handled by the heaving leviathanthat is .NET? Ancilary issues: 1. Serialisation as a part of the language?? (Germane) thoughts everyone? Cheers -- Matthew Wilson Author: "Imperfect C++", Addison-Wesley, 2004 (http://www.imperfectcplusplus.com) Contributing editor, C/C++ Users Journal (http://www.synesis.com.au/articles.html#columns) Director, Synesis Software (www.synesis.com.au) STLSoft moderator (http://www.stlsoft.org) "Youth ages, Immaturity is outgrown, Ignorance can be educated, drunkenesssobered. But stupid lasts forever",Aristophenes ----------------------------------------------------- "antiAlias" <fu bar.com> wrote in messagenews:cg3pmt$2q32$1 digitaldaemon.com...helpWhat you suggest sounds really promising Eric, and it would certainlydeliberatelytremendously with what I'm doing. So, what am I doing, specifically? Well, Mango has a clustering package, used for the caching, queuing, and execution of D classes across a LAN. Naturally, the classes passed around at runtime must be known at compile-time. Within a cluster, the server (storage) nodes get around this problem by maintaining such classes in serialized form only. That is, theywithavoid instantiating an instance (otherwise they'd need to be compiled~every single possible class that might be stored). The cluster-clients, on the other hand, do need to know about each classnotsince they will receive and operate upon concrete class instances. These classes must be known at compile time. For certain applications this issecuritya restriction of any kind. In fact, it may actually be viewed asanbenefit. However, most software systems evolve rather dynamically, and rebootingintoentire operational network to get some new class-instances configuredclusteringthe cluster is just not practical. That's where DLL's (or shared libs) step in. In particular, thepackagedpackage would benefit greatly if the mobile classes involved wereappropriate.as discrete dll's. That way, it would be easy to ship them around the cluster too (as files), and they'd 'attach' to client nodes asintoThis is very similar in approach to how servlets are loaded dynamicallyclassesa running server (and reloaded when they are seen to change). The other factor involved in such an approach is this: these mobilemobileoften need to use resources outside of their own codebase (think Mango classes, or a database, or whatever). One does not want to bloat thethisdll's with such artifacts ~ they should be bound when said dll is loaded instead. That is, the Mango library itself should be a dll. Being able to do this cleanly, elegantly, efficiently, and robustly is important. I think something needs to be done to bring D up-to-date ininrespect. How about it? "pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrotefashion. Imessage news:cf80ak$m3v$1 digitaldaemon.com...In article <cf73n3$b1l$2 digitaldaemon.com>, Lars Ivar Igesund says...antiAlias wrote:Currently, D libraries are predominantly linked in a staticas ahavea fairly substantial OO library that I'd really like to distributestopdll/shared-lib, but there are apparently a number of issues thatforonelookingdoing so. I may have all of this completely wrong, and I'm reallyfor guidance more that anything else: 1) each DLL has its own GC. Crossing DLL boundaries is a problemcorrectlymemorymethodsallocations, especially for OO libraries (new doesn't work; someinstead;allocate within the DLL but the reference is held by the clientetc). 2) as I understand it, Exceptions do not cross DLL boundariesendOne of the goals of providing a library is "ease of use" for theclassuser. Idon't wish to make anyone jump through hoops just to use an OOpotentiallyfrom aDLL, yet the library really needs to be shareable (there'savoidavery large number of small bound clients, so one would hope toAfterdirection?static-binding where possible). Can someone point me in the rightOr can we get some support from the compiler, if it's necessary?...all,a new language is a tough sell without good, easy to use librariesbeingright?I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), butpeoplerather difficult to use correctly and safely seems to keep mostmentionedfrom actually creating any. At the very least, strategies for how to overcome the problemspossibleabove, should be collected (at the Wiki, I suppose). Maybe it'sautomatically,to make tools that can create the factories, stubs, etcIbut it sure would be nice to be able to use them the easy way. I would like to come with suggestions for how to 'fix' the DLL's, butbutDLL's indon't think I really have the know-how to even suggest. I *do* know though, that I would like to not have to use reference-counting. Lars Ivar IgesundHonestly, I've already surmounted a huge number of issues regarding Dmy time writing DSP. I've had to devise some workarounds including,signalnotlimited to: object proxies, pointer lists and event messaging toWiki,dllunloads. I like your suggestion that solutions should be up on thewantand Imay publish my findings there. :) Like everyone in this thread, Iofmorefrom D with regard to how libraries are handled. Here's my $0.02: What is really missing is giving the DLL's a larger role in the eyeswhenthegarbage collector. Having a separate GC on each library works wellithavingD inter-operate with different languages, but within a 100% D projectHowever,canbecome a hinderance. Without close and careful management of where agiven Dobject "lives", releasing a DLL mid-process can be disasterous.C++,thisisn't any different from what we've already come to know about C andlibraryitsjust something we would all rather live without (what with D alreadymakingstrides to overcome other problems in C++). Two years ago, I put down development of my own GC-based runtimeit.for C++I came across this issue and devised some solutions for it, but wasunable toimplement it as my GC engine had some impossible-to-debug quirks withIForall that effort, I did learn some rather invaluable lessons about theimpact acollector has on a language. Hooking a GC into another dll isn't that hard to do, as long as one iswillingto take on the notion of D-platform-dependent libraries. Ultimately,canrealizedthat the problem regarding Dll's and GC engines is easy provided youaanswerone question: Does a given pointer represent a pointer to code on a given DLL, or toit'svalidroot in a given DLL? From this we can deduce the rest of the information we need to doeverythingelse dynamically. If a DLL has no vtables or delegates pointing totherecode,and no pointers elsewhere to any other roots within the DLL, thentheare nodependencies on that DLL and it may be dismissed. This leads up toenoughnotionthat DLL's themselves may be managed by utilizing the gc. A DLL can be treated as a collectable object, provided that its rootpointersand _entire code space_ are set as roots to be scanned by the hostingprocess'sgarbage collector. Such A DLL can be unloaded from the process in amanneranalagous to collection of a typical object (i.e. lazy destruction andreleaseof resources). The result is something that is almost totally transparent to thelanguage,provided that phobos is given some additional support (outside ofstd.loader)for DLLs. Careful object management and prodding the GC should bemoreto geta library to release/unload/close whenever needed. By constrast an explicit and immediate unload of a DLL requires farlibraryplumbing and participation on behalf of the library developer anduseralike. Collectable DLL's, IMO are the way forward for D. - Pragma
Aug 19 2004
FYI: this is a long post, please read. Thank you. :) In article <cg41tm$2u6a$1 digitaldaemon.com>, Matthew says..."antiAlias" <fu bar.com> wrote in message news:cg408a$2tge$1 digitaldaemon.com...I'll work on a more detailed treatment as soon as time permits. I'll have to first go back through my old source/notes and make sure that there's nothing that I've managed to miss. One thing I will say though: No matter how many times I revisit the problem, the businss of explicitly unloading a library at runtime has ugly consequences for raising our expectations of how this should be handled. I don't think the problem can be completely solved for in-memory objects, without resorting to proxies and/or notification lists.Eric describes (below) sounds really attractive.It sounds promising. I'd like to hear more fine details, though.I'd also like to hear if his ideas would require changes to std.loader (as I'm itching for an excuse to rewrite that stillborn obscenity).I think my first reaction to reading that source was: "This compiled?" (j/k) I wouldn't anticipate need to change std.loader drastically. Outside of that, I'd love to see the thread-local storage bits broken out into another library or as an extension to std.thread. ;) One question though: is all the extra ref-counting code needed for linux libraries, or does it supply some extra value to both Win32 and Linux environments?I'd also like to hear Walter's opinions on the matter. I think this issue is of sufficient import to be a 1.0 prerequesite, don't you?I couldn't agree more. I too, would like to hear what direction things will take with respect to dll's.With respect to Kris' concern about handling exceptions, its really obnoxious how an uncaught exception within a library kills your app. Aside from making all of my libraries behave like class-factories, I've taken to using methods that do this:Other than that, what about the exception-boundary issue?Well, D's going to have an ABI, and since all exceptions are going to co-exist memorywise (when the GC's linearised/homogenised), what's the prob?int someMethod(int foo){ /* impl */ }..to be called and exported by a dll stub function:export(Windows) Exception someMethod(int foo,out _returnval){ Exception _exception; try{ _returnval = someMethod(foo); } catch(Exception e){ _exception = e; } return(_exception); }You can use a similar stub on the calling side that wraps the function pointer that you grab from the library. Meanwhile (on a slightly OT note), I'm still working on some of the more tricky aspects of dll's in D. In particular, I've tracked one really nasty bug down to (what looks like) the digitalmars-C backend:// deceptively simple example. import std.c.windows.windows; void main(){ HMODULE mod = LoadLibrary("mydll.dll"); printf("freeing..."); FreeLibrary(mod); printf("You will never see this print.\n"); }(Matthew, Kris, have you had this problem on your Windows machines? I've done this on two separate boxes with the same result. If you two or anyone else can confirm this, I'll go ahead and post it to the bugs NG) Basically, stdout and stdin are "automagically" set to EOF (or some similar state) after the call to FreeLibrary(): nothing goes in and nothing comes out. Everything else runs fine, no exceptions are thrown, and GetLastError() faithfully returns 0. I've been able to recreate the above in DMC, with a 100% C-built Dll using the same .def file as the mydll sample. The results are also the same when calling that dll from a host program written in MSVC6, DMD and DMC. Unless I'm horribly mistaken on how to do compose dll's using Digitalmars' technology, this is what you get the instant you unload any DMC/DMD built dll. The problem seems to only manifest when a proper DllMain() method is exported from the library. If none is provided, or if the given implementation can be optimized away, the error does not ocurr. This caused me hours upon hours of anguish trying to figure out why in my DSP/Mango server kept quietly halting on me: it was waiting for console input to terminate, but Mango's Stdin throws on EOF. :( - Pragma
Aug 20 2004
I've read it once, but want to take some time to think before I respond to some of the points. Let me pose my question in a more direct manner: AFAICS, one of the biggest problems is the ability to be able to use DLLs with D in *all* of the following guises: 1. D exe, C dll. Communication by plain C-API function calls. All resources returned whence they came. 2. C exe, D dll. Communication via extern(C) calls and/or interfaces with well-known vtable layout (e.g. COM). All resources returned whence they came 3. D exe, D dll, Communication via extern(C) calls and/or interfaces with well-known vtable layout (e.g. COM). All resources returned whence they came 4. D exe, D dll, Communication via extern(C) calls and/or interfaces with well-known vtable layout (e.g. COM). Memory allocated hither and used safely thither 5. D exe, D dll, Communication via extern(C) calls and/or extern(D) calls and/or interfaces with well-known vtable layout (e.g. COM). Memory allocated hither and used safely thither 6. D exe, D dll, Communication via 5. + classes. (Not sure of these details.) Note, for each of the above, you can permute by replacing exe with D client code inside a D dll in any of cases 2-6! Since D has, putatively at least, an ABI, all 6 (or 11) of these should, in principle be realisable. Further, commercially speaking, D *must* provide all of these, to not be abandoned by developers more influenced by deadline and pragmatism than idealism and performance - in other words, most of them. To my mind, we have two choices. One option is that the GC and supporting infrastructure is *always* in some DCore.dll - i.e. there're no more statically linked programs - in the same vein as .NET. The other option is that we come up with a mechanism whereby each link-unit is able to detect whether the process in which it is loaded already has a GC and, if so, links to that, otherwise starting its own. The complication to this is that if the first such link-unit is not the process' exe, we have the issue whereby the GC might be prematurely unloaded while other link-units are still depending on it. This could, hopefully(!), be resolved be having dependent link-units hold an independent dynamic-load reference on the GC's owning DLL. Thoughts? Walter, I'd be very interested in your thoughts on this, both on my comments on the need for this commercially, and also on possible implementation mechanisms. "pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in message news:cg5184$c7u$1 digitaldaemon.com...FYI: this is a long post, please read. Thank you. :) In article <cg41tm$2u6a$1 digitaldaemon.com>, Matthew says..."antiAlias" <fu bar.com> wrote in message news:cg408a$2tge$1 digitaldaemon.com...I'll work on a more detailed treatment as soon as time permits. I'll have to first go back through my old source/notes and make sure that there's nothing that I've managed to miss. One thing I will say though: No matter how many times I revisit the problem, the businss of explicitly unloading a library at runtime has ugly consequences for raising our expectations of how this should be handled. I don't think the problem can be completely solved for in-memory objects, without resorting to proxies and/or notification lists.Eric describes (below) sounds really attractive.It sounds promising. I'd like to hear more fine details, though.I'd also like to hear if his ideas would require changes to std.loader (as I'm itching for an excuse to rewrite that stillborn obscenity).I think my first reaction to reading that source was: "This compiled?" (j/k) I wouldn't anticipate need to change std.loader drastically. Outside of that, I'd love to see the thread-local storage bits broken out into another library or as an extension to std.thread. ;) One question though: is all the extra ref-counting code needed for linux libraries, or does it supply some extra value to both Win32 and Linux environments?I'd also like to hear Walter's opinions on the matter. I think this issue is of sufficient import to be a 1.0 prerequesite, don't you?I couldn't agree more. I too, would like to hear what direction things will take with respect to dll's.With respect to Kris' concern about handling exceptions, its really obnoxious how an uncaught exception within a library kills your app. Aside from making all of my libraries behave like class-factories, I've taken to using methods that do this:Other than that, what about the exception-boundary issue?Well, D's going to have an ABI, and since all exceptions are going to co-exist memorywise (when the GC's linearised/homogenised), what's the prob?int someMethod(int foo){ /* impl */ }..to be called and exported by a dll stub function:export(Windows) Exception someMethod(int foo,out _returnval){ Exception _exception; try{ _returnval = someMethod(foo); } catch(Exception e){ _exception = e; } return(_exception); }You can use a similar stub on the calling side that wraps the function pointer that you grab from the library. Meanwhile (on a slightly OT note), I'm still working on some of the more tricky aspects of dll's in D. In particular, I've tracked one really nasty bug down to (what looks like) the digitalmars-C backend:// deceptively simple example. import std.c.windows.windows; void main(){ HMODULE mod = LoadLibrary("mydll.dll"); printf("freeing..."); FreeLibrary(mod); printf("You will never see this print.\n"); }(Matthew, Kris, have you had this problem on your Windows machines? I've done this on two separate boxes with the same result. If you two or anyone else can confirm this, I'll go ahead and post it to the bugs NG) Basically, stdout and stdin are "automagically" set to EOF (or some similar state) after the call to FreeLibrary(): nothing goes in and nothing comes out. Everything else runs fine, no exceptions are thrown, and GetLastError() faithfully returns 0. I've been able to recreate the above in DMC, with a 100% C-built Dll using the same .def file as the mydll sample. The results are also the same when calling that dll from a host program written in MSVC6, DMD and DMC. Unless I'm horribly mistaken on how to do compose dll's using Digitalmars' technology, this is what you get the instant you unload any DMC/DMD built dll. The problem seems to only manifest when a proper DllMain() method is exported from the library. If none is provided, or if the given implementation can be optimized away, the error does not ocurr. This caused me hours upon hours of anguish trying to figure out why in my DSP/Mango server kept quietly halting on me: it was waiting for console input to terminate, but Mango's Stdin throws on EOF. :( - Pragma
Aug 21 2004
Matthew; As far as the GC is concerned, it would be wonderful to stuff that into a DLL ... that would solve a major problem right off the bat. Putting Phobos in a DLL would be a good idea also (no duplication of code across DLL instances). If subsequent DLL's were loaded as collectable entities (wrapped by a class; or perhaps /as/ a class) then the GC could handle all the murky ref-counting in its own inimitable fashion (invoking the destructor when the DLL is no longer referenced). That would eliminate another sticky wicket; as Eric pointed out. Those two get my immediate support; they would help tremendously with both Mango clustering and with the servlet-engine. As to how one gains access to a class within the DLL ... I'd be happy with a simple and convenient means of accessing a factory method from the DLL, and going from there. Of course, what you are describing would be infinitely superior; but I'd be happy to wait for it if the primary issues were taken care of (shareable GC; DLLs as collectible entities). "Matthew" <admin.hat stlsoft.dot.org> wrote in message news:cg8kuk$2il8$1 digitaldaemon.com...I've read it once, but want to take some time to think before I respond tosome of the points.Let me pose my question in a more direct manner: AFAICS, one of the biggest problems is the ability to be able to use DLLswith D in *all* of the following guises:1. D exe, C dll. Communication by plain C-API function calls. Allresources returned whence they came.2. C exe, D dll. Communication via extern(C) calls and/or interfaces withwell-known vtable layout (e.g. COM). Allresources returned whence they came 3. D exe, D dll, Communication via extern(C) calls and/or interfaces withwell-known vtable layout (e.g. COM). Allresources returned whence they came 4. D exe, D dll, Communication via extern(C) calls and/or interfaces withwell-known vtable layout (e.g. COM). Memoryallocated hither and used safely thither 5. D exe, D dll, Communication via extern(C) calls and/or extern(D) callsand/or interfaces with well-known vtablelayout (e.g. COM). Memory allocated hither and used safely thither 6. D exe, D dll, Communication via 5. + classes. (Not sure of thesedetails.)Note, for each of the above, you can permute by replacing exe with Dclient code inside a D dll in any of cases 2-6!Since D has, putatively at least, an ABI, all 6 (or 11) of these should,in principle be realisable. Further,commercially speaking, D *must* provide all of these, to not be abandonedby developers more influenced by deadline andpragmatism than idealism and performance - in other words, most of them. To my mind, we have two choices. One option is that the GC and supportinginfrastructure is *always* in some DCore.dll -i.e. there're no more statically linked programs - in the same vein as.NET. The other option is that we come up with amechanism whereby each link-unit is able to detect whether the process inwhich it is loaded already has a GC and, ifso, links to that, otherwise starting its own. The complication to this isthat if the first such link-unit is not theprocess' exe, we have the issue whereby the GC might be prematurelyunloaded while other link-units are still dependingon it. This could, hopefully(!), be resolved be having dependentlink-units hold an independent dynamic-load referenceon the GC's owning DLL. Thoughts? Walter, I'd be very interested in your thoughts on this, both on mycomments on the need for this commercially, and alsoon possible implementation mechanisms. "pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrotein messagenews:cg5184$c7u$1 digitaldaemon.com...news:cg408a$2tge$1 digitaldaemon.com...FYI: this is a long post, please read. Thank you. :) In article <cg41tm$2u6a$1 digitaldaemon.com>, Matthew says..."antiAlias" <fu bar.com> wrote in messageit, whathave toI'll work on a more detailed treatment as soon as time permits. I'llEric describes (below) sounds really attractive.It sounds promising. I'd like to hear more fine details, though.nothingfirst go back through my old source/notes and make sure that there'sproblem, thethat I've managed to miss. One thing I will say though: No matter how many times I revisit theconsequencesbusinss of explicitly unloading a library at runtime has uglyregardless of how the GC is hooked. Also, I blame languages like Javathink thefor raising our expectations of how this should be handled. I don'tresorting toproblem can be completely solved for in-memory objects, without(as I'm itching for an excuse to rewrite thatproxies and/or notification lists.I'd also like to hear if his ideas would require changes to std.loader(j/k)stillborn obscenity).I think my first reaction to reading that source was: "This compiled?"that,I wouldn't anticipate need to change std.loader drastically. Outside oflibrary orI'd love to see the thread-local storage bits broken out into anotherissue is of sufficient import to be a 1.0as an extension to std.thread. ;) One question though: is all the extra ref-counting code needed for linux libraries, or does it supply some extra value to both Win32 and Linux environments?I'd also like to hear Walter's opinions on the matter. I think thiswillprerequesite, don't you?I couldn't agree more. I too, would like to hear what direction thingsco-exist memorywise (when the GC'stake with respect to dll's.Other than that, what about the exception-boundary issue?Well, D's going to have an ABI, and since all exceptions are going toobnoxiouslinearised/homogenised), what's the prob?With respect to Kris' concern about handling exceptions, its reallymakinghow an uncaught exception within a library kills your app. Aside frommethodsall of my libraries behave like class-factories, I've taken to usingpointerthat do this:int someMethod(int foo){ /* impl */ }..to be called and exported by a dll stub function:export(Windows) Exception someMethod(int foo,out _returnval){ Exception _exception; try{ _returnval = someMethod(foo); } catch(Exception e){ _exception = e; } return(_exception); }You can use a similar stub on the calling side that wraps the functiontrickythat you grab from the library. Meanwhile (on a slightly OT note), I'm still working on some of the moredown toaspects of dll's in D. In particular, I've tracked one really nasty bugI've done(what looks like) the digitalmars-C backend:// deceptively simple example. import std.c.windows.windows; void main(){ HMODULE mod = LoadLibrary("mydll.dll"); printf("freeing..."); FreeLibrary(mod); printf("You will never see this print.\n"); }(Matthew, Kris, have you had this problem on your Windows machines?else canthis on two separate boxes with the same result. If you two or anyonesimilarconfirm this, I'll go ahead and post it to the bugs NG) Basically, stdout and stdin are "automagically" set to EOF (or somecomes out.state) after the call to FreeLibrary(): nothing goes in and nothingusing theEverything else runs fine, no exceptions are thrown, and GetLastError() faithfully returns 0. I've been able to recreate the above in DMC, with a 100% C-built Dllcallingsame .def file as the mydll sample. The results are also the same whenhorriblythat dll from a host program written in MSVC6, DMD and DMC. Unless I'mis whatmistaken on how to do compose dll's using Digitalmars' technology, thisexportedyou get the instant you unload any DMC/DMD built dll. The problem seems to only manifest when a proper DllMain() method iscan befrom the library. If none is provided, or if the given implementationmyoptimized away, the error does not ocurr. This caused me hours upon hours of anguish trying to figure out why ininput toDSP/Mango server kept quietly halting on me: it was waiting for consoleterminate, but Mango's Stdin throws on EOF. :( - Pragma
Aug 21 2004
I've read it once, but want to take some time to think before I respond to some of the points. Let me pose my question in a more direct manner: AFAICS, one of the biggest problems is the ability to be able to use DLLs with D in *all* of the following guises: 1. D exe, C dll. Communication by plain C-API function calls. All resources returned whence they came. 2. C exe, D dll. Communication via extern(C) calls and/or interfaces with well-known vtable layout (e.g. COM). All resources returned whence they came 3. D exe, D dll, Communication via extern(C) calls and/or interfaces with well-known vtable layout (e.g. COM). All resources returned whence they came 4. D exe, D dll, Communication via extern(C) calls and/or interfaces with well-known vtable layout (e.g. COM). Memory allocated hither and used safely thither 5. D exe, D dll, Communication via extern(C) calls and/or extern(D) calls and/or interfaces with well-known vtable layout (e.g. COM). Memory allocated hither and used safely thither 6. D exe, D dll, Communication via 5. + classes. (Not sure of these details.) Note, for each of the above, you can permute by replacing exe with D client code inside a D dll in any of cases 2-6! Since D has, putatively at least, an ABI, all 6 (or 11) of these should, in principle be realisable. Further, commercially speaking, D *must* provide all of these, to not be abandoned by developers more influenced by deadline and pragmatism than idealism and performance - in other words, most of them. To my mind, we have two choices. One option is that the GC and supporting infrastructure is *always* in some DCore.dll - i.e. there're no more statically linked programs - in the same vein as .NET. The other option is that we come up with a mechanism whereby each link-unit is able to detect whether the process in which it is loaded already has a GC and, if so, links to that, otherwise starting its own. The complication to this is that if the first such link-unit is not the process' exe, we have the issue whereby the GC might be prematurely unloaded while other link-units are still depending on it. This could, hopefully(!), be resolved be having dependent link-units hold an independent dynamic-load reference on the GC's owning DLL. Thoughts? Walter, I'd be very interested in your thoughts on this, both on my comments on the need for this commercially, and also on possible implementation mechanisms. "pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in message news:cg5184$c7u$1 digitaldaemon.com...FYI: this is a long post, please read. Thank you. :) In article <cg41tm$2u6a$1 digitaldaemon.com>, Matthew says..."antiAlias" <fu bar.com> wrote in message news:cg408a$2tge$1 digitaldaemon.com...I'll work on a more detailed treatment as soon as time permits. I'll have to first go back through my old source/notes and make sure that there's nothing that I've managed to miss. One thing I will say though: No matter how many times I revisit the problem, the businss of explicitly unloading a library at runtime has ugly consequences for raising our expectations of how this should be handled. I don't think the problem can be completely solved for in-memory objects, without resorting to proxies and/or notification lists.Eric describes (below) sounds really attractive.It sounds promising. I'd like to hear more fine details, though.I'd also like to hear if his ideas would require changes to std.loader (as I'm itching for an excuse to rewrite that stillborn obscenity).I think my first reaction to reading that source was: "This compiled?" (j/k) I wouldn't anticipate need to change std.loader drastically. Outside of that, I'd love to see the thread-local storage bits broken out into another library or as an extension to std.thread. ;) One question though: is all the extra ref-counting code needed for linux libraries, or does it supply some extra value to both Win32 and Linux environments?I'd also like to hear Walter's opinions on the matter. I think this issue is of sufficient import to be a 1.0 prerequesite, don't you?I couldn't agree more. I too, would like to hear what direction things will take with respect to dll's.With respect to Kris' concern about handling exceptions, its really obnoxious how an uncaught exception within a library kills your app. Aside from making all of my libraries behave like class-factories, I've taken to using methods that do this:Other than that, what about the exception-boundary issue?Well, D's going to have an ABI, and since all exceptions are going to co-exist memorywise (when the GC's linearised/homogenised), what's the prob?int someMethod(int foo){ /* impl */ }..to be called and exported by a dll stub function:export(Windows) Exception someMethod(int foo,out _returnval){ Exception _exception; try{ _returnval = someMethod(foo); } catch(Exception e){ _exception = e; } return(_exception); }You can use a similar stub on the calling side that wraps the function pointer that you grab from the library. Meanwhile (on a slightly OT note), I'm still working on some of the more tricky aspects of dll's in D. In particular, I've tracked one really nasty bug down to (what looks like) the digitalmars-C backend:// deceptively simple example. import std.c.windows.windows; void main(){ HMODULE mod = LoadLibrary("mydll.dll"); printf("freeing..."); FreeLibrary(mod); printf("You will never see this print.\n"); }(Matthew, Kris, have you had this problem on your Windows machines? I've done this on two separate boxes with the same result. If you two or anyone else can confirm this, I'll go ahead and post it to the bugs NG) Basically, stdout and stdin are "automagically" set to EOF (or some similar state) after the call to FreeLibrary(): nothing goes in and nothing comes out. Everything else runs fine, no exceptions are thrown, and GetLastError() faithfully returns 0. I've been able to recreate the above in DMC, with a 100% C-built Dll using the same .def file as the mydll sample. The results are also the same when calling that dll from a host program written in MSVC6, DMD and DMC. Unless I'm horribly mistaken on how to do compose dll's using Digitalmars' technology, this is what you get the instant you unload any DMC/DMD built dll. The problem seems to only manifest when a proper DllMain() method is exported from the library. If none is provided, or if the given implementation can be optimized away, the error does not ocurr. This caused me hours upon hours of anguish trying to figure out why in my DSP/Mango server kept quietly halting on me: it was waiting for console input to terminate, but Mango's Stdin throws on EOF. :( - Pragma
Aug 21 2004
In article <cg8kut$2ilc$1 digitaldaemon.com>, Matthew says...To my mind, we have two choices. One option is that the GC and supporting infrastructure is *always* in some DCore.dll - i.e. there're no more statically linked programs - in the same vein as .NET. The other option is that we come up with a mechanism whereby each link-unit is able to detect whether the process in which it is loaded already has a GC and, if so, links to that, otherwise starting its own. The complication to this is that if the first such link-unit is not the process' exe, we have the issue whereby the GC might be prematurely unloaded while other link-units are still depending on it. This could, hopefully(!), be resolved be having dependent link-units hold an independent dynamic-load reference on the GC's owning DLL. Thoughts?I like the idea, but it represents quite a paradigm shift for D. Also, any time you introduce a platform library, you have the messy consequences of library versioning and which library instance (if multiple are present) is used on the search path. - Pragma
Aug 21 2004
"pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in message news:cg5184$c7u$1 digitaldaemon.com...FYI: this is a long post, please read. Thank you. :) In article <cg41tm$2u6a$1 digitaldaemon.com>, Matthew says...Ok. This is an issue that will run and run, I think. At least for a month or two, or until it's sorted, at least."antiAlias" <fu bar.com> wrote in message news:cg408a$2tge$1 digitaldaemon.com...I'll work on a more detailed treatment as soon as time permits. I'll have to first go back through my old source/notes and make sure that there's nothing that I've managed to miss.Eric describes (below) sounds really attractive.It sounds promising. I'd like to hear more fine details, though.One thing I will say though: No matter how many times I revisit the problem, the businss of explicitly unloading a library at runtime has ugly consequences regardless of how the GC is hooked.Can you give some more detailed examples. I'm an example kinda guy. :)for raising our expectations of how this should be handled. I don't think the problem can be completely solved for in-memory objects, without resorting to proxies and/or notification lists.Can you be specific? I'm troubled by its implementations for certain reasons, but I'd like to hear your unalloyed criticisms.I'd also like to hear if his ideas would require changes to std.loader (as I'm itching for an excuse to rewrite that stillborn obscenity).I think my first reaction to reading that source was: "This compiled?" (j/k)I wouldn't anticipate need to change std.loader drastically. Outside of that, I'd love to see the thread-local storage bits broken out into another library or as an extension to std.thread. ;)Do you think we'll need to provide any additional mechanisms that will need to be standardised via std.loader? For example, GC-using D dlls might be required to export a specific entry point to facilitate GC-hooking, which would be built into std.loader.One question though: is all the extra ref-counting code needed for linux libraries, or does it supply some extra value to both Win32 and Linux environments?Probably not for Linux, but I'm very cautious/cynical on this issue, as I've previously been bitten on some UNIXen that did not do internal ref-counting on dynamic libs. Hence, I think it's safest to do it ourselves.I've posted another, more detailed, response on this in this thread. I'd be keen to hear your ideas on that.I'd also like to hear Walter's opinions on the matter. I think this issue is of sufficient import to be a 1.0 prerequesite, don't you?I couldn't agree more. I too, would like to hear what direction things will take with respect to dll's.Yes, exceptions also need sorting from a multiple library point of view. As I say in the other post, I'm beginning to think that D link-units need to search each other out at runtime, and coordinate their activities somehow. We've just got to hope that it turns out to be less messy than COM or, heaven forefend, .NET!With respect to Kris' concern about handling exceptions, its really obnoxious how an uncaught exception within a library kills your app. Aside from making all of my libraries behave like class-factories, I've taken to using methods that do this:Other than that, what about the exception-boundary issue?Well, D's going to have an ABI, and since all exceptions are going to co-exist memorywise (when the GC's linearised/homogenised), what's the prob?I confess I've done ~0 dynamic libs with D. :-)int someMethod(int foo){ /* impl */ }..to be called and exported by a dll stub function:export(Windows) Exception someMethod(int foo,out _returnval){ Exception _exception; try{ _returnval = someMethod(foo); } catch(Exception e){ _exception = e; } return(_exception); }You can use a similar stub on the calling side that wraps the function pointer that you grab from the library. Meanwhile (on a slightly OT note), I'm still working on some of the more tricky aspects of dll's in D. In particular, I've tracked one really nasty bug down to (what looks like) the digitalmars-C backend:// deceptively simple example. import std.c.windows.windows; void main(){ HMODULE mod = LoadLibrary("mydll.dll"); printf("freeing..."); FreeLibrary(mod); printf("You will never see this print.\n"); }(Matthew, Kris, have you had this problem on your Windows machines? I've done this on two separate boxes with the same result. If you two or anyone else can confirm this, I'll go ahead and post it to the bugs NG)Basically, stdout and stdin are "automagically" set to EOF (or some similar state) after the call to FreeLibrary(): nothing goes in and nothing comes out. Everything else runs fine, no exceptions are thrown, and GetLastError() faithfully returns 0. I've been able to recreate the above in DMC, with a 100% C-built Dll using the same .def file as the mydll sample. The results are also the same when calling that dll from a host program written in MSVC6, DMD and DMC. Unless I'm horribly mistaken on how to do compose dll's using Digitalmars' technology, this is what you get the instant you unload any DMC/DMD built dll. The problem seems to only manifest when a proper DllMain() method is exported from the library. If none is provided, or if the given implementation can be optimized away, the error does not ocurr. This caused me hours upon hours of anguish trying to figure out why in my DSP/Mango server kept quietly halting on me: it was waiting for console input to terminate, but Mango's Stdin throws on EOF. :( - Pragma
Aug 21 2004
In article <cg8png$2ltl$1 digitaldaemon.com>, Matthew says..."pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote inI'll take an oversimplified example from my D-Servlet Pages project. void foo(Request req,Response res){ // ServletLibrary proxies all the exports from the dll // and exposes some extra housekeeping functions ServletLibrary library = getServletLibrary("mylib.dll"); // library is queried for a servlet. The servlet is created inside the dll DSPServlet servlet = library.getServlet(); // Do some work (generate HTML, and so forth) servlet.service(req,res); // This frees the library. It is now no longer in memory library.unload(); // "servlet" is now invalid (see below) } No matter which side has the responsibility for performing GC operations and memory allocations, the V-table for any object always lives where it was created. This application in particular rebuilds dlls on demand, so references to servlets can be invalidated at a drop of a hat, across multiple threads.One thing I will say though: No matter how many times I revisit the problem, the businss of explicitly unloading a library at runtime has ugly consequences regardless of how the GC is hooked.Can you give some more detailed examples. I'm an example kinda guy. :)Honestly, it comes down to a matter of coding style: I'm just not used to reading your code. :) You say poh-tay-toh I say po-tot-oh... But I understand why its organized the way it is, and I feel its a very solid lib. The only thing I'd have done differently would be to roll HXModule into a non-auto class that handles all the refcounting, while wrapping the linux functions with Win32-like functions (or the other way around), so there's less code in there.I think my first reaction to reading that source was: "This compiled?" (j/k)Can you be specific?I'm troubled by its implementations for certain reasons, but I'd like to hear your unalloyed criticisms.If we're going to go with hooking rather than a GCCore.dll-type solution (from your other post, I like that idea), then yea, that would be best served internally by loader. A non-auto class (DllModule maybe?) would be a nice touch. Also an 'event' (I guess a delegate[] in D is close enough) that is called when a dll is finally unloaded (refcount goes to zero), would be a *very* nice addition.I wouldn't anticipate need to change std.loader drastically. Outside of that, I'd love to see the thread-local storage bits broken out into another library or as an extension to std.thread. ;)Do you think we'll need to provide any additional mechanisms that will need to be standardised via std.loader? For example, GC-using D dlls might be required to export a specific entry point to facilitate GC-hooking, which would be built into std.loader.Yes, exceptions also need sorting from a multiple library point of view. As I say in the other post, I'm beginning to think that D link-units need to search each other out at runtime, and coordinate their activities somehow. We've just got to hope that it turns out to be less messy than COM or, heaven forefend, .NET!I confess I've done ~0 dynamic libs with D. :-)Hehe.. we'll fix that. ;) Walter has made it easy as sin to create .dll's in D. What's missing is a D-standard stub that is /implicitly/ added to a library along with classinfo, exception piping, GC hooking, etc etc... one becomes painfully aware of all this only *after* you start working with dll's heavily. Its even worse coming from using Java's classloader or .NET assemblies; D has a very long way to go in this department. - Pragma
Aug 21 2004