    #include <cstdint>
    #include <iostream>
    #include <mutex>
    #include <thread>
    
    typedef long Money; //In minor unit.
    
    class Account {
    public:
    	bool transfer(Account& to,const Money amount);
    	Money get_balance() const;
    	Account(const Money deposit=0) : balance{deposit} {}
    private:
        mutable std::mutex lock;
    	Money balance;
    };
    
    bool Account::transfer(Account& to,const Money amount){
    	std::unique_lock<decltype(this->lock)> flock{this->lock,std::defer_lock};
    	std::unique_lock<decltype(to.lock)> tlock{to.lock,std::defer_lock};
    //NON-PORTABLE:BEGIN: using intptr_t AND assuming Total Strict Order.
    	const auto fi{reinterpret_cast<const std::intptr_t>(static_cast<const void*>(&this->lock))};
    	const auto ti{reinterpret_cast<const std::intptr_t>(static_cast<const void*>(&to.lock))};
    	if(fi<ti){
    		flock.lock();
    		tlock.lock();
    	} else if (fi!=ti) {
    		tlock.lock();
    		flock.lock();
    	} else {
    		flock.lock();
    	}
    //NON-PORTABLE:END	
    	this->balance-=amount;
    	to.balance+=amount;
    	return true;
    }
    
    Money Account::get_balance() const{
    	const std::lock_guard<decltype(this->lock)> guard{this->lock};
    	return this->balance;
    }
    
    void hammer_transfer(Account& from,Account& to,const Money amount, const int tries){
    	for(int i{1};i<=tries;++i){
    	    from.transfer(to,amount);
    	}
    }
    
    int main() {
    	constexpr Money open_a{ 200000L};
 	    constexpr Money open_b{ 100000L};
        constexpr Money tran_ab{10};
        constexpr Money tran_ba{3};
        constexpr Money tran_aa{7};

        Account A{open_a};
    	Account B{open_b};
    	
    	std::cout << "A Open:" << A.get_balance() << '\n';
    	std::cout << "B Open:" << B.get_balance() << '\n';
    	
    	constexpr long tries{20000}; 
    	std::thread TAB{hammer_transfer,std::ref(A),std::ref(B),tran_ab,tries};
    	std::thread TBA{hammer_transfer,std::ref(B),std::ref(A),tran_ba,tries};
    	std::thread TAA{hammer_transfer,std::ref(A),std::ref(A),tran_aa,tries};
    
    	TAB.join();
    	TBA.join();
    	TAA.join();
 
        const auto close_a{A.get_balance()};
        const auto close_b{B.get_balance()};   
    	
    	std::cout << "A Close:" << close_a<< '\n';
    	std::cout << "B Close:" << close_b<< '\n';
    	
        int errors{0};
        if((close_a+close_b)!=(open_a+open_b)){
            std::cout << "ERROR: Money Leaked!\n";
            ++errors;
        }
        if(close_a!=(open_a+tries*(tran_ba-tran_ab)) ||
              close_b!=(open_b+tries*(tran_ab-tran_ba))
        ){
            std::cout << "ERROR: 'Lost' Transaction(s)\n";
            ++errors;
        }
        if(errors==0){
            std::cout << "* SUCCESS *\n";
        }else{
            std::cout << "** FAILED **\n";
        }
        std::cout << std::endl;
    	return 0;
    }
