snp-lab-code/P08_Sync/work/Sync/banking-solution/a3/banking.c

143 lines
4.0 KiB
C

//******************************************************************************
// Course: BSy
// File: banking.c
// Author: M. Thaler, ZHAW
// Purpose: locking mechanisms
// Version: v.fs20
//******************************************************************************
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include "banking.h"
//******************************************************************************
#define MAX( a, b ) ( ( a > b) ? a : b )
#define MIN( a, b ) ( ( a <= b) ? a : b )
typedef struct account_struct_ {
long int balance;
pthread_mutex_t acntLock;
} Account;
typedef struct branch_struct {
Account *accounts;
pthread_mutex_t branchLock;
} Branch;
//******************************************************************************
static Branch *bank;
static int nBranches, nAccounts;
//******************************************************************************
// banking functions
void makeBank(int num_branches, int num_accounts) {
nBranches = num_branches;
nAccounts = num_accounts;
bank = (Branch *)malloc(nBranches * sizeof(Branch));
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
//pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
for (int i = 0; i < nBranches; i++) {
bank[i].accounts = (Account *)malloc(nAccounts * sizeof(Account));
for (int j = 0; j < nAccounts; j++) {
pthread_mutex_init(&bank[i].accounts[j].acntLock, NULL);
bank[i].accounts[j].balance = 0;
}
}
}
void deletebank(void) {
for (int i = 0; i < nBranches; i++)
free(bank[i].accounts);
free(bank);
nBranches = nAccounts = 0;
}
long int withdraw(int branchNr, int accountNr, long int value) {
int rv, tmp;
rv = 0;
tmp = bank[branchNr].accounts[accountNr].balance - value;
if (tmp >= 0) {
bank[branchNr].accounts[accountNr].balance = tmp;
rv = value;
};
return rv;
}
void deposit(int branchNr, int accountNr, long int value) {
bank[branchNr].accounts[accountNr].balance += value;
}
void transfer(int fromB, int toB, int accountNr, long int value) {
if (fromB == toB) {
return;
}
int first = MIN(fromB, toB);
int second = MAX(fromB, toB);
pthread_mutex_lock(&bank[first].accounts[accountNr].acntLock);
pthread_mutex_lock(&bank[second].accounts[accountNr].acntLock);
int money = withdraw(fromB, accountNr, value);
deposit(toB, accountNr, money);
pthread_mutex_unlock(&bank[first].accounts[accountNr].acntLock);
pthread_mutex_unlock(&bank[second].accounts[accountNr].acntLock);
}
void checkAssets(void) {
static long assets = 0;
long int sum = 0;
for (int i = 0; i < nBranches; i++) {
for (int j = 0; j < nAccounts; j++) {
sum += (long int)bank[i].accounts[j].balance;
}
}
if (assets == 0) {
assets = sum;
printf("Balance of accounts is: %ld\n", sum);
}
else {
if (sum != assets) {
printf("Balance of accounts is: %ld ... not correct\n", sum);
}
else
printf("Balance of accounts is: %ld ... correct\n", assets);
}
}
int checkIBC(void) {
static long ibcError = 0;
long sum = 0;
for (int i = 0; i < nBranches; i++) {
pthread_mutex_lock(&bank[i].branchLock);
for (int j = 0; j < nAccounts; j++) {
pthread_mutex_lock(&bank[i].accounts[j].acntLock);
}
}
for (int i = 0; i < nBranches; i++) {
for (int j = 0; j < nAccounts; j++) {
sum += (long)bank[i].accounts[j].balance;
}
}
for (int i = nBranches - 1; i >= 0; i--) {
pthread_mutex_unlock(&bank[i].branchLock);
for (int j = 0; j < nAccounts; j++) {
pthread_mutex_unlock(&bank[i].accounts[j].acntLock);
}
}
if (ibcError == 0) ibcError = sum;
return (ibcError != sum);
}
//******************************************************************************