www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is it possible to modify shared struct array in a function.

reply Sudhi <sudheendra.malli gmail.com> writes:
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
Feb 07 2019
parent reply Arun Chandrasekaran <aruncxy gmail.com> writes:
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
Feb 07 2019
parent reply Sudhi <sudheendra.malli gmail.com> writes:
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
Feb 07 2019
next sibling parent Arun Chandrasekaran <aruncxy gmail.com> writes:
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.
Feb 07 2019
prev sibling parent reply Jerry <labuurii gmail.com> writes:
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.
Feb 07 2019
parent reply Eduard Staniloiu <edi33416 gmail.com> writes:
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
Feb 08 2019
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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
Feb 08 2019