Jump to content
terran

Creating multiple threads in a DLL

Recommended Posts

Hi! When I try to create a multiple threads in a DLL, they are probably running not in parallel, but sequential, and using only a single CPU core. Is it possible to make it to use multiple CPU cores?

My "DLL" is a plugin for third-party app, and i have no idea what does the App with the DLL.

 

library whatever;

{$IFDEF FPC}
  {$MODE delphiunicode}
{$ENDIF}

{$R *.res}
{$IFDEF WIN64}
  {$EXTENSION 'wdx64'}
{$ENDIF}
{$IFDEF WIN32}
  {$EXTENSION 'wdx'}
{$ENDIF}
{zzz$SetPEOptFlagszzz $160}

uses
  SysUtils,
  Windows,
  Classes,
  contplug,
  RTLConsts;

const
  cFieldsNames: array [0..0] of AnsiString = ('Data');

  cFieldsTypes: array [0..High(cFieldsNames)] of Integer =
    (ft_Numeric64);


  DetectStr = 'EXT="JPG"';

type
  TLastInfo = record
    FileName: string;
    hash:int64;
  end;

type TProcessFile = class
  private
    type TThreadx = class(TThread)
      private
      protected
        procedure Execute; override;
      public
        is_running:boolean;
      end;
  public
   threadx:array{[1..NUM_THREADS]} of tthreadx;
   function ProcessFile(const FileName: UnicodeString; FieldIndex, UnitIndex: Integer): Boolean;
  end;

var
  RTL: TRTLCriticalSection;
  LastInfo: TLastInfo;
  ProcessFileVar:TProcessFile;
var NUM_THREADS:integer=10;

procedure TProcessFile.TThreadx.Execute;
begin
// dddddddd

is_running:=false;
end;

function TProcessFile.ProcessFile(const FileName: UnicodeString; FieldIndex, UnitIndex: Integer): Boolean;
var
 a:integer;
 is_finished:boolean;
begin
  Result := false;
  try
    if LastInfo.FileName <> FileName then
    begin
        LastInfo := Default(TLastInfo);
        LastInfo.FileName := FileName;
       try
          setlength(threadx,NUM_THREADS);
          for a:=0 to NUM_THREADS-1 do
            begin
            threadx[a]:=TThreadx.Create(true);
            threadx[a].Priority:=tpLower;
            threadx[a].FreeOnTerminate:=false;
            threadx[a].is_running:=true;
            if threadx[a].Suspended then threadx[a].Resume;
            sleep(0);
            end;
            repeat
            is_finished:=true;
            for a:=0 to NUM_THREADS-1 do
              begin
              if threadx[a].is_running then is_finished:=false;
              sleep(0);
              end;
            until is_finished=true;
          for a:=0 to NUM_THREADS-1 do
            begin
            threadx[a].Free;
            end;

       finally
       end;
        Result := true;
    end;
  except
    Result := False;
  end;
end;

function ContentGetSupportedField(FieldIndex: Integer; FieldName: PAnsiChar;
  Units: PAnsiChar; MaxLen: Integer): Integer; stdcall;
var
  Str: AnsiString;
  I: Integer;
begin
  if FieldIndex in [0..High(cFieldsNames)] then
  begin
    StrCopy(Units,'');
    StrLCopy(FieldName, PAnsiChar(cFieldsNames[FieldIndex]), MaxLen - 1);
    Result := cFieldsTypes[FieldIndex];
    StrLCopy(Units, PAnsiChar(''), MaxLen - 1);
    //for I := Low(cWebpEncodingString) to High(cWebpEncodingString) do
    //  Str := cWebpEncodingString[I] + '|';
    //if FieldIndex = 2 then
    //  StrLCopy(Units, PAnsiChar(Str), MaxLen - 1);
  end else
    Result := ft_NoMoreFields;
end;

function GetValueW(FileName: PWideChar; FieldIndex, UnitIndex: Integer;
  FieldValue: PByte; MaxLen, Flags: Integer): Integer;
var
  AFileName: string;
begin
  Result := ft_FieldEmpty;

  AFileName := FileName;
  if Length(AFileName) > 256 then
    if Pos('\\', AFileName) > 0 then
      AFileName := '\\?\UNC\' + Copy(AFileName, 3, Length(AFileName) - 2)
    else
      AFileName := '\\?\' + AFileName;

  if not FileExists(AFileName) then
    Exit;

  try
    ProcessFileVar:=TProcessFile.Create;
  try
    if not ProcessFileVar.ProcessFile(AFileName, FieldIndex, UnitIndex) then
      Exit;
  except
    Exit;
  end;
  finally
    ProcessFileVar.Free;
  end;

  case FieldIndex of
    0: PInt64(FieldValue)^ := LastInfo.hash;
  end;

  if FieldIndex in [0 .. High(cFieldsNames)] then
    Result := cFieldsTypes[FieldIndex]
  else
    Result := ft_fieldempty;
end;

function ContentGetValueW(FileName: PWideChar; FieldIndex, UnitIndex: Integer;
  FieldValue: PByte; MaxLen, Flags: Integer): Integer; stdcall;
begin
  if (Flags and CONTENT_DELAYIFSLOW > 0) then
  begin
    Result := FT_DELAYED;
    Exit;
  end;

  EnterCriticalSection(RTL);
  try
    Result := GetValueW(FileName, FieldIndex, UnitIndex, FieldValue, MaxLen, Flags);
  finally
    LeaveCriticalSection(RTL);
  end;
end;

function ContentGetValue(FileName: PAnsiChar; FieldIndex, UnitIndex: Integer;
  FieldValue: PByte; MaxLen, Flags: Integer): Integer; stdcall;
begin
  Result := ContentGetValueW(PWideChar(WideString(AnsiString(FileName))),
    FieldIndex, UnitIndex, FieldValue, MaxLen, Flags)
end;

procedure ContentGetDetectString(DetectString: PAnsiChar; MaxLen: integer); stdcall;
begin
  StrLCopy(DetectString, PAnsiChar(DetectStr), MaxLen - 1);
end;

procedure ContentSetDefaultParams(dps: PContentDefaultParamStruct); stdcall;
begin
end;

procedure DLLEntryProc;
begin
  DeleteCriticalSection(RTL);
end;

exports
  ContentGetDetectString,
  ContentGetSupportedField,
  ContentGetValue,
  ContentGetValueW;
  //ContentSetDefaultParams;

begin
  InitializeCriticalSectionAndSpinCount(RTL, 4000);
  DisableThreadLibraryCalls(HInstance);
  //Dll_Process_Detach_Hook := @DLLEntryProc;
  //DllProc := @DLLEntryProc;
end.

 

Edited by terran

Share this post


Link to post

We don't know what your code does, and how it interacts with its host. Nobody can answer your question with the amount of information provided here. 

Share this post


Link to post
42 minutes ago, terran said:

When I try to create a multiple threads in a DLL, they are probably running not in parallel, but sequential, and using only a single CPU core.

Sounds like you (or the host app) are not actually creating new threads to call your DLL functions, instead you/it are just calling your DLL functions in the context of an existing thread.

42 minutes ago, terran said:

Is it possible to make it to use multiple CPU cores?

Anything is possible.

42 minutes ago, terran said:

My "DLL" is a plugin for third-party app, and i have no idea what does the App with the DLL.

Without seeing your actual DLL code, and without seeing some code/documentation about the host app's plugin interface, how do you expect anyone to help you?

Share this post


Link to post

I have added the code to the first post.

The plugin interface: https://ghisler.github.io/WDX-SDK/contents.htm

 

Sorry if I don't specified the info. Because if i sure that it is written correctly, there is no need to specify the code, and if it's impossible, then, too.

Edited by terran

Share this post


Link to post

Your thread class Execute method is basically empty. Is there any other code in there you didn't show? If not then that is the reason your code is running sequentially, as threads don't do anything. Also using lower priority for threads can make threads wait longer to get the CPU slice. 

Share this post


Link to post

Soorry, probabiy it is executing too fast, so I could not notice that.

And the slowest part cannot be paralleled.

Edited by terran

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×