179 lines
4.1 KiB
C++
179 lines
4.1 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*==============================================================================
|
|
IPC.h: Public interface for inteprocess communication module
|
|
==============================================================================*/
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "HAL/PlatformProcess.h"
|
|
|
|
namespace IPC
|
|
{
|
|
/**
|
|
* Example class for synchronized interprocess memory
|
|
*/
|
|
class FSynchronizedInterprocessMemory
|
|
{
|
|
/** Lock that guards access to the memory region */
|
|
FPlatformProcess::FSemaphore * Mutex;
|
|
|
|
/** Low-level memory region */
|
|
FPlatformMemory::FSharedMemoryRegion * Memory;
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
FSynchronizedInterprocessMemory(FPlatformProcess::FSemaphore * InMutex, FPlatformMemory::FSharedMemoryRegion * InMemory)
|
|
: Mutex(InMutex)
|
|
, Memory(InMemory)
|
|
{
|
|
check(Mutex);
|
|
check(Memory);
|
|
}
|
|
|
|
public:
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
~FSynchronizedInterprocessMemory()
|
|
{
|
|
if (Mutex)
|
|
{
|
|
FPlatformProcess::DeleteInterprocessSynchObject(Mutex);
|
|
Mutex = NULL;
|
|
}
|
|
|
|
if (Memory)
|
|
{
|
|
FPlatformMemory::UnmapNamedSharedMemoryRegion(Memory);
|
|
Memory = NULL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a new synchronized interprocess memory object
|
|
*/
|
|
static FSynchronizedInterprocessMemory * Create(const TCHAR* Name, SIZE_T Size)
|
|
{
|
|
FPlatformMemory::FSharedMemoryRegion * Memory = FPlatformMemory::MapNamedSharedMemoryRegion(Name, true,
|
|
FPlatformMemory::ESharedMemoryAccess::Read | FPlatformMemory::ESharedMemoryAccess::Write, Size);
|
|
|
|
if (!Memory)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
// initialize memory with zeroes
|
|
check(Memory->GetAddress());
|
|
FMemory::Memzero(Memory->GetAddress(), Memory->GetSize());
|
|
|
|
FPlatformProcess::FSemaphore * Mutex = FPlatformProcess::NewInterprocessSynchObject(Name, true);
|
|
if (!Mutex)
|
|
{
|
|
FPlatformMemory::UnmapNamedSharedMemoryRegion(Memory);
|
|
return NULL;
|
|
}
|
|
|
|
return new FSynchronizedInterprocessMemory(Mutex, Memory);
|
|
}
|
|
|
|
/**
|
|
* Opens existing synchronized interprocess memory object
|
|
*/
|
|
static FSynchronizedInterprocessMemory * OpenExisting(const TCHAR* Name, SIZE_T Size)
|
|
{
|
|
FPlatformMemory::FSharedMemoryRegion * Memory = FPlatformMemory::MapNamedSharedMemoryRegion(Name, false,
|
|
FPlatformMemory::ESharedMemoryAccess::Read | FPlatformMemory::ESharedMemoryAccess::Write, Size);
|
|
|
|
if (!Memory)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
FPlatformProcess::FSemaphore * Mutex = FPlatformProcess::NewInterprocessSynchObject(Name, false);
|
|
if (!Mutex)
|
|
{
|
|
FPlatformMemory::UnmapNamedSharedMemoryRegion(Memory);
|
|
return NULL;
|
|
}
|
|
|
|
return new FSynchronizedInterprocessMemory(Mutex, Memory);
|
|
}
|
|
|
|
/**
|
|
* Writes string to shared memory
|
|
*
|
|
* @param String string to write
|
|
* @param MaxMillisecondsToWait max milliseconds to wait (if 0, wait forever)
|
|
*
|
|
* @return true if was able to write
|
|
*/
|
|
bool Write(const FString& String, uint32 MaxMillisecondsToWait = 0)
|
|
{
|
|
check(Mutex);
|
|
check(Memory);
|
|
|
|
// acquire
|
|
if (!MaxMillisecondsToWait)
|
|
{
|
|
Mutex->Lock();
|
|
}
|
|
else
|
|
{
|
|
if (!Mutex->TryLock(MaxMillisecondsToWait * 1000000ULL)) // 1ms = 10^6 ns
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// we have exclusive ownership now!
|
|
TCHAR* RawMemory = reinterpret_cast< TCHAR* >(Memory->GetAddress() );
|
|
FCString::Strncpy(RawMemory, *String, Memory->GetSize());
|
|
|
|
// relinquish
|
|
Mutex->Unlock();
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Reads a string from shared memory
|
|
*
|
|
* @param String string to read into
|
|
* @param MaxMillisecondsToWait max milliseconds to wait (if 0, wait forever)
|
|
*
|
|
* @return true if read withing given time
|
|
*/
|
|
bool Read(FString& OutString, uint32 MaxMillisecondsToWait = 0)
|
|
{
|
|
check(Mutex);
|
|
check(Memory);
|
|
|
|
// acquire
|
|
if (!MaxMillisecondsToWait)
|
|
{
|
|
Mutex->Lock();
|
|
}
|
|
else
|
|
{
|
|
if (!Mutex->TryLock(MaxMillisecondsToWait * 1000000ULL)) // 1ms = 10^6 ns
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// we have exclusive ownership now!
|
|
const TCHAR* RawMemory = reinterpret_cast< const TCHAR* >( Memory->GetAddress() );
|
|
OutString = FString(RawMemory);
|
|
|
|
// relinquish
|
|
Mutex->Unlock();
|
|
|
|
return true;
|
|
}
|
|
};
|
|
}; // namespace IPC
|