RTC Forums
May 19, 2024, 08:53:37 PM *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Login Register  
Pages: [1]
  Print  
Author Topic: Copy all values from one RtcRecord to another  (Read 5791 times)
HelgeLange
RTC Expired
*
Posts: 100


« on: July 18, 2015, 01:47:17 PM »

Hi Danijel,

my server architecture needs to copy everything that comes in in a remote function as param to a new call to another server (some kind of send through function). TRtcRecord.CopyOf doesn't help as it creates a new object, but I need to copy in am existing object.

Any ideas ? or is it always manual ?

Thanks in advance
Helge
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #1 on: July 18, 2015, 02:43:03 PM »

I'm sorry, but I do not understand your problem.

Regards,
Danijel
Logged
HelgeLange
RTC Expired
*
Posts: 100


« Reply #2 on: July 18, 2015, 03:23:36 PM »

Something like this, where I have code that makes a copy from one RtcRecord to another which already exists

original :

Quote
        aRec.asBoolean[STR_ADRESS_OK] := Param.asBoolean[STR_ADRESS_OK];
        aRec.asString[STR_ADRESS] := Param.asString[STR_ADRESS];
        aRec.asString[STR_CITY] := Param.asString[STR_CITY];
        aRec.asString[STR_COUNTRY] := Param.asString[STR_COUNTRY];
        aRec.asString[STR_COUNTRY_CODE] := Param.asString[STR_COUNTRY_CODE];
        aRec.asString[STR_POSTAL_CODE] := Param.asString[STR_POSTAL_CODE];
        aRec.asString[STR_REGION] := Param.asString[STR_REGION];
        aRec.asString[STR_STATE] := Param.asString[STR_STATE];
        aRec.asString[STR_STREET] := Param.asString[STR_STREET];
        aRec.asString[STR_STREET_NUMBER] := Param.asString[STR_STREET_NUMBER];

What I thought of is something like

Quote
procedure TMyObject.MyCall1Execute(Sender: TRtcConnection; Param: TRtcFunctionInfo; Result: TRtcValue);
  Fi := ClientModule1.prepare('MyCall'); // call to another server
  Fi.CopyFrom(Param);
  Fi.Call(nil)
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #3 on: July 18, 2015, 03:33:30 PM »

This should do the trick:

procedure TMyObject.MyCall1Execute(Sender: TRtcConnection; Param: TRtcFunctionInfo; Result: TRtcValue);
  ClientModule1.Data.asObject:=Param.CopyOf; // copy the entire "Param" object
  ClientModule1.Param.FunctionName:='MyCall'; // required only if "function name" has to be changed
  ClientModule1.Call(nil);

Regards,
Danijel
Logged
HelgeLange
RTC Expired
*
Posts: 100


« Reply #4 on: July 18, 2015, 03:51:50 PM »

thanks, I will try that at once
Logged
HelgeLange
RTC Expired
*
Posts: 100


« Reply #5 on: August 28, 2015, 04:03:55 PM »

Let's say I am inside a delayed call and have data to send back to the caller, how would I do that there ? I tried the following, but it raises later on an access violation

Code:
      pItem := TRtcRecord(pData^.FpNotifyList.Items[0]);
      Result.asRecord := TRtcRecord(pItem.copyOf);
      pData^.FpNotifyList.Delete(0);
      pItem.Free;

I have in the FpNotifyList a list of TRtcRecord, i'm taking the first one from the list and try to create a new copy of the record from it as result for the delayed call.

I'm doing anything wrong here ?

Thanks in adv. Helge

Edit : It works like a charm, the error was something else I forgot to change when I switched from packed records to TRtcRecord
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #6 on: August 28, 2015, 04:31:34 PM »

The explanation for the "asRecord" property in the HELP file says:
{ read: Access stored record / write: assign a copy of the source TRtcRecord }
In other words, this line will result in a memory leak:
Code:
Result.asRecord := TRtcRecord(pItem.copyOf);
If you want to assign a copy of pItem:TRtcValueObject to Result:TRtcValue, you can do it like this:
Code:
Result.asObject := pItem.copyOf;
Or, if you KNOW that "pItem" is a TRtcRecord, you can assign a copy to Result:TRtcValue like this:
Code:
Result.asRecord := TRtcRecord(pItem);
Either way will be fine and won't result in memory leaks nor Access Violations, provided that "pItem" is safe to be accessed during the assignment.

As for your Access Violation problem, it could be related to the way you are working with your "pData" and/or "FpNotifyList" objects in a multi-threaded environment. If you are simply using a TList which is being populated from a different thread, but are NOT using critical sections anywhere to secure access to that list, you will run into problems when more than one thread tries to access the list at the same time. And I don't see anything in your code snippet which would suggest a use of critical sections.

Best Regards,
Danijel Tkalcec
Logged
HelgeLange
RTC Expired
*
Posts: 100


« Reply #7 on: August 28, 2015, 08:17:51 PM »

thanks for the explanation.

to clarify fast : The access violation was my fault, not RTC, it had nothing to do with it, but the way I treated in another code the RtcRecord (before I had a delphi record and this code still used it as such).

pItem is a TRtcRecord, that I send from another thread but never acces it afterwards outside the code I showed. So that should be all good.

Code:
Result.asObject := pItem.copyOf;
this makes the copy and I free pItem directly after, as I don't need it anymore.

Code:
Result.asRecord := TRtcRecord(pItem);
this will use my current copy directly and RTC will free it ? So i don't free it myself ?

Thanks Smiley
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #8 on: August 28, 2015, 09:08:38 PM »

Well, not quite. Let me try to rephrase my reply.

The "CopyOf" method creates a copy, as well as an assignment to the "asResult" property, because of which the two lines below basically do the same thing, just in a different way:
Code:
Result.asObject := pItem.copyOf; // this assigns a copy of "pItem" to Result
Code:
Result.asRecord := TRtcRecord(pItem); // this ALSO assigns a copy of "pItem" to Result

If you want to assign the original "pItem" object and NOT a copy of that object (in which case the Result object would manage your object, so you should NOT destroy it yourself), you have to assign your object to the "asObject" property, like this:
Code:
Result.asObject:=pItem;

What you should NOT do, is assigning a "CopyOf" to the "asRecord" property, because that will create two copies, leaking one of them. That is what I was trying to point out in my original reply above. In other words, this line is WRONG, because it will result in a memory leak:
Code:
Result.asRecord := TRtcRecord(pItem.copyOf); // this assigns a copy of a copy of "pItem" to Result, "leaking" the 1st copy

Best Regards,
Danijel Tkaclec
Logged
HelgeLange
RTC Expired
*
Posts: 100


« Reply #9 on: August 29, 2015, 01:01:25 AM »

Ok, now I get it Smiley
I will use this fire-and-forget solution

Code:
Result.asObject:=pItem;

Thanks a lot, Danijel!
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.026 seconds with 16 queries.