/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

	【機能概要】	: C++言語関連で使用する共有メモリ関連メソッド群
					  本アプリで実装している共通メソッドは、以下の通り
					  使用方法については、各メソッドの実装部で記述

	【作成日】		: 2021.04.23

	【実装関数】	: checkSharedMemory			# 共有メモリの作成チェック
					: SetSharedMemoryID			# 共有メモリID設定
					: SetLockMutexID			# LockミューテックスID設定（WIN用）
					: CreateSheredMemory		# 共有メモリ作成
					: OpenSheredMemory			# 共有メモリオープン
					: OpenWriteSheredMemory		# 共有メモリ作成＆オープン（未使用）
					: CloseSheredMemory			# 共有メモリクローズ
					: WriteSheredMemoryStart	# 排他書き込み開始（WIN用）
					: WriteSheredMemoryEnd		# 排他書き込み終了（WIN用）
					: WriteSheredMemoryCheck	# 排他書き込みチェック（WIN用）
					: ~CLSSharedMemory			# デスクトラクタ

_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

#include "sharedmemory_cls.h"

//*******************************************************************************
//* CLSSharedMemoryクラス メソッド定義                                          *
//*******************************************************************************
//* 共有メモリの作成チェック
//* BOOL checkSharedMemory()
//* return TRUE :作成済み
//*        FALSE:未作成
BOOL CLSSharedMemory::checkSharedMemory(){
	if(pData == NULL){
		return FALSE;
	}
	else{
		return TRUE;
	}
}

//*******************************************************************************
//* 共有メモリID設定
//* BOOL SetSharedMemoryName()
//* parameter	I	inputSharedMemoryID			:共有メモリID
//* return TRUE :作成済み
//*        FALSE:未作成
BOOL CLSSharedMemory::SetSharedMemoryID(
	key_t inputSharedMemoryID	//共有メモリID
){
	if(pData == NULL){
		keySharedMemoryID = inputSharedMemoryID;
		return TRUE;
	}
	else{
		return FALSE;
	}
}

//*******************************************************************************
//* LockミューテックスID設定
//* void SetSharedMemoryName()
//* parameter	I	inputLockMutexID			:ロック用ミューテックスID
//* return 無し
BOOL CLSSharedMemory::SetLockMutexID(
	key_t inputLockMutexID		//ロック用ミューテックスID
){
	if(pData == NULL){
		keyLockMutexID = inputLockMutexID;
		return TRUE;
	}
	else{
		return FALSE;
	}
}

//*******************************************************************************
//* 共有メモリ作成
//* void * CreateSheredMemory()
//* parameter	I	memSize						:共有メモリサイズ
//* return NULL以外:正常終了（確保されたメモリのポインタ）
//* return NULL    :異常終了
void * CLSSharedMemory::CreateSheredMemory(
	long  memSize	//サイズ
){
#ifdef WIN32
	char cSharedMemoryName[12];
	char cLockMutexID[12];
#endif
	//共有メモリIDが指定されていない場合は異常終了
	if(keySharedMemoryID <= 0){
		return NULL;
	}

	//すでに共有メモリが存在している場合は異常終了
	if(pData != NULL){
		return NULL;
	}

	/* 排他制御用ミューテックスオブジェクト作成 */
	if(keyLockMutexID > 0){
#ifdef WIN32
		sprintf(cLockMutexID,"%011d",keyLockMutexID);			//IDを文字列化する
		hLockMutex = CreateMutex(NULL, FALSE, cLockMutexID);	//ミューテックス作成
		if(hLockMutex <= 0){
			return NULL;
		}
#else
		if(iLockMutex <= 0){
			return NULL;
		}
#endif
	}

	/* 共有メモリの作成 */
#ifdef WIN32
	sprintf(cSharedMemoryName,"%011d",keySharedMemoryID);		//IDを文字列化する
	hSharedMemory = CreateFileMapping(
		INVALID_HANDLE_VALUE,
		NULL,
		PAGE_READWRITE | SEC_COMMIT,
		0, memSize, 
		cSharedMemoryName);
	if(hSharedMemory <= NULL){
		hSharedMemory = NULL;
		return NULL;
	}
#else
	iSharedMemory = shmget(keySharedMemoryID, memSize, 0666|IPC_CREAT);
	if(iSharedMemory < 0){
		iErrorNo = errno;
		strcpy(cErrorMsg,"CreateSheredMemory実行時にshmgetにてエラー検出");
		iSharedMemory = -1;
		return NULL;
	}
#endif

	/* 共有メモリを実アドレスにマッピングする */
#ifdef WIN32
	pData = MapViewOfFile(hSharedMemory, FILE_MAP_ALL_ACCESS, 0, 0, 0);
#else
	pData = shmat(iSharedMemory, 0, 0);
	if(pData < 0){
		iErrorNo = errno;
		strcpy(cErrorMsg,"CreateSheredMemory実行時にshmatにてエラー検出");
		pData = NULL;
	}
#endif
	return pData;
}

//*******************************************************************************
//* 共有メモリ作成（IDとサイズの同時設定）
//* void * CreateSheredMemory()
//* parameter	I	inputSharedMemoryID			:共有メモリID
//* parameter	I	memSize						:共有メモリサイズ
//* return NULL以外:正常終了（確保されたメモリのポインタ）
//* return NULL    :異常終了
void * CLSSharedMemory::CreateSheredMemory(key_t inputSharedMemoryID,long memSize){
	SetSharedMemoryID(inputSharedMemoryID);
	return CreateSheredMemory(memSize);
}

//*******************************************************************************
//* 共有メモリオープン
//* void * OpenSheredMemory()
//* return NULL以外:正常終了（確保されたメモリのポインタ）
//* return NULL    :異常終了
void * CLSSharedMemory::OpenSheredMemory(
){
#ifdef WIN32
	char cSharedMemoryName[12];
	char cLockMutexID[12];
#endif
	//すでに共有メモリがアタッチされている場合は異常終了
	if(pData != NULL){
		return NULL;
	}

	/* 排他制御用ミューテックスオブジェクト作成 */
	if(keyLockMutexID > 0){
#ifdef WIN32
		sprintf(cLockMutexID,"%011d",keyLockMutexID);			//IDを文字列化する
		hLockMutex = CreateMutex(NULL, FALSE, cLockMutexID);	//ミューテックス作成
		if(hLockMutex <= 0){
			return NULL;
		}
#else
#endif
	}

	/* ファイルマッピングオブジェクトの作成 */
#ifdef WIN32
	sprintf(cSharedMemoryName,"%011d",keySharedMemoryID);		//IDを文字列化する
	hSharedMemory = OpenFileMapping(FILE_MAP_READ,FALSE,cSharedMemoryName);
	if(hSharedMemory <= 0){
		return NULL;
	}
#else
	iSharedMemory = shmget(keySharedMemoryID, 0, 0444);
	if(iSharedMemory < 0){
		iErrorNo = errno;
		strcpy(cErrorMsg,"OpenSheredMemory実行時にshmgetにてエラー検出");
		return NULL;
	}
#endif

	/* 共有メモリを実アドレスにマッピングする */
#ifdef WIN32
	pData = MapViewOfFile(hSharedMemory, FILE_MAP_READ, 0, 0, 0);
#else
	pData = shmat(iSharedMemory, 0, 0);
	if(pData < 0){
		iErrorNo = errno;
		strcpy(cErrorMsg,"OpenSheredMemory実行時にshmatにてエラー検出");
		pData = NULL;
	}
#endif
	return pData;
}

//*******************************************************************************
//* 共有メモリオープン（ID指定）
//* void * OpenSheredMemory()
//* parameter	I	inputSharedMemoryID			:共有メモリID
//* return NULL以外:正常終了（確保されたメモリのポインタ）
//* return NULL    :異常終了
void * CLSSharedMemory::OpenSheredMemory(key_t inputSharedMemoryID){
	if(!SetSharedMemoryID(inputSharedMemoryID)){
		return NULL;
	}
	return OpenSheredMemory();
}

//*******************************************************************************
//* 共有メモリ作成＆オープン（未使用）
//* void * OpenWriteSheredMemory()
//* return NULL以外:正常終了（確保されたメモリのポインタ）
//* return NULL    :異常終了
void * CLSSharedMemory::OpenWriteSheredMemory(){

#ifdef WIN32
	char cSharedMemoryName[12];
	char cLockMutexID[12];
#endif

	//すでに共有メモリが存在している場合はFALSE
	if(checkSharedMemory() == TRUE){
		return NULL;
	}

	/* 排他制御用ミューテックスオブジェクト作成 */
	if(keyLockMutexID > 0){
#ifdef WIN32
		sprintf(cLockMutexID,"%011d",keyLockMutexID);			//IDを文字列化する
		hLockMutex = CreateMutex(NULL, FALSE, cLockMutexID);	//ミューテックス作成
		if(hLockMutex <= 0){
			return NULL;
		}
#else
#endif
	}

	/* 共有メモリのオープン */
#ifdef WIN32
	sprintf(cSharedMemoryName,"%011d",keySharedMemoryID);		//IDを文字列化する
	hSharedMemory = OpenFileMapping(FILE_MAP_WRITE,FALSE,cSharedMemoryName);
	if(hSharedMemory <= 0){
		return NULL;
	}
#else
	iSharedMemory = shmget(keySharedMemoryID, 0, 0666);
	if(iSharedMemory < 0){
		iErrorNo = errno;
		strcpy(cErrorMsg,"OpenWriteSheredMemory実行時にshmgetにてエラー検出");
		return NULL;
	}
#endif

#ifdef WIN32
	pData = MapViewOfFile(hSharedMemory, FILE_MAP_WRITE, 0, 0, 0);
#else
	pData = shmat(iSharedMemory, 0, 0);
	if(pData < 0){
		iErrorNo = errno;
		strcpy(cErrorMsg,"OpenWriteSheredMemory実行時にshmatにてエラー検出");
		pData = NULL;
	}
#endif
	return pData;
}

//*******************************************************************************
//* 共有メモリ作成＆オープン（ID指定・未使用）
//* void * OpenWriteSheredMemory()
//* parameter	I	inputSharedMemoryID			:共有メモリID
//* return NULL以外:正常終了（確保されたメモリのポインタ）
//* return NULL    :異常終了
void * CLSSharedMemory::OpenWriteSheredMemory(key_t inputSharedMemoryID){
	if(!SetSharedMemoryID(inputSharedMemoryID)){
		return NULL;
	}
	return OpenWriteSheredMemory();
}

//*******************************************************************************
//* 共有メモリクローズ
//* void CloseSheredMemory()
void CLSSharedMemory::CloseSheredMemory(
){
	if(pData != NULL){
#ifdef WIN32
		UnmapViewOfFile(pData);
#else
		shmdt((char *)pData);
#endif
		pData = NULL;
	}
#ifdef WIN32
	if(hSharedMemory!=NULL){
		CloseHandle(hSharedMemory);
	}
#endif
}

//*******************************************************************************
//* 排他書き込み開始
//* BOOL WriteSheredMemoryStart()
//* return TRUE :排他書き込み準備OK
//*        FALSE:排他書き込み準備NG
BOOL CLSSharedMemory::WriteSheredMemoryStart(){
#ifdef WIN32
	WaitForSingleObject(hLockMutex, INFINITE);
	blMutexFlg = TRUE;
#endif
	return TRUE;
}

//*******************************************************************************
//* 排他書き込み終了
//* BOOL WriteSheredMemoryEnd()
//* return TRUE :排他書き込み準備OK
//*        FALSE:排他書き込み準備NG
BOOL CLSSharedMemory::WriteSheredMemoryEnd(){
#ifdef WIN32
	ReleaseMutex(hLockMutex);
	blMutexFlg = FALSE;
#endif
	return TRUE;
}

//*******************************************************************************
//* 排他書き込みチェック
//* BOOL WriteSheredMemoryEnd()
//* return TRUE :排他書き込み中
//*        FALSE:排他書き込み中ではない
BOOL CLSSharedMemory::WriteSheredMemoryCheck(){
	BOOL bReturn = TRUE;

#ifdef WIN32
	DWORD dwReturn;
	dwReturn=WaitForSingleObject(hLockMutex, 0);
	switch(dwReturn){
		case WAIT_OBJECT_0:
			dwReturn = WriteSheredMemoryEnd();
			bReturn = FALSE;
			break;
		default:
			break;
	}
#endif
	return bReturn;
}

//*******************************************************************************
//* デスクトラクタ
//* void ‾CLSSharedMemory()
CLSSharedMemory::~CLSSharedMemory(){
	if(pData != NULL){
#ifdef WIN32
		UnmapViewOfFile(pData);
#else
		shmdt((char *)pData);
#endif
		pData = NULL;
	}
#ifdef WIN32
	if(hSharedMemory!=NULL){
		CloseHandle(hSharedMemory);
	}
	if(blMutexFlg == TRUE){
		ReleaseMutex(hLockMutex);
	}
	if(hLockMutex!=NULL){
		CloseHandle(hLockMutex);
	}
#endif
}

