Thread overview | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 23, 2006 using scoped_handle | ||||
---|---|---|---|---|
| ||||
Attachments:
| Hi, I have a 3rd party lib that provides various create/release functions for various types. They all return a pointer to the type (some are opaque some are not) e.g. Type*. I want to use scoped_handle with these to give me automatic release when I go out of scope. The problem is that the all the release functions accept as a parameter Type**. This is, purportedly, done to that the release function can zero the pointer. This means that I cannot use scoped_handle as RAII, but only as a separate object defined after the bare pointer (in the same scope). If I define a forwarding function that accepts Type*& and forwards to the original function (as &arg) , the code does not compile. Any suggestions? Thanks, Adi |
November 23, 2006 Re: using scoped_handle | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adi Shavit | > I have a 3rd party lib that provides various create/release functions for various types. They all return a pointer to the type (some are opaque some are not) e.g. Type*. > > I want to use scoped_handle with these to give me automatic release when I go out of scope. A jolly good idea. ;-) > The problem is that the all > the release functions accept as a parameter Type**. This is, > purportedly, done to that the release function can zero the > pointer. This means that I cannot use scoped_handle as RAII, > but only as a separate object defined after the bare pointer > (in the same scope). If I define a forwarding function that > accepts Type*& and forwards to the original function > (as &arg) , the code does not compile. > > Any suggestions? None off the top of my head. I'm done with my post-book break tomorrow, after which I'll apply my mind to this issue. Give me until after the w/e, and I'll see what I can conjure. <g> |
November 23, 2006 Re: using scoped_handle | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew | Don't know how parse text/html message |
December 27, 2006 Re: using scoped_handle | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adi Shavit | > > Any suggestions? > Well, I guess a wrapper that somehow (how?) binds the pointer to the first > argument and accepts a dummy argument of type Type* that is not used. > But this is not really elegant. > > Adi Ok I've managed to get an effective solution. It's a prosaic, but functional, solution: just overload all the ctors for the by-ref functions. And the function translators now have another member type - indirect_function_type - and another method - translate_indirect(). I wanted to do it with an adaptor function template, something along the lines of template< typename R , typename H > function_creator<R, H, ???>::fn set_null_deref(R (*pfn)(H*) ); But as you can see from the ???, there's no way to get a function in there. The answer would be to have the function_creator class hold some state, but then that would require scoped_handle to understand function pointers and some special kind of function object. It all seemed too much, so, even though it's an exponential solution - 6 more overloads to cover all calling conventions and compiler weirdies - it's the way to go. Not to mention that, despite the extra complexity to the library author, it's a great deal simpler to the user. They just continue to pass the function to the s_h ctor, e.g. handle_t handle_make(char const *); void handle_close(handle_t); void handle_close_set_null(handle_t *); { // old form handle_t h = handle_make("abc"); scoped_handle<handle_t> sh(h, handle_close); } { // new form handle_t h = handle_make("def"); scoped_handle<handle_t> sh(h, handle_close_set_null); } using the adaptor would have required something like: { // new form with adaptor handle_t h = handle_make("def"); scoped_handle<handle_t> sh(h, set_null_deref(handle_close_set_null)); } So the extra brain/finger strain's just for the librarian. In any case, I think we're pretty safe from having a request to to R (*)(H***), don't you agree? ;-) I've a whole heap of testing to do now, to make sure this doesn't wreck anything, as it's a pretty fundamental component. But if it's good it'll be out with beta 35. (When, oh when will 1.9.1 proper ever get out there ... ? <g>) Cheers Matthew |
December 27, 2006 Re: using scoped_handle | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew | Hi Matthew, > Ok > > I've managed to get an effective solution. > > It's a prosaic, but functional, solution: just overload all the ctors for > the by-ref functions. And the function translators now have another member > type - indirect_function_type - and another method - translate_indirect(). > Yes, I guess this /would/ be the simplest solution. > <snip> > So the extra brain/finger strain's just for the librarian. In any case, I > think we're pretty safe from having a request to to R (*)(H***), don't you > agree? ;-) > Yes. Thanks! Adi |
January 31, 2007 scoped_handle and handle copies | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adi Shavit | Hi, Another question/remark about scoped_handle<>. The docs say <http://www.synesis.com.au/software/stlsoft/doc-1.9/classstlsoft_1_1scoped__handle.html#_details> it: Provides automated scope-based cleanup of arbitrary resource types without any memory allocation required to implement the generic support. The template is parameterised on the resource type (e.g. FILE*, int, void*) and instances are initialised from a resource handle and the address of a (single-parameter) cleanup function, as in: <snip...> FILE *file = ::fopen("file.ext", "r"); ::stlsoft::*scoped_handle*<FILE*> h2(file, ::fclose); Also, the class provides support for indirect cleanup function like releaseAndSetNull() (Thanks!). However, note the program below: #include <stlsoft/smartptr/scoped_handle.hpp> int* getNewInt() { return new int(1); } void releaseIntAndReset(int** n) { delete *n; *n = 0; } int main() { int* i =0; //stlsoft::scoped_handle<int*> fgdet(i, releaseIntAndReset); // this will NOT release i i = getNewInt(); stlsoft::scoped_handle<int*> fgdet(i, releaseIntAndReset); // only this will release i } My remarks might be just to clarify the documentation to specifically explain that (apparently) a COPY of the handle (e.g. i) is taken, and the release function is called on this copy, and NOT on the original (via a hypothetical reference). I somehow assumed that a reference to the handle is kept so that in the program above, i will be properly released. For example, with indirect releaseAndSetNull() functions, the setNull part is essentially thrown away, while the external pointer is left dangling. If it is in the same scope then this is not a problem, but say i above is a member, which get tested for 0 and allocated and release repeatedly in different scopes (e.g. methods), then manual 0 assignment will be required and the whole point of the scoped_handle in this case is missed. e.g.: int main() { int* i =0; { i = getNewInt(); stlsoft::scoped_handle<int*> fgdet(i, releaseIntAndReset); // release i, but not set i to 0 } int j = (int)i; // j != 0; } Of course, I can use the internal handle directly, but this is not always possible, and makes readability slightly harder. Adi |
February 01, 2007 Re: scoped_handle and handle copies | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adi Shavit | > Another question/remark about scoped_handle<>. > > The docs say > <http://www.synesis.com.au/software/stlsoft/doc-1.9/classstlsoft_1_1scoped__ handle.html#_details> > it: > > Provides automated scope-based cleanup of arbitrary resource types > without any memory allocation required to implement the generic > support. > > The template is parameterised on the resource type (e.g. FILE*, int, > void*) and instances are initialised from a resource handle and the > address of a (single-parameter) cleanup function, as in: > > <snip...> > > FILE *file = ::fopen("file.ext", "r"); > ::stlsoft::*scoped_handle*<FILE*> h2(file, ::fclose); > > > > Also, the class provides support for indirect cleanup function like > releaseAndSetNull() (Thanks!). > > However, note the program below: > > #include <stlsoft/smartptr/scoped_handle.hpp> > > int* getNewInt() > { > return new int(1); > } > void releaseIntAndReset(int** n) > { > delete *n; > *n = 0; > } > > > int main() > { > int* i =0; > //stlsoft::scoped_handle<int*> fgdet(i, releaseIntAndReset); // > this will NOT release i > i = getNewInt(); > stlsoft::scoped_handle<int*> fgdet(i, releaseIntAndReset); // > only this will release i > } > > My remarks might be just to clarify the documentation to specifically > explain that (apparently) a COPY of the handle (e.g. i) is taken, and > the release function is called on this copy, and NOT on the original > (via a hypothetical reference). > > I somehow assumed that a reference to the handle is kept so that in the program above, i will be properly released. > > For example, with indirect releaseAndSetNull() functions, the setNull > part is essentially thrown away, while the external pointer is left > dangling. > If it is in the same scope then this is not a problem, but say i above > is a member, which get tested for 0 and allocated and release repeatedly > in different scopes (e.g. methods), then manual 0 assignment will be > required and the whole point of the scoped_handle in this case is missed. > > e.g.: > > int main() > { > int* i =0; > { > i = getNewInt(); > stlsoft::scoped_handle<int*> fgdet(i, releaseIntAndReset); // > release i, but not set i to 0 > } > int j = (int)i; // j != 0; > } > > > Of course, I can use the internal handle directly, but this is not always possible, and makes readability slightly harder. Seems like a hasty implementation on my part. I think the better solution is to ensure that the external resource handle is "null'd". I worked it out this morning (on my bike <g>), and have just to find a time to implement it. Basically, I'll add a union that holds a "H h" and a "H* ph". The scoped_handle will hold onto an instance of that, and a marker to say which is viable. The function translators will know which member to use anyway (translate() will use the h member; translate_indirect will use the ph member). It's time for a beta 44 anyway. Just busy beavering with the last few issues on XSTLv1 - have so far chopped 600 pages to 545, and hope to get down to 500 - so it might be a day or two until I can do the STLSoft beta. btw, this'll also be properly "rooted" - i.e. all will be below /stlsoft-1.9.1-beta44/ - as I've recently done to several other projects. I'm starting to toe the OS line ... ;-) Once the book's sent off I will do STLSoft 1.9.1 proper. All that's really wanting is the docs and the website. So please keep sending in your documentation criticism. Cheers Matthew |
February 01, 2007 Re: scoped_handle and handle copies | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew Wilson | Don't know how parse text/html message |
February 01, 2007 Re: scoped_handle and handle copies | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adi Shavit Attachments:
| You're right. I'd already considered this, and so decided that the "nulling" ctor overload would take an address of the handle. This has the big advantage that there can be no such confusion, and the small disadvantage that you can't "inline" the allocation function invocation with the scoped_handle ctor. ;-) This should all work ticketyboo (LOL, don't you love the silly English and our daft expressions!). Just give me a few days to get over the last book push. BigBoy "Adi Shavit" <adish@gentech.co.il> wrote in message news:epsgtf$hve$1@digitaldaemon.com... Seems like a hasty implementation on my part. I think the better solution is to ensure that the external resource handle is "null'd". I worked it out this morning (on my bike <g>), and have just to find a time to implement it. Basically, I'll add a union that holds a "H h" and a "H* ph". The scoped_handle will hold onto an instance of that, and a marker to say which is viable. The function translators will know which member to use anyway (translate() will use the h member; translate_indirect will use the ph member). Hmmm.. That'll work and, indeed, fix the problem. However, I am concerned (from your point of view) that this would make 2 scoped_handle classes, with 2 subtly different behaviors. Ideally the union should (impossibly?) detect if the class was constructed with an externally held handle e.g. FILE *file = ::fopen("file.ext", "r"); // ... { ::stlsoft::scoped_handle<FILE*> h2(file, ::fclose); // ... } // ... or used with the internally held handle e.g. ::stlsoft::scoped_handle<int> h1(::open("file.ext"), ::close); What would happen if I used an indirect function, with a reference to a temporary? Can this happen? Can the scope of the scoped_handle<> exceed the scope of the given temporary ? Something like this: // MyClass ctor MyClass(): myScopedHandle(makeHandle(), ::releaseAndReset) // init myScopedHandle handle with indirect function {} Can this happen? makeHandle() will generate a temp handle, and myScopedHandle will hold a reference to it. When the ctor goes out of scope, what happens to the temp reference? (I'm not so clear about temp rules at the moment). In this case, it seems that a copy need to be made, not a reference. Confused, Adi |
February 01, 2007 Re: scoped_handle and handle copies | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew Wilson Attachments:
| > You're right. I'd already considered this, and so decided that the "nulling" ctor overload would take an address of the handle. This has the big advantage that there can be no such confusion, and the small disadvantage that you can't "inline" the allocation function invocation with the scoped_handle ctor. ;-) Actually, I'm not sure I understand what you mean. The problem I mentioned was specifically related to and assumed taking a reference. Do you mean something like taking a reference as opposed to taking a const reference to not compile (or select another ctor) when a temp is given? > This should all work ticketyboo (LOL, don't you love the silly English > and our daft expressions!). Just give me a few days to get over the > last book push. > > BigBoy You're in a good mood :-). Adi |
Copyright © 1999-2021 by the D Language Foundation