Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Usage of ConcurrentQueue<StrongBox<T>>

I am basically looking for a container of image collections acquired from camera in a thread. Since ConcurrentQueue is thread-safe, I wanted to use it. But while debugging my code, I found this article saying

If the elements are small, you’ll probably never notice this. If, however, the elements hold on to large resources (e.g. each element is a huge image bitmap), it’s possible you could see the impact of this (one workaround is to queue a wrapper object, e.g. have a ConcurrentQueue<StrongBox<T>> rather than a ConcurrentQueue<T>, and null out the wrapper’s reference to the T value after the wrapper has been dequeued).

As far as I can see, StrongBox is a kind of wrapper for original value. Does that mean I have to store another collection of the images?

So I am looking for an usage or an example of ConcurrentQueue<StrongBox<T>>. Only thing I found from google is this code.

like image 852
Tae-Sung Shin Avatar asked Nov 28 '12 18:11

Tae-Sung Shin


1 Answers

The reminder of the dangers of premature optimization are in the comments, so I will address the semantics of what's going on here.

Like the article points out, the ConcurrentQueue can hold on to references of some things that have already gone through it. I learned it as 'a few dozen' and the article says it is no more than 31, which seems to gel pretty nicely. If the queue is tracking big objects, like your 2000x2000 Bitmaps, that can theoretically become a problem. It depends on what the rest of your program is doing, of course.

Wrapping it in a StrongBox<T> helps because the only thing StrongBox does is hold onto a reference to something else. Therefore, a StrongBox has a very tiny footprint, and whatever it holds will go out of scope and (theoretically) get GC'd quicker.

Since StrongBox has all the content of diet soda, you're kind of overthinking its usage. You literally just load up the Value field with some T and then reference it later. It looks a little like this:

var boxedBitmap = new StrongBox<Bitmap>(new Bitmap(1,1));
var bitmap = boxedBitmap.Value;

Or alternatively:

var boxedBitmap = new StrongBox<Bitmap>();
boxedBitmap.Value = new Bitmap(1,1);
var bitmap = boxedBitmap.Value;

Seriously, the implementation of this class if you pop it open in Reflector is like 5 lines.

This being the case, your usage of ConcurrentQueue<T> is not really any different from the usage of ConcurrentQueue<StrongBox<T>>. You'll simply tack on .Value before you send the resource to its destination thread. This did help a company I worked for reduce the memory imprint of a massive multithreaded analysis service by quite a bit by simply passing around a reference to a deterministic tool instead of passing the entire tool around, but your mileage may vary - I am not clear on what ramifications it would have if you were passing something to be mutated and then used by something else.

like image 102
tmesser Avatar answered Sep 20 '22 00:09

tmesser