Mutex-Programmierung in QT

Alles rund um die Programmierung mit Qt
Antworten
Peach
Beiträge: 1
Registriert: 2. September 2010 13:26

Mutex-Programmierung in QT

Beitrag von Peach »

Hallo zusammen

Wir portieren zur Zeit eine Applikation aus Delphi nach QT/C++.
Damit das ganze später möglichst Plattform-Unabhängig ist, darf keine WinAPI benutzt werden.

Damit ich mehrere Threads synchronisieren kann, benötige ich ja sogenannte 'Mutex'.
Die Delphi Version setzt voll und ganz auf die WinAPI.

Meine Aufgabe ist es, das ganze nun in C++/QT umzusetzen.

Der Delphi-Code sieht folgendermassen aus:

Code: Alles auswählen

// DELPHI
unit IPCtools;

interface
uses
  SysUtils, Classes, Windows;

{ TEvent }

{ This class encapsulates the concept of a Win32 event (not to be
  confused with Delphi events), see "CreateEvent" in the Win32
  reference for more information }

type

{ THandledObject }

{ This is a generic class for all encapsulated WinAPI's which need to call
  CloseHandle when no longer needed.  This code eliminates the need for
  3 identical destructors in the TEvent, TMutex, and TSharedMem classes
  which are descended from this class. }

  THandledObject = class(TObject)
  protected
    FHandle: THandle;
  public
    destructor Destroy; override;
    property Handle: THandle read FHandle;
  end;

  TEvent = class(THandledObject)
  public
    constructor Create(const Name: string; Manual: Boolean);
    procedure Signal;
    procedure Reset;
    function Wait(TimeOut: Integer): Boolean;
  end;


{ TMutex }

{ This class encapsulates the concept of a Win32 mutex.  See "CreateMutex"
  in the Win32 reference for more information }

  TMutex = class(THandledObject)
  public
    constructor Create(const Name: string);
    function Get(TimeOut: Integer): Boolean;
    function Release: Boolean;
  end;

{ TSharedMem }

{ This class simplifies the process of creating a region of shared memory.
  In Win32, this is accomplished by using the CreateFileMapping and
  MapViewOfFile functions. }

  TSharedMem = class(THandledObject)
  private
    FName: string;
    FSize: Integer;
    FCreated: Boolean;
    FFileView: Pointer;
  public
    constructor Create(const Name: string; Size: Integer);
    destructor Destroy; override;
    property Name: string read FName;
    property Size: Integer read FSize;
    property Buffer: Pointer read FFileView;
    property Created: Boolean read FCreated;
  end;


implementation


procedure Error(const Msg: string);
begin
  raise Exception.Create(Msg);
end;

{ THandledObject }

destructor THandledObject.Destroy;
begin
  if FHandle <> 0 then
    CloseHandle(FHandle);
end;


{ TEvent }

constructor TEvent.Create(const Name: string; Manual: Boolean);
begin
  FHandle := CreateEvent(nil, Manual, False, PChar(Name));
  if FHandle = 0 then abort;
end;

procedure TEvent.Reset;
begin
  ResetEvent(FHandle);
end;

procedure TEvent.Signal;
begin
  SetEvent(FHandle);
end;

function TEvent.Wait(TimeOut: Integer): Boolean;
begin
  Result := WaitForSingleObject(FHandle, TimeOut) = WAIT_OBJECT_0;
end;

{ TMutex }

constructor TMutex.Create(const Name: string);
begin
  FHandle := CreateMutex(nil, False, PChar(Name));
  if FHandle = 0 then abort;
end;

function TMutex.Get(TimeOut: Integer): Boolean;
begin
  Result := WaitForSingleObject(FHandle, TimeOut) = WAIT_OBJECT_0;
end;

function TMutex.Release: Boolean;
begin
  Result := ReleaseMutex(FHandle);
end;

{ TSharedMem }

constructor TSharedMem.Create(const Name: string; Size: Integer);
begin
  try
    FName := Name;
    FSize := Size;
    { CreateFileMapping, when called with $FFFFFFFF for the hanlde value,
      creates a region of shared memory }
    FHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0,
        Size, PChar(Name));
    if FHandle = 0 then abort;
    FCreated := GetLastError = 0;
    { We still need to map a pointer to the handle of the shared memory region }
    FFileView := MapViewOfFile(FHandle, FILE_MAP_WRITE, 0, 0, Size);
    if FFileView = nil then abort;
  except
    Error(Format('Error creating shared memory %s (%d)', [Name, GetLastError]));
  end;
end;

destructor TSharedMem.Destroy;
begin
  if FFileView <> nil then
    UnmapViewOfFile(FFileView);
  inherited Destroy;
end;

{ IPC Classes }




end.
So, würde ich 1zu1 die Definition des Codefiles übersetzen sollte dies ja ungefähr so aussehen:

Code: Alles auswählen

#ifndef IPCTOOLS_H
#define IPCTOOLS_H

#include <QMutex>
#include <QObject>
#include <QPointer>
#include <QString>


class THandledObject : public QObject{

public:
    THandledObject();
    ~THandledObject();
    HANDLE FHandle() { return _FHandle; }

protected:
    HANDLE _FHandle;

};


class TEvent : public THandledObject{
public:
    TEvent(const char* Name, bool Manual);
    void Signal();
    void Reset();
    bool Wait(int TimeOut);

};


class TMutex : public THandledObject{
public:
    TMutex(const char* Name);
    bool Get(int TimeOut);
    bool Release();
};


class TSharedMem : public THandledObject{
public:
    TSharedMem(const char* Name, int Size);
    ~TSharedMem();
    const char* Name() { return FName; }
    int Size() { return FSize; }
    bool Created() { return FCreated; }
    QPointer Buffer() { return FFPointer; }

private:
    const char * FName;
    int FSize;
    bool FCreated;
    QPointer FFileView;

};

#endif // IPCTOOLS_H
Wie schon erwähnt setzt die Implementierung nun komplett auf WinAPI - was ich hier nicht darf.

FHandle kann ich denk ich mal als QMutex umsetzen.
Das Handle wird in Delphi als Mutex definiert.
Ebenfalls wird immer vom gleichen Handle der Status abgefragt.

TMutex.Get (Also ansich die WinApi Funktion 'WaitForSingleObject') gibt mir eigentlich zurück ob der Mutext locked/unlocked ist. Ist dies richtig so?
Wenn ja, könnte ich ja dann einfach einen getter setzen, der mir das Attribut: 'locked' zurückgibt.

TMutex.Release = Mutex.unlock()?


Beim Dekonstruktor der Klasse TSharedMem habe ich keine Ahnung was das bewirkt (WinAPI Funktion: UnmapViewOfFile).

Ich hoffe jemand von euch kann mir eine Antwort auf meine Fragen geben ;)


Gruss,
Peach
Antworten