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.
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
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