How to make C (P/invoke) code called from C# "Thread-safe"

c, c#, multithreading, pinvoke

Solution

A common pattern is to have

- a function that allocates memory for the state,

- a function that has no side-effects but mutating the passed-in state, and

- a function that releases the memoy for the state.

The C# side would look like this:

Usage:

var state = new ThreadLocal<SomeSafeHandle>(NativeMethods.CreateSomeState);

Parallel.For(0, 100, i =>
{
    var result = NativeMethods.SomeFunction(state.Value, i, 42);

    Console.WriteLine(result);
});

Declarations:

internal static class NativeMethods
{
    [DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern SomeSafeHandle CreateSomeState();

    [DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int SomeFunction(SomeSafeHandle handle,
                                          int parameter1,
                                          int parameter2);

    [DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
    internal static extern int FreeSomeState(IntPtr handle);
}

SafeHandle magic:

[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
internal class SomeSafeHandle : SafeHandle
{
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
    public SomeSafeHandle()
        : base(IntPtr.Zero, true)
    {
    }

    public override bool IsInvalid
    {
        get { return this.handle == IntPtr.Zero; }
    }

    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
    protected override bool ReleaseHandle()
    {
        return NativeMethods.FreeSomeState(this.handle) == 0;
    }
}

Problem

I have some simple C-code which uses a single global-variable. Obviously this is not thread-safe, so when I call it from multiple threads in C# using P/invoke, things screw up. How can I either import this function separately for each thread, or make it thread-safe? I tried declaring the variable `__declspec(thread)`, but that caused the program to crash. I also tried making a C++/CLI class, but it doesn't allow member-functions to be `__declspec(naked)`, which I need (I'm using inline-assembly). I'm not very experienced writing multi-threaded C++ code, so there might be something I'm missing. Here is some example code: C# ``` [DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int SomeFunction(int parameter1, int parameter2); ``` C++ ``` extern "C" { int someGlobalVariable; int __declspec(naked) _someFunction(int parameter1, int parameter2) { __asm { //someGlobalVariable read/written here } } int __declspec(dllexport) SomeFunction(int parameter1, int parameter2) { return _someFunction(parameter1, parameter2); } } ``` [Edit]: The result of `SomeFunction()` must go in some prescribed order based on `someGlobalVariable` (think of eg. a PRNG, with `someGlobalVariable` as the internal state). So, using a mutex or other sort of lock is not an option - each thread must have its own copy of `someGlobalVariable`.

Original source

Related problems