Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <pthread.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include <unistd.h>
- #include <sys/file.h>
- #include <sys/wait.h>
- #include <semaphore.h>
- #include "myutils.h"
- #define NOPERATIONS 1000
- #define FILENAME "Bank.dat"
- #define NACCOUNTS 10
- #define NTHREADS 250
- #define INITIAL_ACCOUNT_MONEY 100
- int SOLUTION = 0; // La Solution 1 es usando FileLocks y la Solution 2 es con Semáforos.
- int fbank; // Archivo Bank.dat
- typedef struct account { int ID; double Balance; } Account; // Estructura de nuestra cuenta bancaria.
- sem_t* NamedMutex;
- void doSomething() { for (int i=0; i < 100000; i++); }
- void bankInit(){
- for(int i=0; i<NACCOUNTS; i++) {
- Account CurrentAccount = {.ID = i, .Balance = INITIAL_ACCOUNT_MONEY}; // Iniciamos la cuenta.
- write(fbank, &CurrentAccount, sizeof(Account)); // Escribimos nuestra cuenta en el Bank.dat
- }
- }
- void fileWithdraw(int accountID, double amount){
- Account tempAccount;
- lseek(fbank, accountID * sizeof(Account), SEEK_SET);
- read(fbank, &tempAccount, sizeof(Account));
- tempAccount.Balance -= amount;
- lseek(fbank, accountID * sizeof(Account), SEEK_SET);
- write(fbank, &tempAccount, sizeof(Account));
- }
- void fileDeposit(int accountID, double amount){
- Account tempAccount;
- lseek(fbank, accountID * sizeof(Account), SEEK_SET);
- read(fbank, &tempAccount, sizeof(Account));
- tempAccount.Balance += amount;
- lseek(fbank, accountID * sizeof(Account), SEEK_SET);
- write(fbank, &tempAccount, sizeof(Account));
- }
- bool check(Account* acc, double amount) { return acc->Balance - amount >= 0; }
- bool fileCheck(int accountID, double amount){
- Account tempAccount;
- lseek(fbank, accountID * sizeof(Account), SEEK_SET);
- read(fbank, &tempAccount, sizeof(Account));
- return check(&tempAccount, amount);
- }
- bool withdraw(int accountID, double amount) {
- if(fileCheck(accountID, amount)) {
- fileWithdraw(accountID, amount);
- doSomething();
- return true;
- }
- return false;
- }
- void deposit(int accountID, double amount) {
- fileDeposit(accountID, amount);
- doSomething();
- }
- bool transfer1(int fromID, int toID, double amount){
- // Solución usando FileLocks.
- int Lock1, Lock2; // Con esto vamos a evitar posibles Deadlocks.
- if (fromID > toID) {Lock1 = toID * sizeof(Account); Lock2 = fromID * sizeof(Account); }
- else{ Lock1 = fromID * sizeof(Account), Lock2 = toID * sizeof(Account); }
- while(file_lock(fbank, Lock1, sizeof(Account)) < 0);
- while(file_lock(fbank, Lock2, sizeof(Account)) < 0);
- // En este momento, ya hemos hecho el lock de la zona determinada de nuestro archivo.
- // Así que ya podemos hacer la operación de sumar y restar dinero.
- bool isDone = withdraw(fromID, amount);
- if (isDone) { deposit(toID, amount); }
- file_unlock(fbank, Lock1, sizeof(Account));
- file_unlock(fbank, Lock2, sizeof(Account));
- return isDone;
- }
- bool transfer2(int fromID, int toID, double amount){
- // Solución usando semáforos.
- sem_wait(NamedMutex);
- bool isDone = withdraw(fromID, amount);
- if (isDone) { deposit(toID, amount); }
- sem_post(NamedMutex);
- return isDone;
- }
- void* tranferThread(){
- fbank = open("Bank.dat", O_RDWR, 0600);
- int iter = NOPERATIONS/NACCOUNTS;
- int fromID = -1, toID = -1;
- while(iter--) {
- fromID = -1; toID = -1;
- while(fromID == toID) { // Si hemos seleccionado aleatoriamente las mismas cuentas, repetimos el proceso.
- fromID = rand()%NACCOUNTS; toID = rand()%NACCOUNTS;
- }
- double randomAmount = rand()%50+1;
- printf("ID: %d --- %d€ ---> ID: %d \n", fromID, (int) randomAmount, toID);
- if (SOLUTION == 1) transfer1(fromID, toID, randomAmount);
- else if (SOLUTION == 2) transfer2(fromID, toID, randomAmount);
- }
- return NULL;
- }
- int main(int argc, char* argv[]){
- if (argc > 1) SOLUTION = atoi(argv[1]);
- startTimer(0);
- if (SOLUTION == 1 || SOLUTION == 2){
- pthread_t ThreadsID[NTHREADS];
- fbank = open(FILENAME, O_CREAT | O_RDWR, 0600);
- if (SOLUTION == 2) NamedMutex = sem_open("/NamedMutex", O_CREAT, 0644, 1);
- bankInit();
- printf("----> Initial Bank Total Money: %d€ <----\n", INITIAL_ACCOUNT_MONEY);
- if (SOLUTION == 1){
- for (int i=0; i < NTHREADS; i++){
- int PID = fork();
- if (PID == 0){
- tranferThread();
- exit(0);
- }
- }
- while(wait(NULL) > 0);
- }
- else if (SOLUTION == 2){
- for(int i=0; i<NTHREADS; i++) { pthread_create(&ThreadsID[i], NULL, tranferThread, NULL); }
- for(int i=0; i<NTHREADS; i++) { pthread_join(ThreadsID[i], NULL); }
- }
- sem_close(NamedMutex);
- close(fbank);
- printf("Time: %ld ms\n", endTimer(0));
- return 0;
- }
- else return -1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement