repo: graficoMenus

#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
#include "resource.h"

#define NUM_CLIENTES 3
#define LIST_SIZE 8

TCHAR* LIST_ITENS[] = {
	TEXT("10€"),
	TEXT("20€"),
	TEXT("40€"),
	TEXT("60€"),
	TEXT("80€"),
	TEXT("100€"),
	TEXT("150€"),
	TEXT("200€")
};

LRESULT CALLBACK TrataEventos(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK TrataEventosLogin(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK TrataEventosLevantar(HWND, UINT, WPARAM, LPARAM);

TCHAR szProgName[] = TEXT("Ficha8");

typedef struct {
	unsigned int ID;
	TCHAR username[16];
	TCHAR password[16];
	unsigned int saldo;
} cliente;

typedef struct {
	unsigned int tipo; // 1 = depósito, 2 = levantamento
	unsigned int quantia;
	unsigned int ID;
} operacao;

typedef struct {
	cliente clientes[NUM_CLIENTES];
	operacao historico[200];
	unsigned int numOperacoes;
} dados;

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
	HWND hWnd;
	MSG lpMsg;
	WNDCLASSEX wcApp;
	HANDLE hAccel;
	dados dadosPartilhados;

	wcApp.cbSize = sizeof(WNDCLASSEX);
	wcApp.hInstance = hInst;

	wcApp.lpszClassName = szProgName;
	wcApp.lpfnWndProc = TrataEventos;

	wcApp.style = CS_HREDRAW | CS_VREDRAW;

	wcApp.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON_APP));
	wcApp.hIconSm = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON_APP));
	wcApp.hCursor = LoadCursor(hInst, MAKEINTRESOURCE(IDI_ICON_APP));
	wcApp.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_PRINCIPAL);

	wcApp.cbClsExtra = sizeof(dados);
	wcApp.cbWndExtra = 0;
	wcApp.hbrBackground = CreateSolidBrush(RGB(220, 220, 220));

	if (!RegisterClassEx(&wcApp))
		return(0);

	hWnd = CreateWindow(
		szProgName,
		TEXT("SO2 - Ficha 8"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		300,
		150,
		(HWND)HWND_DESKTOP,
		(HMENU)NULL,
		(HINSTANCE)hInst,
		0);

	dadosPartilhados.numOperacoes = 5; // Apenas para testar...
	LONG_PTR x = SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)&dadosPartilhados);

	ShowWindow(hWnd, nCmdShow);

	hAccel = LoadAccelerators(NULL, MAKEINTRESOURCE(IDR_ACCELERATOR));

	while (GetMessage(&lpMsg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(hWnd, hAccel, &lpMsg))
		{
			TranslateMessage(&lpMsg);
			DispatchMessage(&lpMsg);
		}
	}

	return((int)lpMsg.wParam);
}

LRESULT CALLBACK TrataEventos(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
	TCHAR str1[512], str2[512];
	dados* dadosPartilhados;

	dadosPartilhados = (dados*)GetWindowLongPtr(hWnd, GWLP_USERDATA);

	switch (messg)
	{
	case WM_CREATE:
		EnableMenuItem(GetMenu(hWnd), ID_CONSULTA, MF_DISABLED | MF_GRAYED);
		EnableMenuItem(GetMenu(hWnd), ID_LEVANTAMENTO, MF_DISABLED | MF_GRAYED);
		break;

	case WM_COMMAND:

		switch (LOWORD(wParam))
		{
		case ID_LOGIN:

			DialogBox(NULL, MAKEINTRESOURCE(IDD_DIALOG_LOGIN), hWnd, TrataEventosLogin);
			EnableMenuItem(GetMenu(hWnd), ID_CONSULTA, MF_ENABLED);
			EnableMenuItem(GetMenu(hWnd), ID_LEVANTAMENTO, MF_ENABLED);
			break;

		case ID_CONSULTA:
		case ID_ACCELERATOR_CONSULTA:

			LoadString(NULL, IDS_STR_CONSULTA, str1, 512);
			_stprintf_s(str2, 512, TEXT("%s (%d)"), str1, dadosPartilhados->numOperacoes);
			MessageBox(hWnd, str2, TEXT("String Table"), MB_OK | MB_ICONINFORMATION);
			break;

		case ID_ACCELERATOR_LEVANTAMENTO:
		case ID_LEVANTAMENTO:

			DialogBox(NULL, MAKEINTRESOURCE(IDD_DIALOG_LEVANTAMENTO), NULL, TrataEventosLevantar);
			break;

		}

		break;

	case WM_DESTROY:
		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(hWnd, messg, wParam, lParam);
		break;
	}

	return(0);
}

LRESULT CALLBACK TrataEventosLogin(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
	TCHAR username[16];

	switch (messg)
	{
	case WM_COMMAND:

		if (LOWORD(wParam) == IDOK)
		{
			GetDlgItemText(hWnd, IDC_EDIT_LOGIN, username, 16);
			MessageBox(hWnd, username, TEXT("Username"), MB_OK | MB_ICONINFORMATION);
		}
		else if (LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hWnd, 0);
			return TRUE;
		}

		break;

	case WM_CLOSE:

		EndDialog(hWnd, 0);
		return TRUE;
	}

	return FALSE;
}

LRESULT CALLBACK TrataEventosLevantar(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
	int i;

	switch (messg)
	{
	case WM_INITDIALOG:

		HWND hwndList = GetDlgItem(hWnd, IDC_LIST_MONTANTES);
		SendMessage(hwndList, LB_RESETCONTENT, 0, 0);

		for (i = 0; i < LIST_SIZE; i++)
			SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)LIST_ITENS[i]);

		break;

	case WM_COMMAND:

		if (LOWORD(wParam) == IDC_LIST_MONTANTES)
		{
			switch (HIWORD(wParam))
			{
			case LBN_DBLCLK:

				HWND hwndList = GetDlgItem(hWnd, IDC_LIST_MONTANTES);
				i = (int)SendMessage(hwndList, LB_GETCURSEL, 0, 0);
				MessageBox(hWnd, LIST_ITENS[i], TEXT("ListBox"), MB_OK | MB_ICONINFORMATION);

				break;
			}
		}

		break;

	case WM_CLOSE:

		EndDialog(hWnd, 0);
		return TRUE;
	}

	return FALSE;
}

e no resource.h

#define IDI_ICON_APP                    101
#define IDR_MENU_PRINCIPAL              102
#define IDR_ACCELERATOR                 107
#define IDD_DIALOG1                     108
#define IDC_LOGIN                       1001
#define IDC_PASSWORD                    1002
#define ID_CANCEL                       1003
#define IDC_LIST_MONTANTES              1004
#define IDC_EDIT1                       1006
#define IDS_STR_CONSULTA                1006
#define ID_OPERA40001                   40001
#define ID_OPERA40002                   40002
#define ID_LOGIN                        40003
#define IDD_DIALOG_LOGIN                40003
#define ID_CONSULTA                     40004
#define ID_LEVANTAMENTO                 40005
#define IDD_DIALOG_LEVANTAMENTO         40005
#define ID_ACCELERATOR_CONSULTA         40006
#define ID_ACCELERATOR_LEVANTAMENTO     40007

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        110
#define _APS_NEXT_COMMAND_VALUE         40009
#define _APS_NEXT_CONTROL_VALUE         1007
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
Tags : ,

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 : ,

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;
}
Tags : ,

repo: atende cliente OverLappedIO

Cliente:

#include <Windows.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <time.h>
#include "..\cliente\util.h"


DWORD WINAPI leResposta(LPVOID lpData) {
	HANDLE hPipe = (HANDLE)lpData;
	TCHAR szStr[TAM];
	DWORD dwLidos, res;


	OVERLAPPED ov;
	HANDLE hEvento;
	hEvento = CreateEvent(NULL, TRUE, FALSE, NULL); //ultimo NULL evento local à thread não peciso de nome

	do {
		ZeroMemory(&ov, sizeof(ov));
		ov.hEvent = hEvento;
		//ResetEvent(hEvent);

		res = ReadFile(hPipe, szStr, TAM, &dwLidos, &ov); //nao fico à espera agora, fica agendada a operação
		if (res) {
			_tprintf(_T("foi realizada de imediato...\n"));
		}
		if (!res && GetLastError() == ERROR_IO_PENDING) { //proteção
			_tprintf(_T("a aguardar informação...\n"));
			/* .... */
			WaitForSingleObject(ov.hEvent, INFINITE);
			GetOverlappedResult(hPipe, &ov, &dwLidos, FALSE);
		}
		_tprintf(_T("Recebi: %s (%d)\n"), szStr, dwLidos);
	} while (_tcscmp(szStr, _T("SAIR")) != 0);
	
	return 0;
}


int _tmain(int argc, TCHAR* argv[]) {
	HANDLE hPipe;
	TCHAR szStr[TAM];
	DWORD dwEscritos;

#ifdef UNICODE 
	_setmode(_fileno(stdin), _O_WTEXT);
	_setmode(_fileno(stdout), _O_WTEXT);
	_setmode(_fileno(stderr), _O_WTEXT);
#endif


	while (1) {
		//ligar ao servidor	
		hPipe = CreateFile(NOME_PIPE,
			GENERIC_READ | GENERIC_WRITE,
			0,
			NULL,
			OPEN_EXISTING,
			FILE_FLAG_OVERLAPPED,
			NULL);
		if (hPipe != INVALID_HANDLE_VALUE) {
			break;

		}
		if (!WaitNamedPipe(NOME_PIPE, 10000)) { //espera 10 segundos
			_tprintf(_T("[erro] named pipe nao existe "));
		}
	}

	//thread para ler resposta
	HANDLE hThread;
	DWORD dwTid;
	hThread = CreateThread(NULL, 0, leResposta, (LPVOID)hPipe, 0, &dwTid);

	OVERLAPPED ov;
	HANDLE hEvento;
	hEvento = CreateEvent(NULL, TRUE, FALSE, NULL);

	//thread inicial
	do {
		_tprintf(_T("TEXTO: "));
		if (_fgetts(szStr, TAM, stdin) == NULL) {
			break;
		}
		szStr[_tcslen(szStr) - 1] = _T('\0');

		ZeroMemory(&ov, sizeof(ov)); //limpar
		ov.hEvent = hEvento; //atribuir
		//ResetEvent(hEvent)//nao é necessário

		WriteFile(hPipe, szStr, ((DWORD)_tcslen(szStr) + 1) * sizeof(TCHAR), &dwEscritos, &ov); //envia info para o servidor, e não bloqueia. dwEscritos total de bytes escritos
		//devia verificar e
//true correu bem																								//true: correu bem
		//false: correu mal
		//getpasteerror, que a oepração foi agendada

		/* .. podemos fazer o que quiseremos não é tão critico.. */
		WaitForSingleObject(ov.hEvent, INFINITE);//esperar que o evento seja assinalado
		GetOverlappedResult(hPipe, &ov, &dwEscritos, FALSE); //esperar que o write foi concluido. dwEscritos verificar se o numero de bytes foram escritos
		_tprintf(_T("Enviei: %s (%d)\n"), szStr, dwEscritos);
	} while (_tcscmp(szStr, _T("SAIR")) != 0);
	return 0;
}

Servidor:

#include <Windows.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <time.h>
#include "..\cliente\util.h"


DWORD WINAPI atendeCliente(LPVOID lpData) {
	HANDLE hPipe = (HANDLE)lpData;
	TCHAR szStr[TAM];
	DWORD dwLidos, dwEscritos;

	_tprintf(_T("Cliente ligado...\n"));
	while (1) {
		if (!ReadFile(hPipe, szStr, TAM, &dwLidos, NULL)) { //lê pedido..
			break;
		}
		_tprintf(_T("Recebi: %s (%d)\n"), szStr, dwLidos); 
		CharUpperBuff(szStr, dwLidos/sizeof(TCHAR)); //processa
		WriteFile(hPipe, szStr, dwLidos, &dwEscritos, NULL); //envia resposta
		_tprintf(_T("Enviei: %s (%d)\n"), szStr, dwEscritos);
	}
	_tprintf(_T("O cliente desligou...\n"));
	FlushFileBuffers(hPipe);
	DisconnectNamedPipe(hPipe);
	CloseHandle(hPipe);
	return 0;
}

int _tmain(int argc, TCHAR* argv[]) {
	HANDLE hPipe;
	DWORD dwTid;

#ifdef UNICODE 
	_setmode(_fileno(stdin), _O_WTEXT);
	_setmode(_fileno(stdout), _O_WTEXT);
	_setmode(_fileno(stderr), _O_WTEXT);
#endif
	
	while (1) {
		//cada vez que um cliente se ligar é criada uma nova thread
		hPipe = CreateNamedPipe(
			NOME_PIPE, 
			PIPE_ACCESS_DUPLEX,
			PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 
			PIPE_UNLIMITED_INSTANCES, 
			BUFFSIZE, 
			BUFFSIZE, 
			10000, 
			NULL);
		if (ConnectNamedPipe(hPipe, NULL)) {
			CreateThread(NULL, 0, atendeCliente, (LPVOID)hPipe, 0, &dwTid);
		}
	}
	return 0;
}

Util:

#define TAM 100
#define NOME_PIPE TEXT("\\\\.\\pipe\\teste")
#define BUFFSIZE 1024
Tags : ,

repo: atende cliente

Cliente:

#include <Windows.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <time.h>
#include "..\cliente\util.h"


int _tmain(int argc, TCHAR* argv[]) {
	HANDLE hPipe;
	TCHAR szStr[TAM];
	DWORD dwLidos, dwEscritos;

#ifdef UNICODE 
	_setmode(_fileno(stdin), _O_WTEXT);
	_setmode(_fileno(stdout), _O_WTEXT);
	_setmode(_fileno(stderr), _O_WTEXT);
#endif

	while (1) {
		//cada vez que um cliente se ligar é criada uma nova thread
		hPipe = CreateFile(NOME_PIPE, 
			GENERIC_READ | GENERIC_WRITE,
			0,
			NULL,
			OPEN_EXISTING,
			0,
			NULL);
		if (hPipe != INVALID_HANDLE_VALUE) {
			break;
			
		}
		WaitNamedPipe(NOME_PIPE, 10000); //espera 10 segundos
	}
	do{
		_tprintf(_T("TEXTO: "));
		if (_fgetts(szStr, TAM, stdin) == NULL) {
			break;
		}
		szStr[_tcslen(szStr) - 1] = _T('\0');
		WriteFile(hPipe, szStr, ((DWORD)_tcslen(szStr) + 1) * sizeof(TCHAR), &dwEscritos, NULL);
		_tprintf(_T("Enviei: %s (%d)\n"), szStr, dwEscritos);
		ReadFile(hPipe, szStr, TAM, &dwLidos, NULL);
		_tprintf(_T("Recebi: %s (%d)\n"), szStr, dwLidos);
	} while (_tcscmp(szStr, _T("SAIR")) != 0);
	return 0;
}

Servidor:

#include <Windows.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <time.h>
#include "..\cliente\util.h"


DWORD WINAPI atendeCliente(LPVOID lpData) {
	HANDLE hPipe = (HANDLE)lpData;
	TCHAR szStr[TAM];
	DWORD dwLidos, dwEscritos;

	_tprintf(_T("Cliente ligado...\n"));
	while (1) {
		if (!ReadFile(hPipe, szStr, TAM, &dwLidos, NULL)) { //lê pedido..
			break;
		}
		_tprintf(_T("Recebi: %s (%d)\n"), szStr, dwLidos); 
		CharUpperBuff(szStr, dwLidos/sizeof(TCHAR)); //processa
		WriteFile(hPipe, szStr, dwLidos, &dwEscritos, NULL); //envia resposta
		_tprintf(_T("Enviei: %s (%d)\n"), szStr, dwEscritos);
	}
	_tprintf(_T("O cliente desligou...\n"));
	FlushFileBuffers(hPipe);
	DisconnectNamedPipe(hPipe);
	CloseHandle(hPipe);
	return 0;
}

int _tmain(int argc, TCHAR* argv[]) {
	HANDLE hPipe;
	DWORD dwTid;

#ifdef UNICODE 
	_setmode(_fileno(stdin), _O_WTEXT);
	_setmode(_fileno(stdout), _O_WTEXT);
	_setmode(_fileno(stderr), _O_WTEXT);
#endif
	
	while (1) {
		//cada vez que um cliente se ligar é criada uma nova thread
		hPipe = CreateNamedPipe(
			NOME_PIPE, 
			PIPE_ACCESS_DUPLEX,
			PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 
			PIPE_UNLIMITED_INSTANCES, 
			BUFFSIZE, 
			BUFFSIZE, 
			10000, 
			NULL);
		if (ConnectNamedPipe(hPipe, NULL)) {
			CreateThread(NULL, 0, atendeCliente, (LPVOID)hPipe, 0, &dwTid);
		}
	}
	return 0;
}

Util:

#define TAM 100
#define NOME_PIPE TEXT("\\\\.\\pipe\\teste")
#define BUFFSIZE 1024
Tags : ,

Apontamentos teóricos

::Slides05 – SO2 – 2022 – BibliotecasWindows v18.pdf
O ficheiro .lib (opcional). Usado para os casos de ligação implícita
O ficheiro .DEF (opcional). Método alternativo para identificar as funções em ligação explícita (identificação por número de ordem em vez de pelo nome)

O método mais habitual é o de identificar as funções pelo nome. A identificação posterior por parte dos programas que usam a DLL é feita então de duas formas: ligação implícita e ligação explícita
Em ambos os casos a DLL tem que estar sempre presente durante a execução

Ligação implícita
É usado um ficheiro auxiliar .lib = biblioteca de ligação estática para estabelecer a ponte entre o programa e as funções na DLL
O programa que usa as funções apenas precisa do .h e do .lib durante a compilação e usa as funções quase como se elas fizessem parte do seu código.
Ligação explícita
Não é necessário nenhum .lib, e, eventualmente, nem sequer um .h durante a compilação
O programa que usa a DLL tem que carregar explicitamente a DLL e depois procurar as funções pelo nome, invocando-as por ponteiro.

Código da DLL
Uma DLL é uma variante de um ficheiro executável.
Não se destina a executar por si só.
Age como um repositório de funções e recursos para ser usado por outros programas

Exemplo:
um função na DLL
#include
// Função “local“ -> não vai ser exportada
int factorial (int n) { // calcula factorial de n
int res = n;
n–;
while (n>1) {
res = res * n;
n–;
}
return res;
}

// Variável exportada
__declspec(dllexport) int nExemplo = 0;

// Função exportada
__declspec(dllexport) int fnExemplo(int n) {
if (n<0) n = -1; return factorial(n); } Resultado da compilação exemplo.dll → Código da DLL exemplo.lib → Ficheiro auxiliar para ligação implícita Ligação implícita Forma de uso da DLL que oculta o facto de se estarem a usar recursos externos ao programa. As funções aparentam estar no próprio programa e o seu uso é muito simplificado. A carga da DLL, procura de funções e libertação da DLL são feitas automaticamente por código disponibilizado numa pequena biblioteca de ligação estática (o .lib) que faz a ponte entre o programa e a DLL. O .lib contém funções com o mesmo nome que as existem no .dll, reencaminhando as chamadas para lá A DLL é carregada automaticamente no início da execução e libertada no fim. Se não estiver presente, o programa não corre de todo. A DLL mantem-se sempre em memória e utilizando assim mais memória Nesta forma, os recursos da DLL aparentam estar no programa tal como se de uma biblioteca de ligação estática se tratasse. Na ligação implícita, se a DLL não estiver presente, todo o programa é impedido de correr. Na ligação implícita, o compilador consegue efectuar algumas validações no uso das funções (pela existência do ficheiro .h). Se existirem muitas DLL com ligação implícita, o processo tem um início demorado pois todas essas DLL são carregadas no início. A ligação implícita requer a biblioteca estática para fazer a ponte com a DLL. Na ligação implícita as DLL mantêm-se mapeadas durante a execução do processo. Ligação explícita A DLL é tratada como um conjunto de recursos que é trazida para memória e usada quando é necessário de uma forma explícita e totalmente controlada pelo programador do programa “cliente” da DLL. O programador decide quando é que precisa de carregar a DLL e carrega-a explicitamente e apenas nessa altura O programador obtém acesso aos recursos da DLL procurando explicitamente as funções que precisa e invoca-as através de um ponteiro O programador liberta a DLL quando já não precisa mais dela, libertando recursos ao processo e ao sistema Nesta forma torna-se óbvio ao programador que está a usar recursos externos ao seu programa faz uso da API WIN32: LoadLibrary / LoadLibraryEx GetProcAddress //aceder a uma função/variavel exportada FreeLibrary //liberta o módulo do espaço do processo Se a DLL não estiver presente, ou se houver algum erro que impeça a sua utilização, o programa não tem que terminar. Apenas a funcionalidade associada à DLL fica inviabilizada Na ligação explícita as DLL são carregadas em qualquer altura. A ligação explícita permite carregar as DLL apenas quando necessário e libertá-las assim que não são necessárias. Isto permite poupar recursos ao processo e sistema ::Slides06 – SO2 – 2022 – Threads_v16.pdf Cada processo tem pelo menos uma thread (thread inicial ou principal) A partir de uma thread pode-se lançar outra thread O facto da thread inicial ser a primeira (ou ser chamada de principal) não lhe confere nenhum privilégio em particular sobre outras threads que venham a existir no processo A criação da thread está associada a uma função. Quando essa função terminar, a thread também termina. API32 threads: CreateThread //Cria uma thread nova ExitThread //Termina a thread GetExitCodeThread //Obtém o código de terminação Terminação de um thread (a partir de outra) Usa-se uma variável de condição acessível às threads envolvidas Para simplicidade vai-se assumir que se trata de uma variável global (mas não precisa de ser assim –> ponteiro passado por parâmetro)

Privilégios de acesso:
SYNCHRONIZE, Permite usar o handle em funções de sincronização
THREAD_ALL_ACCESS, Todos os acessos suportados pelo sistema
THREAD_SUSPEND_RESUME, Permite suspender/des-suspender a thread através do handle obtido

::Slides07 – SO2 – 2022 – Sincronizacao v17.pdf
A sincronização em Win32, aplica-se a:
Serialização de acções (coordenação / cooperação)
Competição por acesso a um recurso
Acesso exclusivo a um recurso (exclusão mútua / secções críticas)

é feita através de espera e sinalização em objectos (através dos seus handles):
O handle de um objecto pode ser usado numa função wait
Os objectos podem estar apenas nos estados assinalado / nãoassinalado

Objectos que podem ser usados em sincronização:
Evento (objectos-evento – não confundir com as mensagens WM_….)
Mutexes
Critical Sections
Semáforos
Waitable Timers

Outros objectos que podem ser usados em sincronização:
Processos
Threads
Input de consola
Notificações de alteração

Objectos de Sincronização no API do Windows:
Semáforos
Ferramenta de sincronização quase universal.
Apropriado a quase todos os casos.
Resolve situações de exlusão mútua, competição e coordenação
Em algumas situações não é o mecanismo mais simples ou mais directo

Mutexes
Resolvem situações de exclusão mútua entre threads e entre processos.
Melhor mecanismo para situações de exclusão mútua que envolvam
processos diferentes.

Critical Section
Versão simplificada de mutexes para uso local a um único processo (com várias threads) em situações de exclusão mútua
O API destes objectos foge à forma habitual usada nos restantes

Waitable Timers
Mecanismos apropriados a acontecimentos relacionados com a passagem de intervalos de tempo

Eventos
Objecto de uso não-específico – o significado e forma de utilização depende muito da lógica da aplicação.
Não são apropriados a situações de exclusão mútua. São mais indicados para cenários de cooperação ou coordenação.

Funções de espera:
WaitForSingleObject / WaitForSingleObjectEx
Espera que um determinado objecto esteja assinalado ou que um determinado timeout se esgote (ou que seja recebido uma notificação de I/O completo)

WaitForMultipleObjects / WaitForMultipleObjectEx
Espera por um conjunto de objectos de uma só vez

WaitForSingleObject retorna:
WAIT_ABANDONED // A thread que detinha o objecto terminou sem o libertar
WAIT_OBJECT_0 //O objecto de sincronização foi libertado
WAIT_TIMEOUT //Ocorreu o tempo máximo de espera

Obtenção dos handles para espera nas funções

Na thread que cria os objectos de sincronização:
CreateEvent //(para eventos)
CreateMutex //(para mutexes)
CreateSemaphore // (para semáforos)

Em outras threads:
OpenEvent //(para eventos)
OpenMutex //(para mutexes)
OpenSemaphore //(para semáforos)

Flags de acesso nas funções open:
Semáforos: SEMAPHORE_MODIFY_STATE (SEMAPHORE_ALL_ACCESS)
Eventos: EVENT_MODIFY_STATE (EVENT_ALL_ACCESS)
Mutexes: MUTEX_MODIFY_STATE (MUTEX_ALL_ACCESS)
Timers: TIMER_MODIFY_STATE (TIMER_ALL_ACCESS)

Sincronização com objectos processo e threads:
A função CreateProcess cria um objecto que representa o novo processo.
Inicialmente o objecto está no estado não-assinalado
O estado passa a assinalado quando o processo termina
Idem para threads

Funções mais úteis para este tipo de objecto de sincronização:
WaitForInputIdle //Espera que o processo esteja bloqueado à espera de input
WaitForSingleObject / WaitForSingleObjectEx // Espera que um processo esteja assinalado (ou seja, tenha terminado)

Sincronização com eventos:
Servem para uma thread indicar que “algo” aconteceu a uma ou mais threads que aguardavam por esse algo.

Um objecto evento é um objecto de sincronização cujo estado pode ser assinalado explicitamente com a função SetEvent

os eventos podem ser usados:
Reset manual (“passam todos até alguém fechar”)
Auto-reset (“só passa o primeiro”)

funções:
HANDLE CreateEvent(..)
HANDLE OpenEvent(..)
BOOL SetEvent(..) //fica assinalado
BOOL ResetEvent(..) //fica não assinalado

Sincronização com mutexes:
Permitem a duas ou mais threads (ou processos) aguardarem por acesso a uma zona de código (”seção crítica”) que manipula um recurso (ex., dados)
Um objecto mutex permite resolver directamente as situações de exclusão mútua
Encontra-se no estado assinalado quando nenhuma thread o possui
Assim que uma thread obtém a sua posse (através das funções de espera), o estado do mutex passa a não-assinalado
Uma thread que tenha a posse de um mutex pode libertá-lo através da função ReleaseMutex. O mutex em questão passa ao estado assinalado

HANDLE CreateMutex(..) //cria ou obtem acesso a um mutex com ou sem nome (NULL), sem nome só ficam restringidos a threads do mesmo processo.
HANDLE OpenMutex(..) //acesso ao mutex
BOOL ReleaseMutex(..) // libterta a possse do mutex

Sincronização com Critical Sections:
podem ser partilhados por processos diferentes. Servem apenas para sincronização de threads dentro do mesmo processo.

Sincronização com semáforos:
Generalização do conceito de mutex – Permite acesso a mais do que um processo/thread em simultâneo
é mantida a contabilização de operações esperar/assinalar que sobre ele são efectuadas
Podem ter nome o que permite que sejam usados por processos diferentes
as funções de espera efectuam a operação de espera sobre o semáforo, decrementando o seu contador interno. Se o contador atinge o valor zero, o estado do semáforo passa a não-assinalado e a thread que que efectuou a espera fica bloqueada
A função ReleaseSemaphore permite efectuar a operação assinalar num semáforo. Uma das thread que estavam bloqueadas à espera nesse semáforo é desbloqueada

funções:
HANDLE CreateSemaphore(..) // cria ou obtem acesso a um semáforo com ou sem nome (NULL)
HANDLE OpenSemaphore(..) //obtem um handle para uma semáforo que existe
BOOL ReleaseSemaphore(..) // Incrementa o contador interno do semáforo na especificada no parâmetro lReleaseCount

::Slides08 – SO2 – 2022 – FicheirosMapeados v16.pdf
Ficheiros mapeados em memória – Memória partilhada
O mecanismo de ficheiros mapeados permite duas funcionalidades:
Mapear (parte de) um ficheiro em memória, operando sobre ele como se se tratasse de uma matriz de bytes
Partilhar um bloco de memória entre processos para situações de comunicação entre processos

Restrições ao uso de ficheiros mapeados:
Manipulação do conteúdo da memória partilhada quando usada para comunicar entre processos (uso em simultâneo em vários processos):
Apenas se pode colocar informação que faça sentido em todos os processos envolvidos.
estão excluídas coisas que só façam sentido no processos que as criou, tais como handles e ponteiros

Uso em simultâneo (concorrente) da mesma memória partilhada por vários processos/threads
Trata-se de um caso típico de acesso concorrente a dados partilhados
Normalmente exigirá o uso de mutexes/semáforos para garantir que duas threads/processos não destroem o trabalho uma da outra e para garantir que o conteúdo dos dados permanece coerente

Uso de ficheiros mapeados:
1 – Obtém handle para o ficheiro
CreateFile //(indica-se o ficheiro)
2 – Criar o objecto FileMapping usando o handle anterior (handle do ficheiro)
CreateFileMapping // (indica-se o handle e o tamanho)
3 – Mapear uma vista do ficheiro no seu espaço de endereçamento
MapViewOfFile //(indica-se a zona pretendida e obtém-se um ponteiro)
4 – Usa a memória partilhada através da vista (sintaxe habitual ponteiros * -> [ ] )
5 – Desmapeia a vista
UnmapViewOfFile //(indica-se o ponteiro)
6 – Fecha o handle do objeto Ficheiro Mapeado
CloseHandle //(handle do filemapping)
7 – Fecha o handle do ficheiro
CloseHandle //(handle do ficheiro)

assim, m processo, inicialmente:
1 – Cria um objecto memória partilhada, obtendo um handle
CreateFileMapping
2 – Mapeia uma vista da memória partilhada no seu espaço de endereçamento
MapViewOfFile
3 – Usa a memória partilhada através da vista (ponteiros ou [ ] )
4 – Desmapeia a vista, eventualmente no final do processo
UnmapViewOfFile
4 – Fecha o handle
CloseHandle

e outro/restantes processos:
1 – Obtém handle para o objecto memória partilhada
OpenFileMapping
2 – Mapeia uma vista da memória partilhada no seu espaço de
endereçamento
MapViewOfFile
3 – Usa a memória partilhada através da vista (ponteiros ou [ ] )
4 – Desmapeia a vista, eventualmente no final do processo
UnmapViewOfFile
5 – Fecha o handle
CloseHandle

funções:
HANDLE WINAPI CreateFileMapping (..) //Esta função é usada para criar um objecto de memória partilhada.
HANDLE WINAPI OpenFileMapping(..) // Esta função é usada para obter acesso ao objecto de memória partilhada (dado o seu nome) criado (normalmente) por outro processo/thread.
LPVOID WINAPI MapViewOfFile (..) //esta função mapeia uma porção da memória partilhada, devolvendo o ponteiro para onde ficou mapeada a vista
LPVOID WINAPI UnmapViewOfFile(..) //Esta função desmapeia uma vista do espaço de endereçamento do processo que a invoca –> o processo deixa de “ver” essa zona de memória partilhada

::Slides09 – SO2 – 2022 – Sincronizacao – Prod-Cons v12.pdf
Produtor/Consumidor – Resolução com recurso a semáforos

Sincronização:
1. Sistemas compostos por mais do que uma entidade activa (processos, threads) que usam recursos e dados partilhados entre si exigem a coordenação do acesso a recursos e dados
2. Sistemas compostos por mais do que uma entidade activa em que uma das entidades é dependente de acontecimentos originados por outra(s) vai exigir mecanismos para coordenar a sua execução em função da execução das outras entidades

Exemplos concretos da vida real
Sistemas cliente servidor envolvendo vários utilizadores ou postos; programas multi-threaded

Situações típicas (exemplos) que envolvem sincronização
Cooperação
Diversas actividades concorrem para a conclusão de uma aplicação comum
Situação que pode ser resolvida algoritmicamente para as aplicações envolvidas com recurso a mecanismos do sistema de suspensão e sinalização
Os processos querem sincronizar as suas acções de forma explícita uns com os outros. Em vez de competição e autorização para avançar, podem voluntariamente auto-suspenderem-se até receberem uma notificação

Competição
Diversos processos competem pela obtenção de um recurso limitado
A competição deve ser resolvida de forma a que o recurso seja utilizado de forma coerente
É complicado e/ou ineficiente resolver esta situação sem ajuda do sistema operativo
Pode ser visto como uma generalização da exclusão mútua: A competição é feita sobre recursos com mais do que uma unidade.
A sincronização é concretizada pelo SO para manter a coerência

Exclusão mútua
A utilização concorrente de uma zona de dados (ou recurso) partilhada pode levar a que os dados fiquem inconsistentes
A utilização desses dados (ou recurso) deve ser feita de uma forma exclusiva: apenas uma entidade activa utiliza o recurso.
A execução de uma secção de código que manipula dados partilhados constitui uma situação típica de acesso em exclusão mútua
Este caso é muito frequente e muito importante. Está também na base da tomada de decisões críticas que podem ter um resultado incorrecto se não for devidamente acautelado

Semáforo:
Constituído por uma estrutura de dados que inclui
Variável de controlo (inteira) = número de autorizações restantes
Fila de espera (de processos / threads bloqueados)
o semáforo bloqueia o processo (thread) e não ocupa o processador
Elimina a espera activa

tipos de semáforos:
Semáforo binário ou MUTEX, Tem apenas uma “autorização” – serve essencialmente para resolver situações de exclusão mútua
Semáforo, Genérico. Permite n “autorizações”, Usado para qualquer tipo de situação (inclusive exclusão mútua). Uso comum em situações de competição e controlo de recursos (por exemplo, cenário produtor/consumidor)

As operações fundamentais sobre semáforos são
Esperar – Requisita o recurso / Requisita uma autorização / (pede acesso a uma secção crítica)
Assinalar – Liberta o recurso / Devolve uma autorização / (liberta a secção crítica)

Método
Cada semáforo tem um contador interno. As operações sobre o semáforo são as de esperar (diminuir o contador) e assinalar (aumentar o contador). Esse contador actua como número de processos que ainda podem passar sem ficarem bloqueados.
Distinguir entre semáforos para exclusão mútua e semáforos para gestão de recursos

Lógica de funcionamento interno de um semáforo
Esperar(Semáforo) //Decrementa a variável de controlo
Assinalar(Semáforo) //Incrementa a variável de controlo

exemplo:
optimizado
Semáforo sem = CriarSemaforo(1);
/* … */
int escreve(tipo_dados valor) {
esperar(sem);
var_partilhada=valor;
assinalar(sem);
}

Produtor/Consumidor – versão com buffer circular, exemplo:
#define DIM … /* tamanho do buffer */
typedef … item; /* a estrutura exacta não é importante */
item buffer[DIM]; /* apenas para simplificação da exposição */
int in, out; /* assumir que DIM cabe em “int” */

/* inicialização (”Semaforo” já definido algures) */
Semaforo sem_mutex_p, sem_mutex_c;
Semaforo sem_itens; // garante que nunca um consumidor tentará utilizar a mesma posição no buffer que um produtor.
Semaforo sem_vazios; // garante que nunca um produtor tentará utilizar a mesma posição no buffer que um consumidor.

/* inicialização */
in = out = 0;
sem_mutex_p = criar_semaforo(1); // 1 -> semáforo de exclusão mútua
sem_mutex_c = criar_semaforo(1); // 1 -> semáforo de exclusão mútua
sem_itens = criar_semaforo(0); // 0 itens produzidos inicialmente
sem_vazios = criar_semaforo(DIM); // DIM elementos disponíveis

Produtor
while (COND) {
item_p = produz_item();
esperar(&sem_vazios); // contabilizar o número de elementos livres no buffer

esperar(&sem_mutex_p); //semáforo de exclusão mútua produtores
buffer[in] = item_p;
in = (in + 1) % DIM;
assinalar(&sem_mutex_p); //semáforo de exclusão mútua produtores

assinalar(&sem_itens); // semáforo para contabilizar o número de itens disponíveis

}

Consumidor
while (COND) {
esperar(&sem_itens); // semáforo para contabilizar o número de itens disponíveis

esperar(&sem_mutex_c); //semáforo de exclusão mútua consumidores
item_c = buffer[out];
out = (out + 1) % DIM;
assinalar(&sem_mutex_c); //semáforo de exclusão mútua consumidores

assinalar(&sem_vazios); // contabilizar o número de elementos livres no buffer
trata_item(item_c);
}

::Slides10 – SO2 – 2022 – NamedPipes v16.pdf
Comunicação interprocesso em Win32 com Named Pipes

Os named pipes podem ser:
De uma só via, O processo ou lê ou escreve (mas não ambos) na sua extremidadedo pipe
De duas vias (pipe duplex), O processo pode ler e escrever na sua extremidade do pipe (mas não ao mesmo tempo: tem que se gerir a sequência de leituras/escritas)

Operações do lado dos servidor:
Criação: CreateNamedPipe
Esperar ligação de um cliente: ConnectNamedPipe
Escrita/leitura: ReadFile / WriteFile

Operações do lado do cliente
Associação a um pipe existente: CreateFile ou CallNamedPipe
Esperar que um servidor esteja à escuta num pipe: WaitNamedPipe
Escrita/leitura: ReadFile / WriteFile

funções:
HANDLE WINAPI CreateNamedPipe(..) //criar namedPipe
BOOL WINAPI ConnectNamedPipe(..) //esperar ligação
BOOL WINAPI DisconnectNamedPipe(..) //terminar ligação

no Servidor:
CreateNamedPipe para criar a primeira instância (e seguintes) do named pipe
ConnectNamedPipe para aguardar um pedido de ligação à instância do named pipe. O atendimento dessa instância pode ser feito numa thread independente, libertando o servidor para criar outra instância e aguardar + processar outro cliente nela
FlushFileBuffers Para desligar do cliente, o servidor aguarda que os dados já tenham sido lidos pelo cliente.
DisconnectNamedPipe Após este passo pode-se desligar a instância do pipe
CloseHandle

no Cliente:
CreateFile para obter um handle (do lado cliente) para uma instância do named pipe
WaitNamedPipe aguardar que exista uma instância do servidor do pipe disponível (= aguardar que o servidor faça um ConnectNamedPipe). Cada cliente que se liga consome (ocupa) uma instância
O cliente interage com o servidor de acordo com um protocolo qualquer predefinido para essa aplicação cliente-servidor
O cliente termina a interação fechando os handles (com reflexo no servidor).

Acerca dos modos
PIPE_READMODE_BYTE
PIPE_READMODE_MESSAGE
Têm que bater certo no lado do servidor e no lado do cliente
PIPE_TYPE_BYTE – PYPE_READMODE_BYTE
PIPE_TYPE_MESSAGE – PYPE_READMODE_MESSAGE

Modo BYTE
O sistema não se preocupa com a fronteira entre mensagens: é tudo uma byte stream
Modo MESSAGE
O sistema percebe que um write corresponde a uma mensagem e ajuda a gerir na leitura. no caso em que se enviam mensagens de tipo e tamanho previamente conhecido

exemplo:
//o servidor
#include
#include
#define BUFSIZE 4096
int _tmain(int argc, TCHAR *argv[]) {
BOOL fConnected;
DWORD dwThreadId;
HANDLE hPipe, hThread;
LPTSTR lpszPipename = TEXT(“\\\\.\\pipe\\mynamedpipe”);
while (1) {
hPipe = CreateNamedPipe(
lpszPipename, // nome do pipe
PIPE_ACCESS_DUPLEX, // acesso read/write (duplex)
PIPE_TYPE_MESSAGE | // pipe to tipo message
PIPE_READMODE_MESSAGE | // modo message-read
PIPE_WAIT, // modo “blocking”
PIPE_UNLIMITED_INSTANCES, // max. instâncias
BUFSIZE, // tam. buffer output
BUFSIZE, // tam. Buffer input
NMPWAIT_USE_DEFAULT_WAIT, // time-out para o cliente
NULL); // atributos segurança default
if (hPipe == INVALID_HANDLE_VALUE) {
_tprintf(TEXT(“CreatePipe falhou”));
return 0;
}
// Aguarda a ligação de um cliente
fConnected = ConnectNamedPipe(hPipe, NULL);
if (!fConnected && (GetLastError() == ERROR_PIPE_CONNECTED) )
fConnected = TRUE;
if (fConnected) {
// atender o cliente (apresentado mais adiante)
AtendeCliente(hPipe) // feita mais adiante
// Este exemplo, não sendo multi-thread
// implica que só trata 1 cliente de cada vez (em série)
}
else
// Este cliente não se conseguiu ligar
// por isso fecha-se o pipe (continua para o prox cliente)
CloseHandle(hPipe);
// Próxima iteração -> mais uma instância e possível cliente
} // ciclo principal (apenas depois de ter atendido este cliente)
return 1;
} // fim do programa servidor

//o cliente
void AtendeCliente (HANDLE hPipe) {
char chRequest[BUFSIZE];
char chReply[BUFSIZE];
DWORD cbBytesRead, cbReplyBytes, cbWritten;
BOOL fSuccess;
while (1) { // ciclo p/ permitir haver N x pergunta-resposta)
// Lê dados do cliente via pipe. // mas cliente só vai fazer 1x
fSuccess = ReadFile(
hPipe, // handle para o pipe
chRequest, // buffer para receber os dados
BUFSIZE * sizeof(char), // tam do buffer (bytes a ler)
& cbBytesRead, // num. de bytes lidos
NULL); // não é overlapped I/O
// se não houver mais dados sai
if (! fSuccess || cbBytesRead == 0) break;
// Escreve a resposta para o pipe
fSuccess = WriteFile(
hPipe, // handle para o pipe
chReply, // buffer com os dados
cbReplyBytes, // num. de bytes a escrever
& cbWritten, // num. de bytes escritos
NULL); // não é overlapped I/O
// verifica operação efectuada
if (! fSuccess || cbReplyBytes != cbWritten)
break;
} // fim do ciclo de escrita
// faz flush ao pipe para garantir que o cliente já leu tudo
// antes de desligar esta instância do pipe
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);
} // fim do atendimento deste cliente

#include
#include
#define BUFSIZE 512
int _tmain(int argc, TCHAR *argv[]) {
HANDLE hPipe;
LPTSTR lpvMessage;
TCHAR chBuf[BUFSIZE];
BOOL fSuccess;
DWORD cbRead, cbWritten, dwMode;
LPTSTR lpszPipename = “\\\\.\\pipe\\mynamedpipe”;
lpvMessage = argv[1]; // msg dada na linha de comando
// tenta repetidamente abrir o named pipe (em ciclo)
// espera se for preciso
while (1) { // o ciclo é só para abrir ligação com servidor
hPipe = CreateFile( // tenta obter um handle para o pipe
lpszPipename, // nome do pipe
GENERIC_READ | // acesso read & write
GENERIC_WRITE,
0, // sem “sharing”
NULL, // attributos segurança default
OPEN_EXISTING, // deve abrir um pipe já existente
0, // atributos default
NULL); // sem “ficheiro” “template”
// se obteve um handle válido, sai do ciclo
if (hPipe != INVALID_HANDLE_VALUE)
break; // pipe aberto -> sai do ciclo
// erro = outro que não PIPE_BUSY -> desiste
if (GetLastError() != ERROR_PIPE_BUSY) {
printf(“Não foi possível abrir o pipe”);
return 0; // num programa real: não terminar logo a
} // aplicação. Pode dar para fazer outras tarefas
// ERROR_PIPE_BUSY – todas as instâncias estavam ocup.
// tenta mais 1 (ou N) vezes mas espera entre cada tent.
// (espera 20 segundos “porque sim” – é só um exemplo )
// isto é uma estratégia definida pelo programador
// e podia ser diferente
if (!WaitNamedPipe(lpszPipename, 20000)) {
printf(“não foi possivel abrir o pipe”);
return 0;
}// O ciclo serve para tentar várias vezes porque o serv
// pode estar ocupado. Pode-se sair após N tentativas.
// Com serv multi-threaded este ciclo é menos importante
// o ciclo termina quando consegue abrir o pipe
// sai do ciclo via break (mais atrás)
} // fim do ciclo while em que tenta ligar ao pipe
// Neste momento o pipe está ligado ao servidor
// mudar para modo de leitura de mensagem
// porque foi esse o modo (MESSAGE) usado no servidor
dwMode = PIPE_READMODE_MESSAGE;
fSuccess = SetNamedPipeHandleState(
hPipe, // handle para o pipe
& dwMode, // novo pipe mode
NULL, // maximum bytes = NULL (não altera)
NULL); // maximum time = NULL (não altera)
if (!fSuccess) {
printf(“SetNamedPipeHandleState falhou”);
return 0;
}
// lógica de interação nesta aplicação (servidor é diferente)
// -> cliente escreve 1 msg, servidor responde, fim
// 1º: cliente escreve,
// 2º cliente lê
// 1º Escrever uma mensagem no pipe
fSuccess = WriteFile( // no exemplo: envia sempre chars
hPipe, // handle para o pipe
lpvMessage, // mensagem
(lstrlen(lpvMessage)+1)*sizeof(TCHAR), // tam da msg
&cbWritten, // bytes escritos
NULL); // não é uma operação overlapped
if (!fSuccess) {
_tprintf(TEXT(“WriteFile falhou“));
return 0;
}
// 2º Ler dados do pipe
do {
fSuccess = ReadFile(
hPipe, // handle para o pipe
chBuf, // buffer para receber os dados
BUFSIZE * sizeof(TCHAR), // tam. do buffer
& cbRead, // num. bytes a ler
NULL); // não é overlapped
// se não houver mais dados sai
if (! fSuccess && GetLastError() != ERROR_MORE_DATA)
break;
printf(“%s\n”, chBuf ); // mostra informação lida
} while (!fSuccess); // repete até não haver mais dados
// = “até a resposta terminar” (o serv não envia mais nada)
CloseHandle(hPipe);
return 0;
} // fim do exemplo

::Slides11 – SO2 – 2022 – AppGraficasWin32 v23.pdf
Como chegar aos dados da janela em questão a partir do handle?
Colocar os dados em questão numa variável estruturada.
Colocar na estrutura do Windows que descreve a janela um ponteiro para essa variável estruturada com os dados em questão (reservando espaço para tal na estrutura WNDCLASSEX)

1) Registar o ponteiro para a estrutura com os dados nos bytes extra associados à janela
wcl.cbWndExtra = sizeof(EstruturaDados *);
2) Colocação de um ponteiro (criação da janela / na função main)
EstruturaDados dados; …
SetWindowLongPtr(hwnd, 0, (LONG_PTR) &dados);
3) Obtenção do ponteiro (na função da janela)
EstruturaDados * pont = (EstruturaDados *) GetWindowLongPtr(hwnd, 0);

A função da janela é modificada da seguinte maneira:
WM_CREATE,
WM_LBUTTONDOWN
WM_MOUSEMOVE
WM_LBUTTONUP
WM_PAINT

Tags : , , , ,

Proposta de trabalho

Encontrei este texto com uma proposta de trabalho para um programador em Construct 3:
“Boas pessoal, estou à procura de um programador que esteja interessado em trabalhar num projecto que estou a desenvolver.
O projecto é um software de animação que permite aos utilizadores animarem sprites com o uso de ossos, e através de sliders. Os resultados podem ser depois exportados como video, frames individuais ou spritesheets para serem usados em videojogos, ou o que o utilizador desejar.
A base do programa já está bastante desenvolvida, mas infelizmente não tenho tido muito tempo para continuar a desenvolvê-lo. Daí estar à procura de alguém.
O programa está a ser feito em Construct 3 (é necessário saber usar este programa), é essencial conhecimento de Arrays, Loops, Funções, referenciar Instâncias. Conhecimento de Javascript também é útil mas não obrigatório.
O orçamento é de $1000 podendo o pagamento ser feito por milestones ao longo do projecto ou no fim de estar completo (o que preferir).
Se estiveres interessado contacta-me por e-mail com alguns trabalhos que tenhas feito antes, para creativemethod.studios@gmail.com”

 

Tags :

Humble Game Dev Assets: Polygon Game Dev Assets (uma campanha)

A malta do Humble tem a decorrer a primeira campanha de 2022 relacionada com Game Dev, e desta vez são 3D assets. Do texto surge: “Looking for eye-catching 3D characters, environments, props, and effects to help you develop your game? This POLYGON bundle could be the instant low-poly, high-style library you’re seeking. Build a high-seas adventure with the help of the award-winning Pirates pack. Find assets for your fantasy prototype, sci-fi saga, or vision of the zombie apocalypse. Create offices, towns, and farms”

A lista de material tem:
Synty Store $10 USD Voucher
POLYGON City Zombies
POLYGON City Characters
POLYGON Fantasy Characters
POLYGON Office
POLYGON Pirates
POLYGON Town
POLYGON Farm
POLYGON Sci-fi Space
POLYGON Icons
POLYGON Mini Fantasy Characters
POLYGON Mini Fantasy
POLYGON Fantasy Rivals
POLYGON Prototype
POLYGON Explorer
POLYGON Snow
POLYGON Spy

+infos(oficial): LINK

 

Tags : , , , , , ,

Proposta de trabalho (em Lisboa)

“As Lead Game Designer, you will help shape the vision for a survival open-world crafting game set in the Dune universe. You will manage designers in one or more strike teams and drive design and content implementation efforts in sections of the game, reporting to the game director. You will assist the design team in captivating players with memorable experiences through mentor-driven leadership. You will effectively liaise with teams which depend on the content your team delivers, as well as making sure your team gets the support they need from other teams.

The Lead Game Designer has experience planning and implementing game features and content. You will work with content design teams and narrative to ensure that the content and features are true to the Dune IP, while delivering a satisfying game experience. You will be challenged to create content that supports the core fantasies of Dune. Most importantly, the Lead Game Designer will oversee the creation of the game toolbox, as well as make sure content designers use the toolbox optimally.

How you can have an impact in your position:
Lead the designers in one or more strike teams through direct mentorship
Assist in the creation of the Content Bible for the game
Expand the game world through game features and content, following the creative vision and Content Bible
Create quality goals, workflows, and guides for all game features and content relevant to your areas of ownership
Collaborate and build relationships with various strike teams that are working on their sections of the game
Plan creation of content and features, including conception, presentation, iteration, and documentation in relevant ownership areas
Feedback on designs, content and features and help drive efforts to improve the quality of the game

We are looking for someone that has:
A bachelor’s degree
5+ years of experience in the game industry working in a game design capacity
2+ years of experience leading/managing a team
Shipped titles in a professional capacity
Extensive understanding of design processes including NPC design, feature design, level design, content design, as well as experience implementing features and content
Passion for leadership and mentoring
Clear, effective communication skills across teams and cultures
Motivation and drive to collaborate and advance positive change in a studio environment
The ability to work diligently while thinking critically and resolving complex issues

In addition, the perfect candidate has:
Experience working on survival games
Enjoys playing survival games
Familiarity with Dune and the Dune IP

We evaluate candidates on an ongoing basis and recommend candidates to apply as soon as possible!

Please apply in English.

Why Funcom?
We are a Scandinavian company and follow Scandinavian work values. For you, that means a flat structure in which you can thrive, be yourself, and leave a mark in the studio and become an ambassador for our company values. We focus on Agile/Scrum methodology, and heavily value the importance of work-life balance in employee culture. Funcom values close-knit, collaborative individuals who crave creative ownership, a drive for constructive input, and a never-ending pursuit of evolution and quality.
We have a dynamic, inclusive, challenging, and engaging work culture, with a basis of continued training and career development opportunities. Come join us in a friendly environment of enthusiastic professionals willing to go the extra mile to deliver world-class games.

Para além desta proposta existem outras também para Lisboa como é o caso de:

+infos(oficial): LINK

Tags :

Proposta de trabalho (em Almada)

“A Marmalade Game Studio PT tem neste momento 2 vagas abertas:
UX/UI Artist
The role
Based in our Almada studio (Lisbon, Portugal), with flexible working options available, this is a role for someone who can fit in with our team of passionate, creative and collaborative professionals. You’ll need to be flexible about tasks, responsibilities and have the ability to transition across development teams.
During the pandemic, we have been working from home. We are not in a hurry to return to the office and will only do so when we feel it is safe.

As a Game UX/UI Artist, some of your responsibilities will include:
Work in a team to define the look and feel of our user interface
Be responsible for the UI of the game, producing style guides, rule sets, and templates
Create, implement and iterate on UI assets and animations
Provide concept sketching, wire-framing, and high-fidelity UX mockups/prototypes.
Work closely with art, design, production, and developers to iterate on the best solutions to UX and UI challenges.

Requirements
Experience as a UX/UI Artist in the games industry or another relevant industry
Strong graphic design skills showcased by a portfolio that meets the quality of Marmalade Games
Ability to explore and create different styles
Experience creating UX prototypes and wireframes
Excellent understanding of typography, composition, color theory, visual design, and interaction design
Basic knowledge of animating assets for conceptual purposes
Ability to respond efficiently to problems and conflicts that may influence game development
Great communication skills
Knowledge of Photoshop, Illustrator, and Unity
Optional but valuable
Experience implementing and animating UI assets in Unity

Benefits
Competitive salary
Generous holiday allowance consisting of 22 days + a bonus 3 days’ holiday when the offices are closed over Christmas and New Year + extra holiday for long service (up to 3!)
Private health insurance
Private life insurance
Great work environment

e um Office Manager
The role
Based in our Almada studio (Lisbon, Portugal), this is a role for a person of sound judgment and strong communication and problem-solving skills. As an Office Manager at MGS, you will be in charge of making sure everything runs smoothly, developing procedures and implementing them to achieve operational efficiency, and nurturing a pleasant work environment for the team.
This position is full-time and on-site. During the pandemic, the successful candidate will be required to work from home. As a company we’re not in a hurry to return to the office and will only do so when it feels safe.

As our Office Manager, some of your responsibilities will include:
Meet and greet visitors
Look after our office space to ensure it is kept to the highest standards of hygiene and appearance
Interact with different stakeholders, i.e. clients, suppliers, business partners and colleagues.
Provide direct administrative support as needed, including scheduling appointments, meetings, and events, and arranging travel, visas and accommodation as required
Update and maintain staff records including staff details, staff absences and holidays.
Oversee and maintain office equipment for uninterrupted function, identify and fulfil office supply needs, maintain, and manage vendors, coordinate food and water delivery as needed.
Manage all aspects of the office’s space/infrastructure planning (moves, adds, and changes to workstations) and provide answers, resources, and solutions as requested
Facility management duties
To develop and improve health and safety procedures within the company, in order to promote general best practises in health and safety issues amongst all employees
Coordination of reports, email and general written correspondence
Responsible for processing of expenses, organising invoices and receipts, and liaising with our accountants and financial department.
To ensure all office equipment is in working order and maintained appropriately

Required
Proven office management, administrative, or assistant experience
Excellent time management skills and ability to multitask and prioritise work
Strong organisational and planning skills
Strives for high quality and pays attention to detail
Knowledge of accounting, data, and administrative management practises and procedures
Excellent written and verbal communication skills
Proficient in Microsoft Office

Benefits
Competitive salary
Generous holiday allowance consisting of 22 days + a bonus 3 days’ holiday when the offices are closed over Christmas and New Year + extra holiday for long service (up to 3 additional days)
Private health insurance
Private life assurance
Great work environment”

+infos(oficial): https://www.marmaladegamestudio.com/careers/

Tags :

Proposta de trabalho (em Oeiras)

A empresa MiniClip em Lisboa tem entre as várias ofertas de trabalho a seguinte:
Quality Assurance Tester – Games Tester

THE POSITION
Miniclip is looking for a Publishing QA Tester (Games Tester) to hire in our Games Development Studio in Tagus Park (Oeiras, Portugal). This is a full-time, permanent position. Please apply only if you have the right to work in Portugal.

DUTIES
Your Primary Responsibilities Will Include
As part of the QA Team, the main responsibility is to ensure the good quality of all 1st party games published by Miniclip.
Test all new game releases/updates and schedule timely quality assurance and testing.
Act as a liaison between development teams, producers and all internal teams involved in the release of a product.
Help in developing, maintaining and improving the roadmap of tests for all releases and updates.
Adapt the existing test documentation to new games and devices while helping to define new testing procedures.
Monitoring game statistics, customer feedback channels, and competing products to constantly question assumptions and make adjustments to our games.
Be part of Miniclip’s quality assurance team, define new test approaches and come up with new ideas to improve testing processes and procedures.

Skills & Experience
We’re looking for a social, hard-working person who enjoys working in a team with other people and is passionate and dedicated about his/her work. The ideal candidate will be strongly skilled in the following
Self-motivated, with excellent organisational skills.
Ability to clearly articulate complex game development project issues.
Confident in exploring new approaches and in communicating with different teams and departments.
Experience in working with teams across different functions and geographical locations.
Fluent in English.
Excellent written and verbal communication skills.
Close attention to detail.
Technical insight on a wide range of physical devices from different manufacturers (Apple, Samsung, etc.) and operating systems (iOS, Android, etc.).
1 – 3 years of experience in the QA and testing fields of game and/or entertainment products and services.
BA or BSc degree or equivalent.

APPLICATION
To apply please submit your CV with your cover letter explaining why you want to be part of our team.

Additional Information
You will be working in our fashionable, open plan studio in Tagus Park (Oeiras, Portugal) with enthusiasts and professionals from the games industry. We like to maintain a very friendly and relaxed atmosphere, with regular team building and social events (virtually, currently). We understand that being tied to a desk all day is not fun and that’s why there is a games area and fridge with complimentary drinks and fruit for all staff.”

+infos(oficial): https://corporate.miniclip.com/careers/vacancies

Tags :

Proposta de trabalho (Lisboa/remoto)

A empresa Volt Games tem várias propostas de trabalho a decorrer, sendo elas:
Game Designer
The Role
As a Game Designer at Volt Games, you will be the lead of MetaStar Strikers, the company’s brand new NFT Sports game, designing new features and polishing the game’s current core loops, while working closely with Volt’s development and art teams.

Responsibilities:
Create new features that make sense with the game’s vision.
Polish the game’s main gameplay to provide a fun experience.
Design and polish MetaStar Strikers’ game core loops.
Work on the economic model and how it connects with the gameplay.
Write all of the game’s new features, designs, economics and loops in documents that can be shared with the rest of the team.
Give constant feedback to the developers and artists on their progresses on the game, to ensure that the execution creates the best possible product.

Skills:
Minimum of 4 years of experience as a Game Designer working in medium/large teams within the video game industry, ideally in mobile games.
Experience working on mid-core designs from initial thought all the way through to implementation.
Interest for the NFT gaming space.
Passion for gaming.

e
Community and Social Media Manager
We are looking for a Community and Social Media Manager who has experience building up communities and promoting games, cryptocurrencies, or blockchain companies through social media, digital PR, and influencer marketing. The role is fully remote.
We’re looking for someone who is able to plan and execute strategies to engage with our audience, identify and build partnerships with top influencers, and (ideally) has existing relationships we can leverage for our NFT Football game.

Responsibilities:
– Communicate the team’s vision to our players
– Manage and activate the communication channels with our audience (Discord, Twitter Medium, Telegram, etc.)
– Develop brand voice, game communications, and editorial calendars. Create a brief, engaging content and copy across major social channels
– Execute engaging and exciting community marketing strategies, aiming towards growing our gaming community
– Understand current trends within the community and provide the team with insights
– Build & manage strong relationships with content creators and influencers from the gaming and crypto space
– Report on social insights and media analytics to internal teams on a regular basis to inform business decisions to maximize growth and user acquisition
– Work with designers to create on-brand, visually appealing graphics that complement social copy and broader strategy

Skills:
– At least 3+ years of experience in a Social Media and influencer marketing position
– Ideally, experience in the gaming industry (not mandatory)
– A good level of understanding of blockchain, cryptocurrency, and NFTs
– Excellent spoken and written communication skills in English
– Passion for gaming and crypto

e também no web site deles surgem as seguintes propostas:
Senior Unity Game Designer
Senior 3D Artist

 

+infos(oficial): https://voltgames.io/

Tags :

Game UI Database

Um recurso interessante para conhecer as UI que são usadas noutros jogos, em diferentes géneros..

+infos(oficial): https://www.gameuidatabase.com/

Tags :

Proposta de trabalho (em Lisboa/hibrida)

“FRVR is looking for a talented and experienced game designer to work exclusively on the game “Worlds FRVR” – a super accessible free-to-play, block-building game made of connected player-created worlds, where players can (co)build and share anything they can imagine. Within this role you will be a part of a fun, talented, inclusive and dedicated game studio.

Key challenges
Being the glue between design, engineering and data to define the overall product experience.
Architecting a balance of the game that makes players fall in love with Worlds FRVR early in their gameplay, whilst giving players a deep sense of belonging in an inclusive, creator and community empowered game geared to drive long-term retention effective monetization.
Play an instrumental role in co-developing the long term roadmap and breathe life into the design vision
What You Will Do
Create the full game design to clearly identify and define any aspects of the game that may impact gameplay as well as establishing and maintaining the Game Design Documentation.
Collaborate with multi-disciplinary team, to guide implementation and maintenance of game systems and mechanics – designing, prototyping and testing gameplay mechanics while identifying opportunities for improvements.
While being accountable for game design, whether new features or changes, set the team up for success by cultivating empowerment and encouraging ownership of any feature a team member is working on.
Ensure stellar game balancing by developing and maintaining mathematical models and plans and coherently define all the rules, player economy, reward and monetization systems.
Operate effectively where you must balance hands-on implementation, and high-level direction – always ensuring expectations are clear, serving as a conduit across the studio.
Contribute to overall team development and provide guidance to junior team members.
You Have What It Takes
Accomplished game designer with 8+ years experience in the role with several years of experience in the mobile F2P space.
Practical understanding and experience in the full development cycle of F2P monetized multiplayer games, which means that you know what it takes to go from initial concept to a full, deeply engaging, and functional game experience.
Deep knowledge and oversight of game economy balancing to match the intended player experience and expected outcomes.
Strong data-science background enabling you to write the necessary scripts for data-mining purposes and running experiments to answer your carefully crafted hypotheses.
Possess a proactive problem-solving attitude and thereby able to look past immediate technical constraints.
A team leadership mindset and a true team player who cares about collaborative culture and ongoing process improvements as part of a cross-functional team consisting of developers, game artists, designers and channel partners.
Ideally, Your Background Should Include
Relevant design or development education, including monetization, value design background.
Work showcases (E. g. in published games, on personal website, or on YouTube).
Community – the Worlds FRVR Game Studio collaborates closely with our community. This should ideally be second nature to you.
A passion for games, game theory development.
In this role, you can either work from our great office in Lisbon, or remotely in a European timezone.”

+infos(empresa): https://careers.frvr.com/

Tags :

Getting Started in Game Design por Joe Slack (uma palestra em video)

Ontem assisti a um seminário/palestra acerca de Game Desing focado em board games, mas que tem vários pontos em comum com os jogos digitais. Foi uma palestra bastante interessante e com algumas dicas sobre o que se passa e como se resolvem determinadas situações. Para além destas informações, o Joe Slack também partilhou outras informações que valem a pena ser revistas. O vídeo foi disponibilizado online..

+infos(oficial): https://boardgamedesigncourse.com/

+infos(o video): LINK

 

Tags : , , , ,

IndieGamesAccelerator Class of 2022

Está a decorrer a chamada de developers indie (pequenos estúdios) que queiram participar no programa da Google, o IndieGamesAccelerator Class of 2022.

Na edição de 2021 colaboraram com os estúdios:
Alex Kozachenko, CEO, HyperBeard
Angelo Lobo, Veteran Game Designer. Ex-Director of Game Design, Zynga
Anna Huerta, Gaming Industry Expert
Are Mack Growen, General Partner and VP of Product Portfolio, LVP
Ashley Ringrose, Founder, SMG Studio
Augusto Petrone, Co-Founder & CPO, The Other Guys
David Yin, CEO, Storms
Ed Chin, Co-Founder & CEO, SuperSolid
Ezequiel Mottillo, Creative Director, etermax
Felipe Hayashida, Chief Marketing Officer, PlayKids
Francisco Cuevas, General Manager for Latin America, Video Game Markers Academy
Gerson Da Silva, Lead Game Designer & Project Manager, Ironhide Game Studio
Gwen Guo, Co-Founder & Creative Director, IMBA Interactive. Chairperson, Singapore Games Association
Iris Kroonstuiver, Talent and Culture, GameHouse
Ivan Carrillo, Managing Partner, Joystick Ventures
Javier Parejo, Co-Founder and CMO, Space Sheep Games
Jayvian Hong, Head of Strategic Partnerships, Miniclip
Jason Schklar, Co-Founder & Chief Game Consultant, UX is Fine!
Joshua Nilson, CEO & Co-Founder, East Side Games
Joline Schouten, Strategic Partnership Manager, GameHouse Original Stories
Lili Lim, Producer, Appxplore
Lucy Hoffman, Co-Founder & COO, Carry1st
Mark Panelo, Head of Partner Relations & Mobile Brand Partnerships, Warner Bros Games
Mark Skaggs, Gaming Expert. Ex-Zynga & EA
Marija llic, Co-Founder, Two Desperados
Mohsin (Mozzy) Ahmed, Executive Producer, Rovio Entertainment Corporation
Noah Falstein, Owner, The Inspiracy. Ex-Chief Game Designer, Google
Nour Khrais, Founder and CEO, Maysalward
Phylicia Koh, Investor, Play Ventures
Poornima Seetharaman, Director of Design, Zynga
Richard Kos, Head of User Acquisition, Azerion
Roki Soeharyo, CEO, Touchten Games
Rami Ismail, Industry ambassador @ Rami Ismail
Sande Chen, Industry Expert
Sam Yang, Director of Product Management, goGame
Simon Hade. Co-Founder and COO, Space Ape Games
Tj’ièn Twijnstra, Game Director, Story Giant Games
Vlad Kuligin, Senior Publishing Producer, M&A, Belka Games
Vanessa Rouhani, Senior Vice President, Publishing & Product Marketing, Jam City
Ziv Kitaro, Director of Product Management, Whaleapp
Aaron Hiscox, Partner Development Manager, Google Play
Adi Haddad, Business Development Manager, Games, Google Play
Andreas Preuer, Head of Play Partnerships, Games, Google Play
Daniel Trocoli, Strategic Partner Development, Google Play Apps and Games, LatAm – Sao Paulo, Google Play
George Yousling, Strategic Partner Development Manager, Google Play
Henrique Savelli Abelha Gomes, Mobile Apps Technical Specialist, Google
Jameel Khalfan, Strategic Partner Development Manager, New Business, Google Play
Jon Foust, Developer Advocate, Google Cloud
Mark Mandel, Developer Advocate, Google Cloud
Nimrod Levy, Business Development Manager, Google Play
Rogers Reichert, Strategic Partnership Manager – LATAM, Google Play
Rachel Cheung, Business Development, Apps and Games, Google Play
Sue Ann Goh, Gaming Growth Manager, AppDev, Google
Serena Shih, Strategic Partnership Manager, Google Play
Victoria Giovannetti, Account Strategist, App Sales – Online Partnerships Group, Google Play
Vineet Tanwar, Strategic Partner Development Manager – Games, Google Play

+infos(oficial): https://events.withgoogle.com/indie-games-google-play/

Tags : ,

Formação gratuita: Gaming: UNITY

Tomei conhecimento acerca de uma ação de formação financiada acerca do motor de videojogo Unity. São 25horas em horário pós-laboral, duas vezes por semana a começar no dia 9 fevereiro e até dia 7 de março. O formador vai ser o José Luís Campo Silva.

O conteúdo Programático:
Editor de jogos 3D
Importação de modelos 3D; texturas e áudio
Aplicação e ajuste de texturas e iluminação
Animação de objetos, elementos e definição de sistemas de partículas
Definição de ações e sincronismo de eventos
Definição de interruptores e ações automáticas
Transição entre áreas de modelos; estrutura de níveis
Definição de limites de deslocamento; desenho de envolvente
Utilização de estruturas de deteção de colisões e sistemas físicos
Definição e extração de cenas animadas a partir do modelo interativo

e tem como pré-requisitos:
Conhecimentos prévios em Programação em C#

Entidade responsável por esta ação de formação é a EISnt – EISnt – Centro de Formação Profissional e Consultoria Formação profissional em tecnologia para empregados e desempregados financiada

+infos(oficial):  LINK

Tags : ,

Mentoria de Programação 2022

São daquelas coisas que se encontram e que merecem muito ser partilhadas. Num grupo de uma rede social encontrei este texto partilhado pela própria autora e no qual consta o seguinte:
Mentoria de Programação 2022
Daniela Policarpo – Mid Level Game Programmer

No que consiste
A mentoria consiste em partilhar conhecimento e experiência sobre programação em jogos, como é trabalhar num ambiente profissional e ajudar-te a fazer um jogo do início ao fim!
As especificidades do que vais aprender dependerá do projeto que estás a desenvolver e dos teus interesses pessoais, mas eis algumas coisas que podes esperar aprender comigo:
-Arquitetura de software em jogos
-Como usar paradigmas e princípios de programação
-Como estruturar o código de um jogo inteiro
-Como criar código reutilizável e genérico
-Como e quando usar threads e async/await
-Como e quando usar ferramentas e ScriptableObjects
-Networking
-Como fazer um jogo multiplayer (peer-to-peer ou cliente-servidor)
-Como criar um servidor de jogo
-Como descarregar conteúdo online
-Como lidar com cheating, error handling e diferentes versões de cliente/servidor
-Controlo de versões (Git)
-Como usar Git, boas práticas e metodologias (git-flow vs CI/CD)
-Como fazer controlo de versões de ficheiros binários (ex: imagens, modelos 3D)
-Save e Load
-Como salvar dados de jogo (Xml, Json, SQL, etc)
-Debugging e Profiling
-Como otimizar assets e código

O processo de mentoria do(a) aluno(a) escolhido(a) consistirá em:
-Conversa inicial de voz/vídeo de 1 hora sobre as necessidades do teu projeto
-Email semanal teu com updates sobre o projeto (dificuldades, dúvidas, sucessos, etc)
-Email de resposta meu com feedback (soluções, ideias, pontos a melhorar, etc)
-Dependendo da disponibilidade e necessidade, outras conversas de voz/vídeo podem ser marcadas

Quem sou eu
Sou uma ex-aluna do curso de Videojogos da Lusófona de Lisboa que trabalha como programadora de jogos em Inglaterra desde 2019.
Tenho uma vasta experiência, desde criação de protótipos a manutenção e adição de conteúdo e funcionalidades a jogos live. Trabalhei em jogos multiplayer e singleplayer, desenvolvi lógica de UI, gameplay, ferramentas, criei servidores, sistemas de automação, etc. A minha paixão é a arquitetura de software em jogos, planear a code base de um jogo e tornar o trabalho de toda a equipa mais eficiente com código estável, fácil de entender e de expandir.
Clica aqui para veres mais sobre a minha experiência no LinkedIn.

O teu perfil
És alguém com sede de conhecimento, persistência e tens um projeto interessante que queres desenvolver do início ao fim? Se sim, então isto é para ti!
Envia email para daniela.policarpo@outlook.com com o assunto Mentoria 2022 e:
-Resumo breve do teu projeto
-O que pretendes aprender com esta mentoria
-Anexo do One Page Document do teu jogo
O(a) aluno(a) com mais motivação e o projeto mais cativante será o(a) escolhido(a). Se o teu projeto é de faculdade com outros alunos, a tua equipa pode ser considerada para mentoria, com a noção de que a mentoria será mais de um ponto de vista de programação.

Esta mentoria é gratuita, o projeto que finalizares é teu. O objetivo é partilhar conhecimento e devolver à comunidade de jogos o que aprendi, pois no passado eu já tive mentores e foi uma ótima experiência.

Boa sorte!

Não é fantástico?..

Tags : , ,

Palestra: “Gaming (not!) Over”

“O Gaming é atualmente a maior indústria de entretenimento no mundo. Com mais investimento, vemos mais oportunidades por explorar, especialmente no mercado português.
Na sessão “Gaming (not!) Over”, João Miguel Salvador, Ivan Barroso, Pedro Monteiro e Mafalda Duarte vão abordar várias temáticas, com foco no contexto nacional.
Para esta sessão e mais, registe-se gratuitamente no Building The Future aqui: https://lnkd.in/eJDCeGve

Vai decorrer no dia 28 pelas 16h40, não sei ainda se é online.

+infos(oficial): https://www.buildingthefuture.pt/

Tags :

Propostas de trabalho (no Porto)

A empresa Fabamaq tem uma série de ofertas de trabalho na area de desenvolvimento de software bem como na área de desenvolvimento de videojogos. Destaco uma dessas propostas que está neste momento em aberto e relacionada com o uso do Godot Engine.
Assim do texto surge:
“Whether you are a gameplay or a physics expert, a graphics or networking specialist, or just a great engineer, there will be always ways to stand out in our next big game.
Responsibilities:
– Development and maintenance of software related to Godot Engine;
– Development and maintenance of our web-based game engine for casino games (slots, bingo, poker, etc);
– Supporting the development of tools to bridge the design team work with our engine.

Expected:
– Proficiency with development in Godot Game Engine;
– Either/Both a degree in Computer Science (or similar area) or proven experience in software development;
– Familiarity with Git and Python.

Valued:
– Familiarity with Javascript;
– Knowledge of web-based rendering libraries such as PIXI.js, Three.js, Phaser.js or similar;
– Knowledge of other game engine technologies such as Unity3D, Unreal Engine or others beside Godot;
– Knowledge of web app development and handling different platform requirements (browser, OS, etc.);
– Experience working in an Agile environment;
– Passion about games and making games.”

+infos(oficial): https://www.fabamaq.com/pages.php?page_id=311

Tags :

Proposta de trabalho (Lisboa/híbrido)

Do texto consta:
“Infinity Games, a Portuguese company that develops and publishes mobile games, is looking for a Game Designer to join its team.

Description:
From the beginning with us, you will:
Contribute to the design of mobile game features and content;
Work on game systems, social features, characters, quests and more;
Configure the data in the game engine to turn the design into reality;
Defend your projects from the initial sales pitch to its implementation, launch and progress;
Working in collaboration with artists, programmers and QA;
Use playtests, player feedback and metrics to gain insights and refine your work;
Analyze competitive games to be an expert on the type of audience and market;
Launch new creative ideas for upcoming projects;
Provide constant feedback on gameplay and design.

Experiences & Qualifications
The ideal candidate will have:
Demonstrated aptitude for game design, which can be demonstrated through:
Experience working in a game company;
Postgraduate in an area related to game design;
Portfolio of personal game projects;
Knowledge of free game design fundamentals;
Experience implementing game content using a programming or scripting language
Excellent verbal, written and visual communication skills;
Strong technical ability to quickly master new software tools;
Ability to adapt and meet deadlines in a fast and creative environment;
Collaborative spirit and love for teamwork;
Passion for free mobile games;
Experience with spreadsheet tools, image editors, scripting tools and flowchart software;
A playable module is preferable – we want to see a short gameplay experience encapsulated, so show us your skills!
Demonstrated ability to work well in a highly collaborative environment
Submissions without a portfolio or work examples will not be considered.

Responsibilities
Work with the lead game designer to create compelling mechanics and ideas that fits the game’s vision
Take ownership of prototypes and features from concept to implementation, iterating and applying feedback along the way.
Experiment and iterate many of our games to design new features and mechanics to improve KPI’s”

+infos(oficial): https://infinitygames.io/

Tags :

Proposta de trabalho (Lisboa)

A Funcom com escritório em Portugal, está à procura de um Lead Game Designer. Da proposta surge:
“From critically acclaimed The Longest Journey to the very first sci-fi MMO Anarchy Online, to the brutal trials of Conan Exiles, our 28-year history has set our players uniquely up for a journey to the harsh world of Dune, where the continual battle for survival and spice will bring a challenge that is Legendary.

The Funcom team consists of over 250 people located in 5 studios – Norway, the US, Portugal, Sweden, a newly opened Romania studio – plus an additional UI/UX hub in the UK. As part of Funcom’s ongoing growth, and completing a successful turnaround, Funcom is now backed by Tencent, the largest online gaming company in the world!

Now, Funcom is working on a survival open-world crafting game set in the universe of Dune and is looking for one Lead Game Designer for its team in Oslo, Norway and one Lead Game Designer in Lisbon, Portugal. As a part of this team, you will take part in bringing this amazing world to life, while pushing the boundaries of quality and gameplay in the survival genre.

Your Mission in Funcom

As Lead Game Designer, you will help shape the vision for a survival open-world crafting game set in the Dune universe. You will manage designers in one or more strike teams and drive design and content implementation efforts in sections of the game, reporting to the game director. You will assist the design team in captivating players with memorable experiences through mentor-driven leadership. You will effectively liaise with teams which depend on the content your team delivers, as well as making sure your team gets the support they need from other teams.

The Lead Game Designer has experience planning and implementing game features and content. You will work with content design teams and narrative to ensure that the content and features are true to the Dune IP, while delivering a satisfying game experience. You will be challenged to create content that supports the core fantasies of Dune. Most importantly, the Lead Game Designer will oversee the creation of the game toolbox, as well as make sure content designers use the toolbox optimally.

How you can have an impact in your position:
Lead the designers in one or more strike teams through direct mentorship
Assist in the creation of the Content Bible for the game
Expand the game world through game features and content, following the creative vision and Content Bible
Create quality goals, workflows, and guides for all game features and content relevant to your areas of ownership
Collaborate and build relationships with various strike teams that are working on their sections of the game
Plan creation of content and features, including conception, presentation, iteration, and documentation in relevant ownership areas
Feedback on designs, content and features and help drive efforts to improve the quality of the game

We are looking for someone that has:
A bachelor’s degree
5+ years of experience in the game industry working in a game design capacity
2+ years of experience leading/managing a team
Shipped titles in a professional capacity
Extensive understanding of design processes including NPC design, feature design, level design, content design, as well as experience implementing features and content
Passion for leadership and mentoring
Clear, effective communication skills across teams and cultures
Motivation and drive to collaborate and advance positive change in a studio environment
The ability to work diligently while thinking critically and resolving complex issues

In addition, the perfect candidate has:
Experience working on survival games
Enjoys playing survival games
Familiarity with Dune and the Dune IP

We evaluate candidates on an ongoing basis and recommend candidates to apply as soon as possible!”

+infos(oficial): https://www.funcom.com/careers-in-funcom/

Tags :

Proposta de trabalho (Lisboa)

A empresa iBNB está a contratar um Game Designer, em que relata as seguintes informações:
“We’re now hiring a Game Designer to help us keep growing. If you’re excited to be part of a winning team at the frontier of crypto-innovation, iBNB is a perfect place to get ahead.

Responsibilities for Game Designer
Create new game ideas
Outline plots and storylines
Develop dynamic characters
Create the rules of the game
Research rules of the sports involved to ensure accuracy in the game
Develop user interface concepts (menus and controls)
Manage a team with junior game designer or interns
Responsible for beta testing

Qualifications for Game Designer
Any programming language certification, required
3-5 years of experience in a similar role
Project Management experience
Must be highly creative and storytelling ability
Passion for video games
Knowledge of gaming trends
Excellent programming skills
Ability to work on a team
Previous experience developing sports game for a wide range of gamers
High interest in crypto
Affinity with Non-Fungible Tokens

+infos(oficial): https://ibnb.finance/

Tags :

Novo ano e mais livros

A malta da editora BitMap Books já tem disponibilizada a possibilidade de compra do novo livro “Go Straight: The Ultimate Guide to Side-Scrolling Beat-’Em-Ups”, que retrata ao longo de 450 páginas alguns dos jogos que foram desenvolvidos e que são do género beat-’em-up”. A lista é extensa e ao longo das 450 páginas estes jogos são apresentados e ilustrados centenas destes jogos. Em fevereiro de 2022 vai ser disponibilizado.

+infos(oficial): LINK

Tags : , , ,