Thread overview
Is it possible to modify shared struct array in a function.
Feb 08, 2019
Sudhi
Feb 08, 2019
Sudhi
Feb 08, 2019
Jerry
Feb 08, 2019
Eduard Staniloiu
Feb 09, 2019
Jonathan M Davis
February 08, 2019
I have a situation, where i want to modify a shared variable in a function. Something like below

struct Company
{
    string name;
    string location;
}

struct Racks
{
    int number;
    int location;
}

struct Metadata
{
    string name;
    Company[] companies;
    Racks[] racks;
}

struct Item
{
    Metadata met;
    int count;
}

shared (Item) item

void main()
{
   updateMetadata()
}

void updateMetadata()
{
   Company company;
   company.name = "Hello";
   company.location = "Bangalore";
   item.met.companies ~= company;
}

Compiler throws me error in last line for appending as below.

"cannot append type Metadata to type shared(Metadata[])".

Please let me know if there is a way to acheive this.

Thanks,
Sudhi


February 08, 2019
On Friday, 8 February 2019 at 04:13:39 UTC, Sudhi wrote:
> I have a situation, where i want to modify a shared variable in a function. Something like below
>
> struct Company
> {
>     string name;
>     string location;
> }
>
> struct Racks
> {
>     int number;
>     int location;
> }
>
> struct Metadata
> {
>     string name;
>     Company[] companies;
>     Racks[] racks;
> }
>
> struct Item
> {
>     Metadata met;
>     int count;
> }
>
> shared (Item) item
>
> void main()
> {
>    updateMetadata()
> }
>
> void updateMetadata()
> {
>    Company company;
>    company.name = "Hello";
>    company.location = "Bangalore";
>    item.met.companies ~= company;
> }
>
> Compiler throws me error in last line for appending as below.
>
> "cannot append type Metadata to type shared(Metadata[])".
>
> Please let me know if there is a way to acheive this.
>
> Thanks,
> Sudhi

Works fine for me with DMD64 D Compiler v2.083.1. https://run.dlang.io/is/RRM8GU

February 08, 2019
On Friday, 8 February 2019 at 04:30:23 UTC, Arun Chandrasekaran wrote:
> On Friday, 8 February 2019 at 04:13:39 UTC, Sudhi wrote:
>> I have a situation, where i want to modify a shared variable in a function. Something like below
>>
>> struct Company
>> {
>>     string name;
>>     string location;
>> }
>>
>> struct Racks
>> {
>>     int number;
>>     int location;
>> }
>>
>> struct Metadata
>> {
>>     string name;
>>     Company[] companies;
>>     Racks[] racks;
>> }
>>
>> struct Item
>> {
>>     Metadata met;
>>     int count;
>> }
>>
>> shared (Item) item
>>
>> void main()
>> {
>>    updateMetadata()
>> }
>>
>> void updateMetadata()
>> {
>>    Company company;
>>    company.name = "Hello";
>>    company.location = "Bangalore";
>>    item.met.companies ~= company;
>> }
>>
>> Compiler throws me error in last line for appending as below.
>>
>> "cannot append type Metadata to type shared(Metadata[])".
>>
>> Please let me know if there is a way to acheive this.
>>
>> Thanks,
>> Sudhi
>
> Works fine for me with DMD64 D Compiler v2.083.1. https://run.dlang.io/is/RRM8GU


My example code was wrong. Below is the right one.

struct Company
{
    string name;
    string location;
}

struct Racks
{
    int number;
    int location;
}

struct Metadata
{
    string name;
    Company[] companies;
    Racks[] racks;
}

struct Item
{
    Metadata[] met;
    int count;
}

shared (Item) item;

void main()
{
   updateMetadata();
}

void updateMetadata()
{
   Company company;
   company.name = "Hello";
   company.location = "Bangalore";
   item.met.companies ~= company;
   import std.stdio: writeln;
   writeln(item);
}

https://run.dlang.io/is/iem0PY

February 08, 2019
On Friday, 8 February 2019 at 04:51:08 UTC, Sudhi wrote:
> On Friday, 8 February 2019 at 04:30:23 UTC, Arun Chandrasekaran wrote:
>> [...]
>
>
> My example code was wrong. Below is the right one.
>
> struct Company
> {
>     string name;
>     string location;
> }
>
> struct Racks
> {
>     int number;
>     int location;
> }
>
> struct Metadata
> {
>     string name;
>     Company[] companies;
>     Racks[] racks;
> }
>
> struct Item
> {
>     Metadata[] met;
>     int count;
> }
>
> shared (Item) item;
>
> void main()
> {
>    updateMetadata();
> }
>
> void updateMetadata()
> {
>    Company company;
>    company.name = "Hello";
>    company.location = "Bangalore";
>    item.met.companies ~= company;
>    import std.stdio: writeln;
>    writeln(item);
> }
>
> https://run.dlang.io/is/iem0PY

`shared struct Metadata` should make it work.

Turtles (shared) all the way down.
February 08, 2019
On Friday, 8 February 2019 at 04:51:08 UTC, Sudhi wrote:
> On Friday, 8 February 2019 at 04:30:23 UTC, Arun Chandrasekaran wrote:
>> On Friday, 8 February 2019 at 04:13:39 UTC, Sudhi wrote:
>>> [...]
>>
>> Works fine for me with DMD64 D Compiler v2.083.1. https://run.dlang.io/is/RRM8GU
>
>
> My example code was wrong. Below is the right one.
>
> struct Company
> {
>     string name;
>     string location;
> }
>
> struct Racks
> {
>     int number;
>     int location;
> }
>
> struct Metadata
> {
>     string name;
>     Company[] companies;
>     Racks[] racks;
> }
>
> struct Item
> {
>     Metadata[] met;
>     int count;
> }
>
> shared (Item) item;
>
> void main()
> {
>    updateMetadata();
> }
>
> void updateMetadata()
> {
>    Company company;
>    company.name = "Hello";
>    company.location = "Bangalore";
>    item.met.companies ~= company;
>    import std.stdio: writeln;
>    writeln(item);
> }
>
> https://run.dlang.io/is/iem0PY

You have to cast away shared:

auto loc_item = cast(Item) item;
loc_item.met ~= m;
item = cast(shared) loc_item;

Just to be clear, this is not threadsafe and require a mutex if you do this other than as init in main.
February 08, 2019
On Friday, 8 February 2019 at 06:55:15 UTC, Jerry wrote:
> On Friday, 8 February 2019 at 04:51:08 UTC, Sudhi wrote:
>> On Friday, 8 February 2019 at 04:30:23 UTC, Arun Chandrasekaran wrote:
>>> On Friday, 8 February 2019 at 04:13:39 UTC, Sudhi wrote:
>>>> [...]
>>>
>>> Works fine for me with DMD64 D Compiler v2.083.1. https://run.dlang.io/is/RRM8GU
>>
>>
>> My example code was wrong. Below is the right one.
>>
>> struct Company
>> {
>>     string name;
>>     string location;
>> }
>>
>> struct Racks
>> {
>>     int number;
>>     int location;
>> }
>>
>> struct Metadata
>> {
>>     string name;
>>     Company[] companies;
>>     Racks[] racks;
>> }
>>
>> struct Item
>> {
>>     Metadata[] met;
>>     int count;
>> }
>>
>> shared (Item) item;
>>
>> void main()
>> {
>>    updateMetadata();
>> }
>>
>> void updateMetadata()
>> {
>>    Company company;
>>    company.name = "Hello";
>>    company.location = "Bangalore";
>>    item.met.companies ~= company;
>>    import std.stdio: writeln;
>>    writeln(item);
>> }
>>
>> https://run.dlang.io/is/iem0PY
>
> You have to cast away shared:
>
> auto loc_item = cast(Item) item;
> loc_item.met ~= m;
> item = cast(shared) loc_item;
>
> Just to be clear, this is not threadsafe and require a mutex if you do this other than as init in main.

You do not need to cast away shared. You had a couple of issues with your `updateMetadata()` function.

First of, `met` is an array, so you need to index it: your code `item.met.companies ~= company` becomes `item.met[0].companies ~= company`. This will compile, but throw a range error because you don't have any `Metadata` object in your `met` array.

I have typed below the revised form of your function

```
void updateMetadata()
{
   // create a Company instance. This must be shared
   shared Company company;
   company.name = "Hello";
   company.location = "Bangalore";

   // create a shared Metadata instance
   shared Metadata m;
   m.name = "m";

   // append m to the array of meta
   item.met ~= m;
   // append the company to the array of companies, for a given meta
   item.met[0].companies ~= company;

   import std.stdio: writeln;
   writeln(item);
}
```

The working version is at https://run.dlang.io/is/RvRKrU

Cheers,
Edi
February 08, 2019
On Friday, February 8, 2019 4:27:44 AM MST Eduard Staniloiu via Digitalmars- d-learn wrote:
> On Friday, 8 February 2019 at 06:55:15 UTC, Jerry wrote:
> > On Friday, 8 February 2019 at 04:51:08 UTC, Sudhi wrote:
> >> On Friday, 8 February 2019 at 04:30:23 UTC, Arun
> >>
> >> Chandrasekaran wrote:
> >>> On Friday, 8 February 2019 at 04:13:39 UTC, Sudhi wrote:
> >>>> [...]
> >>>
> >>> Works fine for me with DMD64 D Compiler v2.083.1. https://run.dlang.io/is/RRM8GU
> >>
> >> My example code was wrong. Below is the right one.
> >>
> >> struct Company
> >> {
> >>
> >>     string name;
> >>     string location;
> >>
> >> }
> >>
> >> struct Racks
> >> {
> >>
> >>     int number;
> >>     int location;
> >>
> >> }
> >>
> >> struct Metadata
> >> {
> >>
> >>     string name;
> >>     Company[] companies;
> >>     Racks[] racks;
> >>
> >> }
> >>
> >> struct Item
> >> {
> >>
> >>     Metadata[] met;
> >>     int count;
> >>
> >> }
> >>
> >> shared (Item) item;
> >>
> >> void main()
> >> {
> >>
> >>    updateMetadata();
> >>
> >> }
> >>
> >> void updateMetadata()
> >> {
> >>
> >>    Company company;
> >>    company.name = "Hello";
> >>    company.location = "Bangalore";
> >>    item.met.companies ~= company;
> >>    import std.stdio: writeln;
> >>    writeln(item);
> >>
> >> }
> >>
> >> https://run.dlang.io/is/iem0PY
> >
> > You have to cast away shared:
> >
> > auto loc_item = cast(Item) item;
> > loc_item.met ~= m;
> > item = cast(shared) loc_item;
> >
> > Just to be clear, this is not threadsafe and require a mutex if you do this other than as init in main.
>
> You do not need to cast away shared. You had a couple of issues with your `updateMetadata()` function.
>
> First of, `met` is an array, so you need to index it: your code `item.met.companies ~= company` becomes `item.met[0].companies ~= company`. This will compile, but throw a range error because you don't have any `Metadata` object in your `met` array.
>
> I have typed below the revised form of your function
>
> ```
> void updateMetadata()
> {
>     // create a Company instance. This must be shared
>     shared Company company;
>     company.name = "Hello";
>     company.location = "Bangalore";
>
>     // create a shared Metadata instance
>     shared Metadata m;
>     m.name = "m";
>
>     // append m to the array of meta
>     item.met ~= m;
>     // append the company to the array of companies, for a given
> meta
>     item.met[0].companies ~= company;
>
>     import std.stdio: writeln;
>     writeln(item);
> }
> ```
>
> The working version is at https://run.dlang.io/is/RvRKrU
>
> Cheers,
> Edi

Honestly, the fact that that code compiles is a bug. You're not supposed to be able to modify shared objects in a manner which isn't guaranteed to be atomic, because it's not thread-safe. The compiler catches it in a number of places, but there are many where it currently doesn't.

But regardless of whether the compiler allows such mutation, a mutex (or similar protection mechanism) needs to be used in order to make the code thread-safe.

- Jonathan M Davis