| 972 | |
| 973 | template <typename A, typename Func> |
| 974 | auto atomicallyImpl(STM<A, Func> const& stmac) -> IO<A> |
| 975 | { |
| 976 | Id<TState> ts; |
| 977 | Id<TResult<A>> r; |
| 978 | auto const dispatchResult = toFunc<> | [=](TResult<A> tResult) |
| 979 | { |
| 980 | return io([=] |
| 981 | { |
| 982 | return std::visit(overload( |
| 983 | [=](Valid<A> const& v_) -> A |
| 984 | { |
| 985 | auto [nts, a] = v_; |
| 986 | auto wslist = (readIORef | nts.writeSet).run(); |
| 987 | auto [success, locks] = (getLocks | nts.transId | wslist).run(); |
| 988 | if (success) |
| 989 | { |
| 990 | auto wstamp = incrementGlobalClock.run(); |
| 991 | auto valid = (validateReadSet | nts.readSet | nts.readStamp | nts.transId).run(); |
| 992 | if (valid) |
| 993 | { |
| 994 | (commitChangesToMemory | wstamp | wslist).run(); |
| 995 | (wakeUpBQ | wslist).run(); |
| 996 | (unlock | nts.transId | locks).run(); |
| 997 | return a; |
| 998 | } |
| 999 | else |
| 1000 | { |
| 1001 | (unlock | nts.transId | locks).run(); |
| 1002 | return atomicallyImpl(stmac).run(); |
| 1003 | } |
| 1004 | } |
| 1005 | else |
| 1006 | { |
| 1007 | unlock | nts.transId | locks; |
| 1008 | return atomicallyImpl(stmac).run(); |
| 1009 | } |
| 1010 | return A{}; |
| 1011 | }, |
| 1012 | [=](Retry const& nts) |
| 1013 | { |
| 1014 | auto rs = (readIORef | nts.readSet).run(); |
| 1015 | auto lrs = rs; |
| 1016 | auto [valid, locks] = (validateAndAcquireLocks | nts.readStamp | nts.transId | lrs).run(); |
| 1017 | if (valid) |
| 1018 | { |
| 1019 | auto waitMVar = newEmptyMVar<_O_>.run(); |
| 1020 | (addToWaitQueues | waitMVar | lrs).run(); |
| 1021 | (unlock | nts.transId | locks).run(); |
| 1022 | // Looks like this line will block. No one is responsible in waking waitqueues in |
| 1023 | (takeMVar | waitMVar).run(); |
| 1024 | return atomicallyImpl(stmac).run(); |
| 1025 | } |
| 1026 | else |
| 1027 | { |
| 1028 | unlock | nts.transId | locks; |
| 1029 | return atomicallyImpl(stmac).run(); |
| 1030 | } |
| 1031 | }, |
no test coverage detected