Kevin Li
Kevin Li

Reputation: 323

.NET Garbage Collection, C++/CLI interior_ptr, and Thread Safety

So I understand that interior_ptr<typename> can be used to operate with arrays of structs exactly as in C♯ using the fixed statement, but it doesn't fix the array on the heap and lets garbage collection move it around. That's good as I don't want to impede the garbage collector from working effectively. However, the garbage collector runs on a separate thread, and when it is active all the other threads are stopped while the objects on the heap are compacted.

Supposed I had the following code:

interior_ptr<unsigned char> sourceBufferPtr = reinterpret_cast<interior_ptr<unsigned char>>(&sourceBuffer[0]) + sourceOffset;

The code should runs like this, for example:

  1. &sourceBuffer[0] returns the address of the first item in the array: 32.
  2. sourceOffset: 8.
  3. reinterpret_cast<interior_ptr<unsigned char>>(&sourceBuffer[0]) casts the address to an interior_ptr<unsigned char>, which gets added to sourceOffset.
  4. sourceBufferPtr should be equal to…
    • 40 if the garbage collector did not move the array.
    • 24 if the garbage collector moved the array to a location like 16.
    • of 40 if the garbage collector moved the array between steps 3 and 4, so the location of the array would be updated to 16 after step 3, but the result assigned to sourceBufferPtr would still be 40.

Am I correct to assume that the garbage collector could stop the thread between steps 3 and 4 and possibly assign the wrong value to sourceBufferPtr or does the Common Language Runtime somehow know how to ensure the entire statement is atomic/value is correct? What is safe to do with interior_ptr<typename>?

Upvotes: 3

Views: 791

Answers (1)

usr
usr

Reputation: 171206

Am I correct to assume that the garbage collector could stop the thread between steps 3 and 4 and possibly assign the wrong value to sourceBufferPtr?

Yes, because your code is incorrect. By using reinterpret_cast after having obtained an unmaanged pointer to the array element you are introducing a window of opportunity for the GC to invalidate the pointer. You need to use interior_ptr without interruption like this:

interior_ptr<unsigned char> bufferPtr = &sourceBuffer[0];
interior_ptr<unsigned char> sourceBufferPtr = bufferPtr + sourceOffset;

In this new code, there are only ever interior_ptr's. Even the temporary on the right-hand-side of the second assignment is an interior_ptr.

Upvotes: 3

Related Questions