Passing large or complex data structures to threads

Simen Kjaeraas simen.kjaras at gmail.com
Mon May 27 14:33:42 PDT 2013


On Mon, 27 May 2013 14:08:12 +0200, Joseph Rushton Wakeling  
<joseph.wakeling at webdrake.net> wrote:

> On 05/26/2013 05:59 PM, Ali Çehreli wrote:
>> On 05/26/2013 05:38 AM, Simen Kjaeraas wrote:
>>
>>
>>>      Tuple!(size_t, size_t)[][] data = createData();
>>>      immutable dataImm = assumeUnique(data);
>>>      data = null; // Simply to ensure no mutable references exist.
>>
>> The last line is not needed. assumeUnique already does that. :)
>
> That's fantastic, thank you both very much.  Does that also work for  
> arbitrary
> data structures (e.g. also associative arrays, complex structs/classes  
> etc.)?

Absolutely. So long as your code does not squirrel away other, mutable
references to the data, assumeUnique is perfectly safe.


> Related question -- assume that I now want to store that immutable data  
> inside a
> broader storage class, but I want that storage class to be agnostic as to
> whether the data is immutable, const or mutable.
>
> Something like this:
>
> 	class MyDataStore
> 	{
> 		float[] someData;
> 		uint[] someMoreData;
> 		Tuple!(size_t, size_t)[][] importedData;
>
> 		this(float[] sd, uint[] smd, Tuple!(size_t, size_t)[][] id)
> 		{
> 			someData = sd;
> 			someMoreData = smd;
> 			importedData = id;
> 		}
> 	}
>
> ... which of course fails if you try passing it immutable data for any  
> of the
> parameters.  So, is there a way to make this broader storage class
> type-qualifier-agnostic?
>
> I guess applying "inout" to the input parameters is necessary, but it's  
> clearly
> not sufficient as the code then fails when trying to assign to the class'
> internal variables.

A few questions:

Why use a class? Will MyDataStore be subclassed?

Will you have some instances of MyDataStore that will be mutated, and
others that will always stay the same?

If the answer was yes, will these be in the same array?


Short answer: If you will have mixed arrays, no. There's no way to make
that safe. If you don't have mixed arrays, there are ways.

This will work:

import std.stdio : writeln;
import std.exception : assumeUnique;
import std.typecons : Tuple, tuple;

class MyDataStore
{
     float[] someData;
     uint[] someMoreData;
     Tuple!(size_t, size_t)[][] importedData;

     inout this(inout float[] sd, inout uint[] smd, inout Tuple!(size_t,  
size_t)[][] id)
     {
         someData = sd;
         someMoreData = smd;
         importedData = id;
     }
}

void main( ) {
     float[] sdMut = [1,2,3];
     uint[] smdMut = [4,5,6];
     Tuple!(size_t, size_t)[][] idMut = [[tuple(0u, 0u), tuple(0u,  
1u)],[tuple(1u, 0u), tuple(1u, 1u)]];
     immutable float[] sdImm = [1,2,3];
     immutable uint[] smdImm = [4,5,6];
     immutable Tuple!(size_t, size_t)[][] idImm = [[tuple(0u, 0u),  
tuple(0u, 1u)],[tuple(1u, 0u), tuple(1u, 1u)]];

     auto a = new MyDataStore(sdMut, smdMut, idMut);
     immutable b = new immutable MyDataStore(sdImm, smdImm, idImm);
     const c = new const MyDataStore(sdImm, smdMut, idImm);
}

(Tested with 2.063 beta, it's possible there are complications in 2.062)

-- 
Simen


More information about the Digitalmars-d-learn mailing list