Recent

Author Topic: Passing an array to a Threadfunction.  (Read 5186 times)

jddev

  • Newbie
  • Posts: 3
Passing an array to a Threadfunction.
« on: June 12, 2014, 08:48:27 pm »
Hi, folks.
I'm not newto Pascal programming, but to thread-programming.

I want to pass an Array filled with Byte-values to a threaded function, but al i tried doe'nt  work, yet.
Here is a minimal example of my current try:

{$mode obfpc}
program miniexp;

uses
  {$ifdef UNIX} cthreads; {$endif}
 
type
  TByteArray = Array of Byte;
  PByteArray = ^TByteArray;
  TArrIndex = Byte;

var
  AnArray : TByteArray; (* Array to pass *)
  ArrAddr : PByteArray; (* addres of AnArray *)
  lc :  TArrIndex; (* loopcounter *)
  thisd : TThreadid; (* threadid *)

(*this function just pronts the passed array.*)
function miniexp(pt : pointer) : ptrint;
var
  toPrint : TByteArray;
  idx : TArrIndex;
begin
  toPrint :=  PByteArray(pt);

  for idx := low(toPrint) to high(toPrint) do
  begin
     writeln(toPrint[idx]);
  end;

   miniexp := 0;
   EndThread;
end;
 
Begin
  SetLength(AnArray, 10); (*set array to proper length*)

  (* fill the array*)
  randomize;
   for lc := low(AnArray) to high(AnArray) do
   begin
      AnArray[lc] := (random(521) mod 256);
   end; 
 
   (*The following works, but does'nt pass the full array. *)
    ArrAddr := @AnArray;
    thid := BeginThread(TThreadfunc(@miniexp), pointer(ArrAddr));
    WaitForThreadTerminate(thid, 1000000);

End.
(*of miniexample.*)

Any suggestions arewelcome.

With greets and respect,
jddev.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11452
  • FPC developer.
Re: Passing an array to a Threadfunction.
« Reply #1 on: June 12, 2014, 08:59:28 pm »
The best advise would probably to not use automated types for pointer tricks.  Probably the main thread deallocates the memory behind your back because it is no longer used. Allocate your memory buffer with getmem.

A standard trick is also to put the automated type inside a record or class, and pass the pointer to the record or class to the thread.

I would also advise you to use tthread.

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: Passing an array to a Threadfunction.
« Reply #2 on: June 12, 2014, 09:06:50 pm »
Your code compiles here (FPC 2.7.1), with only a small change:
Code: [Select]
program miniexp;
{$mode objfpc}

uses
  {$ifdef UNIX} cthreads; {$endif}
 
type
  TByteArray = Array of Byte;
  PByteArray = ^TByteArray;
  TArrIndex = Byte;

var
  AnArray : TByteArray; (* Array to pass *)
  ArrAddr : PByteArray; (* addres of AnArray *)
  lc :  TArrIndex; (* loopcounter *)
  thid : TThreadid; (* threadid *)

(*this function just pronts the passed array.*)
function miniexp(pt : pointer) : ptrint;
var
  toPrint : TByteArray;
  idx : TArrIndex;
begin
  toPrint :=  PByteArray(pt)^;

  for idx := low(toPrint) to high(toPrint) do
  begin
     writeln(toPrint[idx]);
  end;

   miniexp := 0;
  // EndThread;
end;
 
Begin
  SetLength(AnArray, 10); (*set array to proper length*)

  (* fill the array*)
  randomize;
   for lc := low(AnArray) to high(AnArray) do
   begin
      AnArray[lc] := (random(521) mod 256);
   end; 
 
   (*The following works, but does'nt pass the full array. *)
    ArrAddr := @AnArray;
    thid := BeginThread(TThreadfunc(@miniexp), pointer(ArrAddr));
    WaitForThreadTerminate(thid, 1000000);
   
   
End.

I commented EndThread; in the function. With EndThread; it worked too but it gave a memory leak.
Also correction in this line:
Code: [Select]
toPrint :=  PByteArray(pt)^;
« Last Edit: June 12, 2014, 09:08:39 pm by Blaazen »
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Passing an array to a Threadfunction.
« Reply #3 on: June 13, 2014, 03:26:26 pm »
Code: [Select]
type
  TByteArray = Array of Byte;
  //PByteArray = ^TByteArray;
This may simplify the idea a little, you know the TByteArray is already a pointer because it is dynamic array.

If you do:
Code: [Select]
var arr: TByteArray;
begin
  setlength(add, 99999999999);
  someFunc(arr);
It will only pass a pointer to someFunc(). (No data is copied for parameter.)
« Last Edit: June 13, 2014, 03:27:57 pm by User137 »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11452
  • FPC developer.
Re: Passing an array to a Threadfunction.
« Reply #4 on: June 14, 2014, 12:39:00 am »
Your code compiles here (FPC 2.7.1), with only a small change:

Your code is unsafe, relying on implementation dependent features:

Code: [Select]
 
   (*The following works, but does'nt pass the full array. *)
    ArrAddr := @AnArray;
    thid := BeginThread(TThreadfunc(@miniexp), pointer(ArrAddr));

At this point miniexp can be deallocated, while the new thread might still access it.
Code: [Select]
    WaitForThreadTerminate(thid, 1000000);
   

 

TinyPortal © 2005-2018