Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Changed variable names to be more consistent with C++ standard terminology

...

Code Block
bgColor#ffcccc
langc
#include <mutex>
#include <thread>
 
class bank_account {
  int balance;
public:
  std::mutex balance_mutex;
  bank_account() = delete;
  bank_account(int initial_amount) : balance(initial_amount) {}
  int get_balance() { return balance; }
  void set_balance(int amount) { balance = amount; }
};
 
int deposit(bank_account *from, bank_account *to, int amount) {
  std::lock_guard<std::mutex> from_guardlock(from->balance_mutex);
 
  /* Not enough balance to transfer */
  if (from->get_balance() < amount) {
    return -1; /* Indicate error */
  }
  std::lock_guard<std::mutex> to_guardlock(to->balance_mutex);
 
  from->set_balance(from->get_balance() - amount);
  to->set_balance(to->get_balance() + amount);
 
  return 0;
}
 
int main(void) {
  bank_account *ba1 = new bank_account(1000);
  bank_account *ba2 = new bank_account(1000);
 
  /* Perform the deposits */
  std::thread thr1(deposit, ba1, ba2, 100);
  std::thread thr2(deposit, ba2, ba1, 100);
  thr1.join();
  thr2.join();
  return 0;
}

...

Code Block
bgColor#ccccff
langc
#include <atomic>
#include <mutex>
#include <thread>
 
class bank_account {
  static std::atomic<unsigned int> global_id;
  const unsigned int id;
  int balance;
public:
  std::mutex balance_mutex;
  bank_account() = delete;
  bank_account(int initial_amount) : id(global_id++), balance(initial_amount) {}
  unsigned int get_id() { return id; }
  int get_balance() { return balance; }
  void set_balance(int amount) { balance = amount; }
};

std::atomic<unsigned int> bank_account::global_id(1);
 
int deposit(bank_account *from, bank_account *to, int amount) {
  int result = -1;
  std::mutex *first;
  std::mutex *second;
 
  if (from->get_id() == to->get_id()) {
    return -1; /* Indicate error */
  }
 
  /* Ensure proper ordering for locking */
  if (from->get_id() < to->get_id()) {
    first = &from->balance_mutex;
    second = &to->balance_mutex;
  } else {
    first = &to->balance_mutex;
    second = &from->balance_mutex;
  }
  std::lock_guard<std::mutex> first_guardlock(*first);
  std::lock_guard<std::mutex> second_guardlock(*second);
 
  /* Check for enough balance to transfer */
  if (from->get_balance() >= amount) {
    from->set_balance(from->get_balance() - amount);
    to->set_balance(to->get_balance() + amount);
    result = 0;
  }
 
  return result;
}

...