repo: bufferCircular
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 ThreadConsumidor(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;
}
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 hThread;
TCHAR comando[100];
hThread = CreateThread(NULL, 0, ThreadConsumidor, &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;
}
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 ThreadProdutor(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, ThreadProdutor, &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;
}
0 thoughts on “repo: bufferCircular”