Search code examples
c#unmanaged-memory

Exchange pinned array's pointer with an unmanaged memory pointer


I'm pinning and unpinning with:

    GCHandle pinArray(object a)
    {
        return GCHandle.Alloc(a, GCHandleType.Pinned);
    }

    void unpinArray(GCHandle h)
    {
        h.Free(); 
    }

before and after an opencl method so array does not move while computing on it. Now I need to exchange backing array pointer with an aligned unmanaged array pointer to have faster read/write operations on it.

But I couldn't find anything like "change value of gchandle backing array pointer" info.

I need something like an "exchange" method:

 GCHandle h=pinArray(array);

 // how to?
 IntPtr oldBackingArray=exchange(h,alignedMallocCSpace(10000000,4096));

 // unmanaged operations
 copyValues(h,oldBackingArray);
 compute(array,...); // only passing with "array" for simplicity everywhere
 array[3]=5;
 l=array.toList();
 compute(array,....);
 Console.WriteLine(array[3]);
 copyValues(oldBackingArray,h);


 freeCSpace(exchange(h,oldBackingArray));

 unpinArray(h);

does this need reflection to access and change that variable? There are also many C# methods using those arrays inside compute method so will it give more speed even on C# space too? So I'm tring to let C# to use alignedAlloc space for everything using "array" object until I unpin it.


Solution

  • You don't need to. The GCHandle relates to managed memory; unmanaged memory does not require any kind of GCHandle. Nor is it possible to talk to that memory as though it is a managed array. Instead, you need to accept that the unmanaged data is a pointer and only a pointer. You can abstract over the top of that to hide these details, but it doesn't change the reality. Fortunately, to the casual observer, talking to a SomeType[] is very similar to talking to a SomeType* - as long as you pass the lengths around yourself.

    In the future, the upcoming Span<T> does a great job of unifying pointers and arrays, but that is only experimental at the moment.