Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: s/deposit_thr_args/transaction/g

...

Code Block
bgColor#ffcccc
langc
#include <stdlib.h>
#include <threads.h>
 
typedef struct {
  int balance;
  mtx_t balance_mutex;
} bank_account;

typedef struct {
  bank_account *from;
  bank_account *to;
  int amount;
} deposit_thr_argstransaction;

void create_bank_account(bank_account **ba, int initial_amount) {
  bank_account *nba = (bank_account *)
                        malloc(sizeof(bank_account));
  if (nba == NULL) {
    /* Handle Error */
  }

  nba->balance = initial_amount;
  if (thrd_success != mtx_init(&nba->balance_mutex, mtx_plain)) {
    /* Handle error */
  }

  *ba = nba;
}

int deposit(void *ptr) {
  deposit_thr_argstransaction *args = (deposit_thr_argstransaction *)ptr;

  if (thrd_success != mtx_lock(&(args->from->balance_mutex))) {
    /* Handle error */
  }

  /* not enough balance to transfer */
  if (args->from->balance < args->amount) {
    if (thrd_suceess != mtx_unlock(&(args->from->balance_mutex))) {
      /* Handle error  */
    }
    return -1;  /* Indicate error */
  }

  if (thrd_success != mtx_lock(&(args->to->balance_mutex))) {
    /* Handle error */
  }

  args->from->balance -= args->amount;
  args->to->balance += args->amount;

  if (thrd_success != mtx_unlock(&(args->from->balance_mutex))) {
    /* Handle error */
  }
  if (thrd_success != mtx_unlock(&(args->to->balance_mutex))) {
    /* Handle error */
  }

  free(ptr);
  
  return 0;
}

int main(void) {
  thrd_t thr1, thr2;
  int result;
  deposit_thr_argstransaction *arg1;
  deposit_thr_argstransaction *arg2;
  bank_account *ba1;
  bank_account *ba2;

  create_bank_account(&ba1, 1000);
  create_bank_account(&ba2, 1000);

  arg1 = (deposit_thr_argstransaction *)malloc(sizeof(deposit_thr_argstransaction));
  if (arg1 == NULL) {
    /* Handle error */
  }
  arg2 = (deposit_thr_argstransaction *)malloc(sizeof(deposit_thr_argstransaction));
  if (arg2 == NULL) {
    /* Handle error */
  }

  arg1->from = ba1;
  arg1->to = ba2;
  arg1->amount = 100;

  arg2->from = ba2;
  arg2->to = ba1;
  arg2->amount = 100;

  /* Perform the deposits. */
  if (thrd_success != thrd_create(&thr1, deposit, (void *)arg1)) {
    /* Handle error */
  }
  if (thrd_success != thrd_create(&thr2, deposit, (void *)arg2)) {
    /* Handle error */
  }
  return 0;
}

...

Code Block
bgColor#ccccff
langc
#include <stdlib.h>
#include <threads.h>
 
typedef struct {
  int balance;
  mtx_t balance_mutex;
 
  /* Should never be changed after initialized. */ 
  unsigned int id;
} bank_account;

unsigned int global_id = 1;

void create_bank_account(bank_account **ba, int initial_amount) {
  bank_account *nba = (bank_account *)
                        malloc(sizeof(bank_account));
  if (nba == NULL) {
    /* Handle error */
  }

  nba->balance = initial_amount;
  if (thrd_success != mtx_init(&nba->balance_mutex, mtx_plain)) {
    /* Handle error */
  }

  nba->id = global_id++;
  *ba = nba;
}

int deposit(void *ptr) {
  deposit_thr_argstransaction *args = (deposit_thr_argstransaction *)ptr;
  int result = -1;
  mtx_t *first;
  mtx_t *second;

  if (args->from->id == args->to->id)
    return -1;  /* Indicate error */

  /* Ensure proper ordering for locking */
  if (args->from->id < args->to->id) {
    first = &args->from->balance_mutex;
    second = &args->to->balance_mutex;
  } else {
    first = &args->to->balance_mutex;
    second = &args->from->balance_mutex;
  }
  if (thrd_success != mtx_lock(first)) {
    /* Handle error */
  }
  if (thrd_success != mtx_lock(second)) {
    /* Handle error */
  }

  /* Not enough balance to transfer. */
  if (args->from->balance >= args->amount) {
    args->from->balance -= args->amount;
    args->to->balance += args->amount;
    result = 0;
  }

  if (thrd_success != mtx_unlock(second)) {
    /* Handle error */
  }
  if (thrd_success != mtx_unlock(first)) {
    /* Handle error */
  }
  free(ptr);
  return result;
}

...