Hi there, I'm having a bit of trouble using an HRASCONN object as a class member variable inside my managed C++ class. When I call RasDial() and pass in the address of my HRASCONN object, I get the following compiler error from Visual C++ 2005: error C2664: 'RasDialW' : cannot convert parameter 6 from 'cli::interior_ptr<Type>' to 'HRASCONN *' Here is my code snippet: RasInterface.h: -------------------- #include <ras.h> private ref class RasInterface { private: HRASCONN _rasConnection; .... }; RasInterface.cpp: ----------------------- void RasInterface::Dial() { .... DWORD result = RasDial(NULL, NULL, _dialParams, NULL, NULL, &_rasConnection); .... } My question is: Do I need to use a pin_ptr<> here? After some investigation, I tried the following: pin_ptr<HRASCONN> rasConnectionPinned = &_rasConnection; DWORD result = RasDial(NULL, NULL, _dialParams, NULL, NULL, rasConnectionPinned); This compiles and appears to run correctly, but is this The Right Thing To Do? Thanks in advance for any thoughts! -- Whitney Kew
[quoted text, click to view] Whitney Kew wrote: > RasInterface.h: > -------------------- > #include <ras.h> > private ref class RasInterface > { > private: > HRASCONN _rasConnection; > ... > }; > > RasInterface.cpp: > ----------------------- > void RasInterface::Dial() > { > ... > DWORD result = RasDial(NULL, NULL, _dialParams, NULL, NULL, > &_rasConnection); > ... > }
What I would do is this: void RasInterface::Dial() { HRASCONN result_connection; DWORD result = RasDial(NULL, NULL, _dialParams, NULL, NULL, &result_connection); _rasConnection = connection; ... } This way you can avoid pinning an entire object unnecessarily. Right after that I would rename _rasConnection to rasConnection_, because names starting with underscore are reserved for the compiler and standard library vendor. Reference: http://www.gotw.ca/gotw/085.htm
[quoted text, click to view] "Tamas Demjen" wrote: > Whitney Kew wrote: > > > RasInterface.h: > > -------------------- > > #include <ras.h> > > private ref class RasInterface > > { > > private: > > HRASCONN _rasConnection; > > ... > > }; > > > > RasInterface.cpp: > > ----------------------- > > void RasInterface::Dial() > > { > > ... > > DWORD result = RasDial(NULL, NULL, _dialParams, NULL, NULL, > > &_rasConnection); > > ... > > } > > What I would do is this: > void RasInterface::Dial() > { > HRASCONN result_connection; > DWORD result = RasDial(NULL, NULL, _dialParams, NULL, NULL, > &result_connection); > _rasConnection = connection; > ... > } > > This way you can avoid pinning an entire object unnecessarily. > > Tom >
Hi Tom, I ended up doing what you suggested, so thank you. However, could I have used a pin_ptr<> here? Your response implies that doing so wouldn't be ideal; why is that? I'm more curious than anything. Why is pinning an entire object a bad thing? Appreciate any thoughts....
[quoted text, click to view] Whitney Kew wrote: > I ended up doing what you suggested, so thank you. However, could I have > used a pin_ptr<> here? Your response implies that doing so wouldn't be > ideal; why is that? I'm more curious than anything. Why is pinning an > entire object a bad thing? Appreciate any thoughts....
Pinning tells the garbage collector that the object can't be moved in the memory, because there is a native pointer to it. In a heavily multi-threaded project, such as a server/service, very extensive pinning might hurt performance in some cases, because it limits the way the gabage collector can arrange your objects. It's the same issue as passing objects by value vs by reference. When the object is an integer, a pointer, or even a double, I tend to pass it by value, while anything larger than that is most efficiently handled when passed by reference. Similarly, if you have a large managed object or array that needs to be passed to a native function, just pin it. Pinning is very efficient if you don't keep it pinned for longer than necessary. On the other hand, if you just need to pass a single pointer or integer to a native function, it's probably easier and cleaner to introduce a temporary and copy it by value. Do whichever you find easier to read and maintain. Optimization should be a secondary concern, unless profiling proves that a particular function is a performance bottleneck. I doubt in your case either solution would cause performance issues.
[quoted text, click to view] "Tamas Demjen" wrote: > Whitney Kew wrote: > > > I ended up doing what you suggested, so thank you. However, could I have > > used a pin_ptr<> here? Your response implies that doing so wouldn't be > > ideal; why is that? I'm more curious than anything. Why is pinning an > > entire object a bad thing? Appreciate any thoughts.... > > Pinning tells the garbage collector that the object can't be moved in > the memory, because there is a native pointer to it. In a heavily > multi-threaded project, such as a server/service, very extensive pinning > might hurt performance in some cases, because it limits the way the > gabage collector can arrange your objects. > > It's the same issue as passing objects by value vs by reference. When > the object is an integer, a pointer, or even a double, I tend to pass it > by value, while anything larger than that is most efficiently handled > when passed by reference. > > Similarly, if you have a large managed object or array that needs to be > passed to a native function, just pin it. Pinning is very efficient if > you don't keep it pinned for longer than necessary. On the other hand, > if you just need to pass a single pointer or integer to a native > function, it's probably easier and cleaner to introduce a temporary and > copy it by value. > > Do whichever you find easier to read and maintain. Optimization should > be a secondary concern, unless profiling proves that a particular > function is a performance bottleneck. I doubt in your case either > solution would cause performance issues. > > Tom >
Thank you for your time, Tom; you've been very helpful!
[quoted text, click to view] "Tamas Demjen" <tdemjen@yahoo.com> wrote in message news:OwM41UvcHHA.4984@TK2MSFTNGP05.phx.gbl... > Whitney Kew wrote: > >> I ended up doing what you suggested, so thank you. However, could I have >> used a pin_ptr<> here? Your response implies that doing so wouldn't be >> ideal; why is that? I'm more curious than anything. Why is pinning an >> entire object a bad thing? Appreciate any thoughts.... > > Pinning tells the garbage collector that the object can't be moved in the > memory, because there is a native pointer to it. In a heavily > multi-threaded project, such as a server/service, very extensive pinning > might hurt performance in some cases, because it limits the way the gabage > collector can arrange your objects. > > It's the same issue as passing objects by value vs by reference. When the > object is an integer, a pointer, or even a double, I tend to pass it by > value, while anything larger than that is most efficiently handled when > passed by reference. > > Similarly, if you have a large managed object or array that needs to be > passed to a native function, just pin it. Pinning is very efficient if you > don't keep it pinned for longer than necessary. On the other hand, if you > just need to pass a single pointer or integer to a native function, it's > probably easier and cleaner to introduce a temporary and copy it by value.
Pinning appears to copy the object to the large object heap, so for large objects it's trivial, and for small objects it incurs the copy that you probably chose pass-by-pointer to avoid. It also causes additional fragmentation. [quoted text, click to view] > > Do whichever you find easier to read and maintain. Optimization should be > a secondary concern, unless profiling proves that a particular function is > a performance bottleneck. I doubt in your case either solution would cause > performance issues. > > Tom
[quoted text, click to view] "Willy Denoyette [MVP]" <willy.denoyette@telenet.be> wrote in message news:%23kdbjO6cHHA.2068@TK2MSFTNGP06.phx.gbl... > "Ben Voigt" <rbv@nospam.nospam> wrote in message > news:%23Tasm$vcHHA.3648@TK2MSFTNGP05.phx.gbl... >> >> "Tamas Demjen" <tdemjen@yahoo.com> wrote in message >> news:OwM41UvcHHA.4984@TK2MSFTNGP05.phx.gbl... >>> Whitney Kew wrote: >>> >>>> I ended up doing what you suggested, so thank you. However, could I >>>> have used a pin_ptr<> here? Your response implies that doing so >>>> wouldn't be ideal; why is that? I'm more curious than anything. Why is >>>> pinning an entire object a bad thing? Appreciate any thoughts.... >>> >>> Pinning tells the garbage collector that the object can't be moved in >>> the memory, because there is a native pointer to it. In a heavily >>> multi-threaded project, such as a server/service, very extensive pinning >>> might hurt performance in some cases, because it limits the way the >>> gabage collector can arrange your objects. >>> >>> It's the same issue as passing objects by value vs by reference. When >>> the object is an integer, a pointer, or even a double, I tend to pass it >>> by value, while anything larger than that is most efficiently handled >>> when passed by reference. >>> >>> Similarly, if you have a large managed object or array that needs to be >>> passed to a native function, just pin it. Pinning is very efficient if >>> you don't keep it pinned for longer than necessary. On the other hand, >>> if you just need to pass a single pointer or integer to a native >>> function, it's probably easier and cleaner to introduce a temporary and >>> copy it by value. >> >> Pinning appears to copy the object to the large object heap, so for large >> objects it's trivial, and for small objects it incurs the copy that you >> probably chose pass-by-pointer to avoid. It also causes additional >> fragmentation. >> > Not at all, "pinning" puts a *reference* to the instance in the "handle > table", which happens to be part of the LOH in the current implementation > of the CLR, the pinned object stay's where it is, wherever that may be. > Unpinning removes the reference from the handle table. Pinning objects for > a long period can lead to fragmentation, as the GC cannot relocate the > object in the heap during compactation.
From testing with PtrToStringChars with and without pinning, the pointer moved significantly for small strings, and not at all for large strings, and the pinned small string looked like it moved into the area with the large strings. Maybe a GC collection happened to occur in between, but I doubt it, those are usually triggered by allocation and in any case I didn't have a high enough number of allocations to require collection.
[quoted text, click to view] "Ben Voigt" <rbv@nospam.nospam> wrote in message news:%23Tasm$vcHHA.3648@TK2MSFTNGP05.phx.gbl... > > "Tamas Demjen" <tdemjen@yahoo.com> wrote in message > news:OwM41UvcHHA.4984@TK2MSFTNGP05.phx.gbl... >> Whitney Kew wrote: >> >>> I ended up doing what you suggested, so thank you. However, could I have used a >>> pin_ptr<> here? Your response implies that doing so wouldn't be ideal; why is that? >>> I'm more curious than anything. Why is pinning an entire object a bad thing? >>> Appreciate any thoughts.... >> >> Pinning tells the garbage collector that the object can't be moved in the memory, because >> there is a native pointer to it. In a heavily multi-threaded project, such as a >> server/service, very extensive pinning might hurt performance in some cases, because it >> limits the way the gabage collector can arrange your objects. >> >> It's the same issue as passing objects by value vs by reference. When the object is an >> integer, a pointer, or even a double, I tend to pass it by value, while anything larger >> than that is most efficiently handled when passed by reference. >> >> Similarly, if you have a large managed object or array that needs to be passed to a >> native function, just pin it. Pinning is very efficient if you don't keep it pinned for >> longer than necessary. On the other hand, if you just need to pass a single pointer or >> integer to a native function, it's probably easier and cleaner to introduce a temporary >> and copy it by value. > > Pinning appears to copy the object to the large object heap, so for large objects it's > trivial, and for small objects it incurs the copy that you probably chose pass-by-pointer > to avoid. It also causes additional fragmentation. >
Not at all, "pinning" puts a *reference* to the instance in the "handle table", which happens to be part of the LOH in the current implementation of the CLR, the pinned object stay's where it is, wherever that may be. Unpinning removes the reference from the handle table. Pinning objects for a long period can lead to fragmentation, as the GC cannot relocate the object in the heap during compactation. Willy.
[quoted text, click to view] "Ben Voigt" <rbv@nospam.nospam> wrote in message news:%23K4d%23l6cHHA.4388@TK2MSFTNGP05.phx.gbl... > > "Willy Denoyette [MVP]" <willy.denoyette@telenet.be> wrote in message > news:%23kdbjO6cHHA.2068@TK2MSFTNGP06.phx.gbl... >> "Ben Voigt" <rbv@nospam.nospam> wrote in message >> news:%23Tasm$vcHHA.3648@TK2MSFTNGP05.phx.gbl... >>> >>> "Tamas Demjen" <tdemjen@yahoo.com> wrote in message >>> news:OwM41UvcHHA.4984@TK2MSFTNGP05.phx.gbl... >>>> Whitney Kew wrote: >>>> >>>>> I ended up doing what you suggested, so thank you. However, could I have used a >>>>> pin_ptr<> here? Your response implies that doing so wouldn't be ideal; why is that? >>>>> I'm more curious than anything. Why is pinning an entire object a bad thing? >>>>> Appreciate any thoughts.... >>>> >>>> Pinning tells the garbage collector that the object can't be moved in the memory, >>>> because there is a native pointer to it. In a heavily multi-threaded project, such as a >>>> server/service, very extensive pinning might hurt performance in some cases, because it >>>> limits the way the gabage collector can arrange your objects. >>>> >>>> It's the same issue as passing objects by value vs by reference. When the object is an >>>> integer, a pointer, or even a double, I tend to pass it by value, while anything larger >>>> than that is most efficiently handled when passed by reference. >>>> >>>> Similarly, if you have a large managed object or array that needs to be passed to a >>>> native function, just pin it. Pinning is very efficient if you don't keep it pinned for >>>> longer than necessary. On the other hand, if you just need to pass a single pointer or >>>> integer to a native function, it's probably easier and cleaner to introduce a temporary >>>> and copy it by value. >>> >>> Pinning appears to copy the object to the large object heap, so for large objects it's >>> trivial, and for small objects it incurs the copy that you probably chose >>> pass-by-pointer to avoid. It also causes additional fragmentation. >>> >> Not at all, "pinning" puts a *reference* to the instance in the "handle table", which >> happens to be part of the LOH in the current implementation of the CLR, the pinned object >> stay's where it is, wherever that may be. Unpinning removes the reference from the handle >> table. Pinning objects for a long period can lead to fragmentation, as the GC cannot >> relocate the object in the heap during compactation. > > From testing with PtrToStringChars with and without pinning, the pointer moved > significantly for small strings, and not at all for large strings, and the pinned small > string looked like it moved into the area with the large strings. Maybe a GC collection > happened to occur in between, but I doubt it, those are usually triggered by allocation > and in any case I didn't have a high enough number of allocations to require collection. >
Pinning is the act of fixing the location of the object instance instance in the GC heap. Again all there is done is taking the address and wrap it in a GCHandle and store this handle in the handle table. The handle table contains stuff like: Strong Handles, Pinned Handles, Async Pinned Handles, Ref Count Handles, Weak Long Handles, Weak Short Handles. The easiest way to watch all these is by running your code in windbg.exe debugger and load the SOS.DLL debugger extension. All you need is simple program like this: .... GC::Collect(); // clean-up the garbage so far GC::WaitForPendingFinalizers(); array<int>^ ia = gcnew array<int>(10); GCHandle^ pinnedObj = GCHandle::Alloc(ia, GCHandleType::Pinned); DebugBreak(); Console::WriteLine("0x{0:x4}", (int)pinnedObj->AddrOfPinnedObject()); .... load the sos extension and issue a !dso followed by a !do command, specifying the reference of the array instance. !eeheap returns the locations of the heaps, the array should live in the Gen0 heap. !gcroot <objref> returns the number of roots and should show you something like: .... edi:Root:026b38b8(System.Int32[]) Scan Thread 0 OSTHread 9b8 Scan Thread 2 OSTHread 348 DOMAIN(004B3400):HANDLE(Pinned):211590:Root:026b38b8(System.Int32[]) see here the object is rooted and pinned at location 026b38b8 (in the GC heap) !gchandles will shows all handles in the handle table, you should find the array in this table as well. Willy.
Don't see what you're looking for? Try a search.
|