repo: bufferCircular II

produtor:

//produtor
#include <Windows.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <time.h> //lidar com o random


#define TAM_BUFFER_CIRUCLAR 10 //importante para os semáforos, numero de posicoes do buffer circular


typedef struct {
	int id;
	int val;
} CelulaBufferCircular; //estrutura de cada célula do buffer circular

typedef struct {
	int numeroProdutores;
	int numeroConsumidores;
	int proximaPosicaoEscrita; //controlar
	int proximaPosicaoLeitura; //controlar
	CelulaBufferCircular buffer[TAM_BUFFER_CIRUCLAR];
} BufferCircular; //representação da memoria partilhada


typedef struct {
	BufferCircular* memoriaPartilhada;
	HANDLE hSemaforoControlaEscrita;
	HANDLE hSemaforoControloLeitura;
	HANDLE hMutexControloExclusaoMutua; //mutex: exclusivo e partilhado por todos os produtores
	int controloDaThread; //flag, 1 sair, 0 caso contrário
	int idProdutor;
}DadosThreads;

//lidar com o random
int numero_aleatorio(int min, int max) {
	return rand() % (max - min + 1) + min; //valor entre min e max
}


//a trhead produtor
DWORD WINAPI ThreadEscritaProdutor(LPVOID param) {
	DadosThreads* dados = (DadosThreads*)param;
	CelulaBufferCircular celBC;  //teriam que ser vários fosse o caso de enviar para vários consumidores a informação de todos os produtores
	int contadorItensProduzidos = 0;

	while (dados->controloDaThread == 0) {
		celBC.id = dados->idProdutor;
		//produzir o item
		celBC.val = numero_aleatorio(10,99);

		//escrever no buffer circular, 
		WaitForSingleObject(
			dados->hSemaforoControlaEscrita, //existe uma posição para escrevermos
			INFINITE
		); 
		//temos a garantia que temos uma posicção de escrita
		WaitForSingleObject(
			dados->hMutexControloExclusaoMutua, //existe uma posição para escrevermos
			INFINITE
		);
		//temos a garantia que somos nos a escrever
		//os dois estão desbloqueados e vamos ser o unico produtor que vai escrever
		CopyMemory(
			&dados->memoriaPartilhada->buffer[dados->memoriaPartilhada->proximaPosicaoEscrita], //destino, copiar
			&celBC, 
			sizeof(CelulaBufferCircular)
		);
		//a proxima posicao de escrita é incrementada
		dados->memoriaPartilhada->proximaPosicaoEscrita++;
		//cheguei ao limite volto à posicao 0
		if (dados->memoriaPartilhada->proximaPosicaoEscrita == TAM_BUFFER_CIRUCLAR) {
			dados->memoriaPartilhada->proximaPosicaoEscrita = 0;
		}
		//libertar o mutex
		ReleaseMutex(dados->hMutexControloExclusaoMutua);
		//libtertar o semaforo de leitura
		//se ocupamos uma posição de escrita libertamos uma posição de leitura
		//o produtor espera por uma posição de escrita e desbloqueia uma posição de leitura
		//e o consumidor espera por uma posição de leitura e desbloqueia uma posição de escrita
		ReleaseSemaphore(dados->hSemaforoControloLeitura, 1, NULL); //apenas uma posição, 1

		contadorItensProduzidos++;
		_tprintf(TEXT("\nProdutor %d produziu valor %d "), dados->idProdutor, celBC.val);
		Sleep(numero_aleatorio(2, 4)*1000);
	}
	_tprintf(TEXT("\nProdutor %d produziu  %d itens"), dados->idProdutor, contadorItensProduzidos);
	return 0;
}


int _tmain(int argc, LPSTR argv[]) {
	HANDLE hFileMap;
	//mapeamento da memoria partilhada
	DadosThreads dados;
#ifdef UNICODE 
	_setmode(_fileno(stdin), _O_WTEXT);
	_setmode(_fileno(stdout), _O_WTEXT);
	_setmode(_fileno(stderr), _O_WTEXT);
#endif
	//lidar com o random
	srand((unsigned int)time(NULL));

	//os semaforos
	dados.hSemaforoControlaEscrita = CreateSemaphore(
		NULL,
		TAM_BUFFER_CIRUCLAR,
		TAM_BUFFER_CIRUCLAR,
		TEXT("SO2_MEMORIA_ESCRITA")
	);
	if (dados.hSemaforoControlaEscrita == NULL) {
		_tprintf(TEXT("\nerro no hSemaforoControlaEscrita"));
		return 1;
	}
	dados.hSemaforoControloLeitura = CreateSemaphore(NULL,
		0, //quantidade de posições iniciais, não existe nada para ser lido
		TAM_BUFFER_CIRUCLAR, //maximo de posições para serem lidas
		TEXT("SO2_MEMORIA_LEITURA")
	);
	if (dados.hSemaforoControloLeitura == NULL) {
		_tprintf(TEXT("\nerro no hSemaforoControloLeitura"));
		return 1;
	}
	//exclusao mutua para os produtores
	dados.hMutexControloExclusaoMutua = CreateMutex(NULL, FALSE, TEXT("SO2_MUTEX_PRODUTOR"));
	if (dados.hMutexControloExclusaoMutua == NULL) {
		_tprintf(TEXT("\nerro no hMutexControloExclusaoMutua"));
		return 1;
	}

	hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, TEXT("SO2_MEMORIA_PARTILHADA"));
	int primeiroProcesso = FALSE;

	//se existir é aberto
	//se nao existe é nulo
	if (hFileMap == NULL) {
		//existe um problem é porque se calahar não existe
		//criar a memoria partilhada
		primeiroProcesso = TRUE;
		hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE,//INVALID_HANDLE_VALUE ao inves de um ficheiro, faz o sistema isso
			NULL,
			PAGE_READWRITE, //nivel de protecão: lieura e escrita); 
			0, //dimensões da memoria partilhada: mais significativa
			sizeof(BufferCircular), //dimensões da memoria partilhada: menos significataiva
			TEXT("SO2_MEMORIA_PARTILHADA")//nome do file mapping: que vai ser criado e aberto pelos outros, nome em MACRO
		);
		if (hFileMap == NULL) {
			_tprintf(TEXT("\nerro no CreateFileMapping"));
			return 1;
		}
	}

	dados.memoriaPartilhada = (BufferCircular*)MapViewOfFile(
		hFileMap,
		FILE_MAP_ALL_ACCESS, //permissoes, de leitura e escrita
		0, //offsets: onde é mapeada 
		0, //0 para mapear até ao final
		0 //0 para mapear até ao final
	);
	if (dados.memoriaPartilhada == NULL) {
		_tprintf(TEXT("\nerro no MapViewOfFile"));
		return 1;
	}

	//inicialização: só deve ser feita quando a mem partilhada é criada, pois podemos ter N produtores.
	if (primeiroProcesso == TRUE) {
		dados.memoriaPartilhada->numeroConsumidores = 0;
		dados.memoriaPartilhada->numeroProdutores = 0;
		dados.memoriaPartilhada->proximaPosicaoEscrita = 0;
		dados.memoriaPartilhada->proximaPosicaoLeitura = 0;
	}
	//criar a thread
	dados.controloDaThread = 0;
	
	//exclusão mutua proque queremos aceder a algo que está em memoria partilhada
	WaitForSingleObject(dados.hMutexControloExclusaoMutua, INFINITE);
	//ir à memoria partilhada
	dados.memoriaPartilhada->numeroProdutores++;
	dados.idProdutor = dados.memoriaPartilhada->numeroProdutores;
	//liberta ro mutex
	ReleaseMutex(dados.hMutexControloExclusaoMutua);
	
	HANDLE hThread;
	TCHAR comando[100];
	hThread = CreateThread(NULL, 0, ThreadEscritaProdutor, &dados, 0, NULL);
	if (hThread != NULL) {
		_tprintf(TEXT("escreve qualquer coisa para sair"));
		_getts_s(comando, 100);
		dados.controloDaThread = 1;
		WaitForSingleObject(hThread, INFINITE);
	}

	UnmapViewOfFile(dados.memoriaPartilhada);
	//CloseHandle();


	return 0;
}

consumidor:

//consumidor
#include <Windows.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <time.h> //lidar com o random

#define TAM_BUFFER_CIRUCLAR 10 //importante para os semáforos, numero de posicoes do buffer circular

typedef struct {
	int id;
	int val;
} CelulaBufferCircular; //estrutura de cada célula do buffer circular

typedef struct {
	int numeroProdutores;
	int numeroConsumidores;
	int proximaPosicaoEscrita; //controlar
	int proximaPosicaoLeitura; //controlar
	CelulaBufferCircular buffer[TAM_BUFFER_CIRUCLAR];
} BufferCircular; //representação da memoria partilhada


typedef struct {
	BufferCircular* memoriaPartilhada;
	HANDLE hSemaforoControlaEscrita;
	HANDLE hSemaforoControloLeitura;
	HANDLE hMutexControloExclusaoMutua; //mutex: exclusivo e partilhado por todos os produtores
	int controloDaThread; //flag, 1 sair, 0 caso contrário
	int idConsumidor;
}DadosThreads;


//a thread consumidor
DWORD WINAPI ThreadLeituraConsumidor(LPVOID param) {
	DadosThreads* dados = (DadosThreads*)param;
	CelulaBufferCircular celBC;  //teriam que ser vários fosse o caso de enviar para vários consumidores a informação de todos os produtores
	int contadorItensProduzidos = 0;
	int soma = 0;

	while (dados->controloDaThread == 0) {
		
		//ler no buffer circular, 
		WaitForSingleObject(
			dados->hSemaforoControloLeitura, //existe uma posição para ler
			INFINITE
		);
		//temos a garantia que temos uma posicção de escrita
		WaitForSingleObject(
			dados->hMutexControloExclusaoMutua, //existe uma posição para escrevermos
			INFINITE
		);
		//temos a garantia que somos nos a ler
		//os dois estão desbloqueados e vamos ser o unico consumdior que vai ler
		CopyMemory(
			&celBC, //copiar
			&dados->memoriaPartilhada->buffer[dados->memoriaPartilhada->proximaPosicaoLeitura], //destino
			sizeof(CelulaBufferCircular)
		);
		//a proxima posicao de escrita é incrementada
		dados->memoriaPartilhada->proximaPosicaoLeitura++;
		//cheguei ao limite volto à posicao 0
		if (dados->memoriaPartilhada->proximaPosicaoLeitura == TAM_BUFFER_CIRUCLAR) {
			dados->memoriaPartilhada->proximaPosicaoLeitura = 0;
		}
		//libertar o mutex quando terminamos a leitura
		ReleaseMutex(dados->hMutexControloExclusaoMutua);
		//libtertar o semaforo de escrita
		//se ocupamos uma posição de leitura libertamos uma posição de escrita
		//e o consumidor espera por uma posição de leitura e desbloqueia uma posição de escrita
		ReleaseSemaphore(dados->hSemaforoControlaEscrita, 1, NULL); //apenas uma posição, 1

		contadorItensProduzidos++;
		soma = soma + celBC.val;
		_tprintf(TEXT("\nConsumidor %d consumiu valor %d "), dados->idConsumidor, celBC.val);
		//Sleep(numero_aleatorio(2, 4) * 1000);
	}
	_tprintf(TEXT("\nConsumidor %d consumiu  %d acumulado"), dados->idConsumidor, soma);
	return 0;
}

//a thread consumidor
DWORD WINAPI ThreadEscritaConsumidor(LPVOID param) {
	DadosThreads* dados = (DadosThreads*)param;
	CelulaBufferCircular celBC;  //teriam que ser vários fosse o caso de enviar para vários consumidores a informação de todos os produtores
	int contadorItensProduzidos = 0;

	while (dados->controloDaThread == 0) {
		celBC.id = dados->idConsumidor;
		//produzir o item
		celBC.val = numero_aleatorio(10, 99);

		//escrever no buffer circular, 
		WaitForSingleObject(
			dados->hSemaforoControlaEscrita, //existe uma posição para escrevermos
			INFINITE
		);
		//temos a garantia que temos uma posicção de escrita
		WaitForSingleObject(
			dados->hMutexControloExclusaoMutua, //existe uma posição para escrevermos
			INFINITE
		);
		//temos a garantia que somos nos a escrever
		//os dois estão desbloqueados e vamos ser o unico produtor que vai escrever
		CopyMemory(
			&dados->memoriaPartilhada->buffer[dados->memoriaPartilhada->proximaPosicaoEscrita], //destino, copiar
			&celBC,
			sizeof(CelulaBufferCircular)
		);
		//a proxima posicao de escrita é incrementada
		dados->memoriaPartilhada->proximaPosicaoEscrita++;
		//cheguei ao limite volto à posicao 0
		if (dados->memoriaPartilhada->proximaPosicaoEscrita == TAM_BUFFER_CIRUCLAR) {
			dados->memoriaPartilhada->proximaPosicaoEscrita = 0;
		}
		//libertar o mutex
		ReleaseMutex(dados->hMutexControloExclusaoMutua);
		//libtertar o semaforo de leitura
		//se ocupamos uma posição de escrita libertamos uma posição de leitura
		//o produtor espera por uma posição de escrita e desbloqueia uma posição de leitura
		//e o consumidor espera por uma posição de leitura e desbloqueia uma posição de escrita
		ReleaseSemaphore(dados->hSemaforoControloLeitura, 1, NULL); //apenas uma posição, 1

		contadorItensProduzidos++;
		_tprintf(TEXT("\Consumdior %d produziu valor %d "), dados->idConsumidor, celBC.val);
		Sleep(numero_aleatorio(2, 4) * 1000);
	}
	_tprintf(TEXT("\Consumdior %d produziu  %d itens"), dados->idConsumidor, contadorItensProduzidos);
	return 0;
}


int _tmain(int argc, LPSTR argv[]) {
	HANDLE hFileMap;
	//mapeamento da memoria partilhada
	DadosThreads dados;
#ifdef UNICODE 
	_setmode(_fileno(stdin), _O_WTEXT);
	_setmode(_fileno(stdout), _O_WTEXT);
	_setmode(_fileno(stderr), _O_WTEXT);
#endif
	//lidar com o random
	srand((unsigned int)time(NULL));

	//os semaforos
	dados.hSemaforoControlaEscrita = CreateSemaphore(
		NULL,
		TAM_BUFFER_CIRUCLAR,
		TAM_BUFFER_CIRUCLAR,
		TEXT("SO2_MEMORIA_ESCRITA")
	);
	if (dados.hSemaforoControlaEscrita == NULL) {
		_tprintf(TEXT("\nerro no hSemaforoControlaEscrita"));
		return 1;
	}
	dados.hSemaforoControloLeitura = CreateSemaphore(NULL,
		0, //quantidade de posições iniciais, não existe nada para ser lido
		TAM_BUFFER_CIRUCLAR, //maximo de posições para serem lidas
		TEXT("SO2_MEMORIA_LEITURA")
	);
	if (dados.hSemaforoControloLeitura == NULL) {
		_tprintf(TEXT("\nerro no hSemaforoControloLeitura"));
		return 1;
	}
	//exclusao mutua para os produtores
	dados.hMutexControloExclusaoMutua = CreateMutex(NULL, FALSE, TEXT("SO2_MUTEX_CONSUMIDOR"));
	if (dados.hMutexControloExclusaoMutua == NULL) {
		_tprintf(TEXT("\nerro no hMutexControloExclusaoMutua"));
		return 1;
	}

	hFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, TEXT("SO2_MEMORIA_PARTILHADA"));
	int primeiroProcesso = FALSE;

	//se existir é aberto
	//se nao existe é nulo
	if (hFileMap == NULL) {
		//existe um problem é porque se calahar não existe
		//criar a memoria partilhada
		primeiroProcesso = TRUE;
		hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE,//INVALID_HANDLE_VALUE ao inves de um ficheiro, faz o sistema isso
			NULL,
			PAGE_READWRITE, //nivel de protecão: lieura e escrita); 
			0, //dimensões da memoria partilhada: mais significativa
			sizeof(BufferCircular), //dimensões da memoria partilhada: menos significataiva
			TEXT("SO2_MEMORIA_PARTILHADA")//nome do file mapping: que vai ser criado e aberto pelos outros, nome em MACRO
		);
		if (hFileMap == NULL) {
			_tprintf(TEXT("\nerro no CreateFileMapping"));
			return 1;
		}
	}

	dados.memoriaPartilhada = (BufferCircular*)MapViewOfFile(
		hFileMap,
		FILE_MAP_ALL_ACCESS, //permissoes, de leitura e escrita
		0, //offsets: onde é mapeada 
		0, //0 para mapear até ao final
		0 //0 para mapear até ao final
	);
	if (dados.memoriaPartilhada == NULL) {
		_tprintf(TEXT("\nerro no MapViewOfFile"));
		return 1;
	}

	//inicialização: só deve ser feita quando a mem partilhada é criada, pois podemos ter N produtores.
	if (primeiroProcesso == TRUE) {
		dados.memoriaPartilhada->numeroConsumidores = 0;
		dados.memoriaPartilhada->numeroProdutores = 0;
		dados.memoriaPartilhada->proximaPosicaoEscrita = 0;
		dados.memoriaPartilhada->proximaPosicaoLeitura = 0;
	}
	//criar a thread
	dados.controloDaThread = 0;

	//exclusão mutua proque queremos aceder a algo que está em memoria partilhada
	WaitForSingleObject(dados.hMutexControloExclusaoMutua, INFINITE);
	//ir à memoria partilhada
	dados.memoriaPartilhada->numeroConsumidores++;
	dados.idConsumidor = dados.memoriaPartilhada->numeroConsumidores;
	//libertar o mutex
	ReleaseMutex(dados.hMutexControloExclusaoMutua);

	HANDLE hThreadArray[2];
	TCHAR comando[100];
	hThreadArray[0] = CreateThread(NULL, 0, ThreadLeituraConsumidor, &dados, 0, NULL);
	hThreadArray[1] = CreateThread(NULL, 0, ThreadEscritaConsumidor, &dados, 0, NULL);


	if (hThreadArray[0] == NULL || hThreadArray[1] == NULL)
	{
		_tprintf(TEXT("nada de threads"));
		ExitProcess(3);
	}
	WaitForMultipleObjects(2, hThreadArray, TRUE, INFINITE);

	UnmapViewOfFile(dados.memoriaPartilhada);
	//CloseHandle();


	return 0;
}
Tags : ,

0 thoughts on “repo: bufferCircular II”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.