공유 메모리 개체 생성을 위해 C ++ 클래스 템플릿에 할당자를 추가
-
19-09-2019 - |
문제
요컨대, 내 질문은 다음과 같습니다. 수업이 있다면 MyClass<T>
, 당신이 가진 사례를 지원하기 위해 클래스 정의를 어떻게 변경할 수 있습니까? MyClass<T, Alloc>
, STL 벡터가 제공하는 방식과 유사합니다.
공유 메모리에 대한 할당자를 지원하려면이 기능이 필요합니다. 구체적으로, 공유 메모리에서 링 버퍼를 구현하려고합니다. 현재 다음과 같은 CTOR가 있습니다.
template<typename ItemType>
SharedMemoryBuffer<ItemType>::SharedMemoryBuffer( unsigned long capacity, std::string name )
어디 ItemType
버퍼의 각 슬롯에 배치 할 데이터의 유형입니다.
이제 메인 프로그램에서 버퍼를 만들 때 이것은 화려하게 작동합니다.
SharedMemoryBuffer<int>* sb;
sb = new SharedMemoryBuffer<int>(BUFFER_CAPACITY + 1, sharedMemoryName);
그러나이 경우 버퍼 자체는 공유 메모리에서 생성되지 않으므로 다른 프로세스에 액세스 할 수 없습니다. 내가하고 싶은 것은
typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocator;
typedef SharedMemoryBuffer<int, ShmemAllocator> MyBuffer;
managed_shared_memory segment(create_only, "MySharedMemory", 65536);
const ShmemAllocator alloc_inst (segment.get_segment_manager());
MyBuffer *mybuf = segment.construct<MyBuffer>("MyBuffer")(alloc_inst);
그러나 클래스 템플릿에 명시 적 할당자를 추가하는 방법을 모르겠습니다.
해결책
내가 혼란스럽게 만드는 것은, Shm (SharedMemory)에 객체를 할당하거나 만들어야하는 이유는 예를 들어 크기 65536 바이트의 공유 메모리를 예약 한 다음 주소에서 공유 메모리를 얻는다고 가정 해 봅시다. 0x1ABC0000
, 예약 성공이 있으면 무료로 직접 액세스 할 수있는 메모리 공간이 있습니다. 0x1ABC0000 to 0x1ABCFFFF
.
그런 다음 애플리케이션이 크기의 SHM에서 객체를 "할당"해야하는 경우 sizeof(SHMObject)
, 그리고 당신의 메모리 매니저는 그 주소를 참조하십시오 0x1ABC0000+0x1A
무료이므로 메모리 관리자가 반환해야합니다 0x1ABC001A
가치와 마크 ( 0x1ABC001A to 0x1ABC001A+sizeof(SHMObject) )
점령되었고, 당신은 단지 캐스팅하기 만하면됩니다. SHMObject* shmObjectPtr = (SHMObject*)(0x1ABC001A);
그리고 지정된 메모리 주소 범위에서 작동하는 자신의 사용자 정의 메모리 할당자가 있다고 가정합니다.
템플릿의 경우 SHM 링 버퍼가 어떻게 보이는지 이해하지 못하지만 SHM을 사용하기 전에 그렇게했는데 내 구현은 다음과 같습니다.
//memory SHM allocator
template<typename T> class ShmRingAllocator
{
protected:
void* baseAddress;
public:
ShmRingAllocator(void* baseAddress,int memSize);
void* allocate(); //this function do what I described earlier, or you can use placement new: new (baseAddress+offset)T;
}
//some kind of shared_ptr<> that handle object in SHM, this provides mechanishm to check is the pointer still valid in shm or not
template<typname T> ShmRingObjectPtr
{
protected:
T* object; //mapped address of object at current process
ShmBuffer* shm; //every object has pointer to which SHM does this pointer pointing at
public:
virtual T* operator->(); //operator overload to access T object
}
class ShmBuffer //base class for all kind of SHM buffer
{
protected:
std::string shmName;
void* shmBasePtr;
}
template<typename T,class A=ShmRingAllocator<T>> ShmRingBuffer : public ShmBuffer
{
protected:
A allocator;
public:
ShmRingObjectPtr<T> insert() //push one element to ring buffer
{
return ShmRingObjectPtr<T>((T*)this->allocator.allocate(),this);
}
}
`
다른 팁
나는 당신이 표준을 찾고 있다고 생각합니다 새로운 배치.
만약에 shm_addr
a void*
공유 메모리에 대한 포인터 :
MyBuffer *pBuf = new (shm_Addr) MyBuffer;
그리고 새로운 MyBuffer
주어진 위치에 건설됩니다. 이것은 템플릿 유형을 포함하여 모든 유형의 객체에서 작동 할 수 있습니다.
맞는 경우 별도의 기능으로 래핑 할 수 있습니다.
표준으로 만든 것을 파괴합니다 새로운 배치 당신은 명시 적으로 소멸자를 호출해야합니다. 이 때문입니다 delete
메모리를 정기적으로 비 할당하려고합니다 new
유효한 일이 아닌 메모리를 할당했습니다. 이것은 C ++의 유일한 시간입니다. 파괴자를 명시 적으로 호출해야합니다.
pBuf->~MyBuffer();