Yes, the pinned object is pinned only while a pinning pointer points to it.
Once the pinning pointer goes out of scope or is set to 0 in the program,
the object can be moved in the compaction phase of garbage collection. Any
remaining unmanaged pointers to the object should not be dereferenced then
in case they are dangling pointers, i.e. have outlived their target.
A pinning pointer is volatile by default. This prevents the optimizer from
deleting generated code for an assignment of 0 to the pinning pointer in the
source. If it were not volatile, the assignment would be treated as though
it were dead code and the object would still be pinned until its pinning
pointer went out of scope.
> Thanks David for reminding me about __pin.
> What I am wondering about is what happens to the pinned array, is it free
to
> be moved by the garbage collector after the pointer goes out of scope?
> My latest code is:
> System::Array* CMHistogram::GrabData()
> {
> int size = m_pHistogram->GetSize();
> int mdata __gc[] = new int __gc[size];
> int __pin * pmdata = &mdata[0];
> m_pHistogram->GrabData( pmdata, size );
> return( mdata );
> }
> void CHistogram::GrabData( int* pData, int& size )
> {
> EnterCriticalSection( &m_csLock );
> {
> memcpy( pData, m_Data, size * sizeof( int ) );
> }
> LeaveCriticalSection( &m_csLock );
> }
> Bill
> --
> http://www.componentsnotebook.com
> > The call to memcpy should read
> > memcpy(pmdata, udata, size * sizeof(int));
> > for copying the native array. Sorry for the typo.
> > --
> > David Wolfram
> > Visual C++ Compiler Team
> > This posting is covered by the Conditions of Use:
> > http://www.microsoft.com/info/cpyright.htm
> > > Hi Bill,
> > > A way to do this which may be faster is to copy the data using native
> > code.
> > > int mdata __gc[] = new int __gc[size];
> > > for( int j = 0 ; j < size ; j++ )
> > > {
> > > mdata[j] = udata[j];
> > > }
> > > could be re-written as
> > > int mdata __gc[] = new int __gc[size];
> > > int __pin * pmdata = &pmdata[0]; // pin the managed array
> > > memcpy(udata, pmdata, size * sizeof(int));
> > > You need to pin the managed array first to prevent the possibility of
> the
> > > garbage collector moving it during the call to memcpy.
> > > --
> > > David Wolfram
> > > Visual C++ Compiler Team
> > > This posting is covered by the Conditions of Use:
> > > http://www.microsoft.com/info/cpyright.htm
> > > > I have a legacy real-time multi-threaded app, written in C++.
> > > > I eliminated all the MFC and ATL code, so all I had left was the
core
> of
> > > the
> > > > application which is time critical and mult-threaded. Around this I
> > added
> > > a
> > > > managed C++ layer. The GUI and remotting is being done in C#.
> > > > For updating my graphics display, as well as being able to grab a
snap
> > > shot
> > > > of the display data remotely, I need to move arrays from the
> un-managed
> > to
> > > > the managed code once per second. I need to move 3 arrays of 4096
> > > integers
> > > > once a second.
> > > > I have come up with the following code, but was wondering if there
is
> a
> > > more
> > > > efficient way of doing this.
> > > > Here is the managed C++ layer:
> > > > System::Array* CMHistogram::GrabData()
> > > > {
> > > > int size = m_pHistogram->GetSize();
> > > > int* udata = new int[size];
> > > > m_pHistogram->GrabData( udata, size );
> > > > int mdata __gc[] = new int __gc[size];
> > > > for( int j = 0 ; j < size ; j++ )
> > > > {
> > > > mdata[j] = udata[j];
> > > > }
> > > > delete[] udata;
> > > > return( mdata );
> > > > }
> > > > and here is the un-managed layer:
> > > > void CHistogram::GrabData( int* pData, int& size )
> > > > {
> > > > if( size > m_nBins )
> > > > {
> > > > size = m_nBins;
> > > > }
> > > > EnterCriticalSection( &m_csLock );
> > > > {
> > > > memcpy( pData, m_Data, size * sizeof( int ) );
> > > > }
> > > > LeaveCriticalSection( &m_csLock );
> > > > m_bDirty = false;
> > > > }
> > > > Here is the C# layer, with the timer set for 1 sec:
> > > > private int[] m_Buffer;
> > > > private CMHistogram m_Hist;
> > > > private void timer_Tick(object sender, System.EventArgs e)
> > > > {
> > > > if( UpdateData() )
> > > > {
> > > > Display.Invalidate();
> > > > UpdateControlBar();
> > > > }
> > > > }
> > > > private bool UpdateData()
> > > > {
> > > > bool bDirty = m_Hist.Dirty;
> > > > if( bDirty )
> > > > {
> > > > m_Buffer = (int[])m_Hist.GrabData();
> > > > CalcStatistics();
> > > > }
> > > > return( bDirty );
> > > > }
> > > > Bill
> > > > --
> > > > http://www.componentsnotebook.com/