protocol Banking{
func paymentAmount(amount: Double) throws;
}
enum PaymentError: Error {
case inSufficientAccountBalance
}
var accountBalance=30000.00
struct PayPal: Banking {
func paymentAmount(amount: Double) throws {
debugPrint("welcome to paypal payment gateway")
guard accountBalance > amount else{ throw
PaymentError.inSufficientAccountBalance
}
Thread.sleep(forTimeInterval: Double.random(in: 1...3))
accountBalance -= amount
}
func printMessage(){
debugPrint("Payment successful through paypal, new account balance=\(accountBalance)")
}
}
struct Stripe: Banking {
func paymentAmount(amount: Double) throws {
debugPrint("welcome to Stripe payment gateway")
guard accountBalance > amount else{ throw
PaymentError.inSufficientAccountBalance
}
Thread.sleep(forTimeInterval: Double.random(in: 1...3))
accountBalance -= amount
}
func printMessage(){
debugPrint("Payment successful through Stripe, new account balance=\(accountBalance)")
}
}
let queue=DispatchQueue(label: "just-a-queue", qos: .utility, attributes: .concurrent)
queue.async{
do{
let paypal=PayPal()
try paypal.paymentAmount(amount: 10000)
paypal.printMessage()
}catch PaymentError.inSufficientAccountBalance {
debugPrint("Payment failure due to insufficient Account Balance, paypal transaction cancelled")
}catch{
debugPrint("Error")
}
}
queue.async{
do{
let stripe=Stripe()
try stripe.paymentAmount(amount: 25000)
stripe.printMessage()
}catch PaymentError.inSufficientAccountBalance {
debugPrint("Payment failure due to insufficient Account Balance, stripe transaction cancelled")
}catch{
debugPrint("Error")
}
}
The above code have 2 structs PayPal and Stripe that conforms to banking and performs payment if the account balance is greater than amount to be paid. The final payment message that belongs to async block prints payment message for both the structs.
Here in this code I am intentionally trying to create a race condition by making payment from both the gateways. hence after PayPal async block is executed, the balance is 30000-10000=20000
After this, when stripe async block is executed, 20000-25000=-5000.
so the output comes out to be
"welcome to Stripe payment gateway"
"welcome to paypal payment gateway"
"Payment successful through paypal, new account balance=20000.0"
"Payment successful through Stripe, new account balance=-5000.0"
but some times the same code gives different output:
"welcome to paypal payment gateway"
"welcome to Stripe payment gateway"
"Payment successful through Stripe, new account balance=5000.0"
"Payment successful through paypal, new account balance=-5000.0"
Solution:
I think that I was passing an int type amount to be compared with the float type accountBalance.
When I changed the amount to be float type then the code gives the expected output as follows every time :
"welcome to Stripe payment gateway"
"welcome to paypal payment gateway"
"Payment successful through paypal, new account balance=20000.0"
"Payment successful through Stripe, new account balance=-5000.0"
I wanted to ask is there any concept behind the solution or any logic behind the scenes. Because if i normally compare int type to value type then it is surely going to give me an error but in a concurrent environment i am not sure, why does it even run the code for comparing int to float type and then performing execution of other following tasks.