Passing a mapping by reference in CTRL [SOLVED]

Find and share HowTos to various installations / configurations!
5 posts • Page 1 of 1
fandersen
Posts:51
Joined: Tue Aug 26, 2014 12:39 pm

Passing a mapping by reference in CTRL [SOLVED]

Post by fandersen »

Hi together,

is it possible to pass a reference to a variable of type "mapping" to a function?

I am currently investigating some script at our client. Some function checks that a mapping was asynchronously updated by a callback of a dpQueryConnectAll. The function evaluating the mapping never sees an update.

I have put together this example code doing basically the same as the real script.

The debug output is always "999", but I expect it to change to "123" after about 1 second.

Code: Select all

mapping systems;

main()
{
  mapping m;
  
  systems["Test"] = m;
  systems["Test"]["value"] = 999;

  startThread("CheckMapping", systems["Test"]);
  delay(1,0);
  
  systems["Test"]["value"] = 123;
}

void CheckMapping(mapping m)
{
  while(true)
  {
    delay(1,0);
    DebugTN("Check", m);
  }
}
I have found the following Knowlege Base entry with an example, but it was not working for me. CTRL alway creates a deep copy of the passed variable.

How to avoid copy of string variables, mappings and dyn arrays at function call?
https://www.winccoa.com/knowledge-base/ ... -call.html

But changing the function "CheckMapping" to the following does not change the behaviour. CTRL still makes a deep copy of the mapping.

Or am I mistaken?

Code: Select all

void CheckMapping(mapping &m)
{
  while(true)
  {
    delay(1,0);
    DebugTN("Check", m);
  }
BR/Florian
Last edited by fandersen on Thu Jan 26, 2023 2:08 pm, edited 1 time in total.

dbindernagel
Posts:161
Joined: Mon Feb 23, 2015 1:34 pm

Re: Passing a mapping by reference in CTRL

Post by dbindernagel »

Passing a variable by reference is working. Check this code:

Code: Select all

mapping systems;

main(mapping event)
{
  systems["Test"] = makeMapping();
  systems["Test"]["value"] = 999;

  DebugN(systems);
  changeValue(123, systems["Test"]);
  // startThread("changeValue", 123, systems["Test"]);
  DebugN(systems);
}


void changeValue(string value, mapping &m)
{
  m["value"] = value;
}

The problem is that the thread is making a local copy of the variable that is not changed outside of the thread.

In , for example, C# you would have the same problem and might have to declare the variable as volatile.
https://learn.microsoft.com/en-us/dotne ... s/volatile

Not sure if there is a way to do this in CONTROL.

gschijndel
Posts:376
Joined: Tue Jan 15, 2019 3:12 pm

Re: Passing a mapping by reference in CTRL

Post by gschijndel »

You could use a shared pointer to pass the variable to the thread

fandersen
Posts:51
Joined: Tue Aug 26, 2014 12:39 pm

Re: Passing a mapping by reference in CTRL

Post by fandersen »

dbindernagel wrote: ↑ Wed Jan 25, 2023 1:16 pm The problem is that the thread is making a local copy of the variable that is not changed outside of the thread.
OK, I am glad that I've chosen this example as I spawn a new thread explicitly. In the real script, a callback (of dpQueryConnectAll) does the update of the mapping, which executes in a separate thread but it is not as visible in the code.

Now, I have changed the script to accesses the global variable directly and not pass it to the function as an argument anymore, which is working fine.

fandersen
Posts:51
Joined: Tue Aug 26, 2014 12:39 pm

Re: Passing a mapping by reference in CTRL

Post by fandersen »

gschijndel wrote: ↑ Wed Jan 25, 2023 2:07 pm You could use a shared pointer to pass the variable to the thread
Yes, shared pointers work! Thank you!

Code: Select all

mapping systems;

main()
{  
  systems["Test"] = new mapping();
  systems["Test"]["value"] = 999;
  
  shared_ptr<mapping> ptr = systems["Test"];
  
  startThread("CheckMapping", ptr);
  
  delay(1,0);
  
  systems["Test"]["value"] = 123;
}

void CheckMapping(shared_ptr<mapping> mappingPtr)
{
  while(true)
  {
    DebugTN("Check", mappingPtr);
    delay(1,0);
  }
}

5 posts • Page 1 of 1