|
|
@ -0,0 +1,100 @@ |
|
|
|
-module(eGLock). |
|
|
|
|
|
|
|
-include("eGLock.hrl"). |
|
|
|
|
|
|
|
-export([ |
|
|
|
lockApply/2 |
|
|
|
, lockApply/3 |
|
|
|
]). |
|
|
|
|
|
|
|
-spec lockApply(KeyOrKeys :: tuple() | [tuple()], MFAOrFun :: {M :: atom(), F :: atom(), Args :: list()} | {Fun :: function(), Args :: list()}) -> term(). |
|
|
|
lockApply(KeyOrKeys, MFAOrFun) -> |
|
|
|
lockApply(KeyOrKeys, MFAOrFun, ?LockTimeOut). |
|
|
|
|
|
|
|
-spec lockApply(KeyOrKeys :: tuple() | [tuple()], MFAOrFun :: {M :: atom(), F :: atom(), Args :: list()} | {Fun :: function(), Args :: list()}, TimeOut :: integer() | infinity) -> term(). |
|
|
|
lockApply(KeyOrKeys, MFAOrFun, TimeOut) -> |
|
|
|
case KeyOrKeys of |
|
|
|
{_, _} -> |
|
|
|
lockApply(KeyOrKeys, MFAOrFun, TimeOut, erlang:system_time(millisecond)); |
|
|
|
_ -> |
|
|
|
lockApplys(KeyOrKeys, MFAOrFun, TimeOut, erlang:system_time(millisecond)) |
|
|
|
end. |
|
|
|
|
|
|
|
-define(CASE(Cond, Then, That), case Cond of true -> Then; _ -> That end). |
|
|
|
lockApply(Key, MFAOrFun, TimeOut, FirstTime) -> |
|
|
|
case ets:insert_new(?EtsGLockKey, Key) of |
|
|
|
true -> |
|
|
|
try doApply(MFAOrFun) |
|
|
|
catch C:R:S -> |
|
|
|
{error, {lock_apply_error, {C, R, S}}} |
|
|
|
after |
|
|
|
ets:delete(?EtsGLockKey, element(1, Key)), |
|
|
|
ok |
|
|
|
end; |
|
|
|
_ -> |
|
|
|
loopTry(Key, MFAOrFun, TimeOut, FirstTime) |
|
|
|
end. |
|
|
|
|
|
|
|
loopTry(Key, MFAOrFun, TimeOut, FirstTime) -> |
|
|
|
receive |
|
|
|
after ?ReTryTime -> |
|
|
|
case ets:lookup(?EtsGLockKey, element(1, Key)) of |
|
|
|
[] -> |
|
|
|
lockApply(Key, MFAOrFun, TimeOut, FirstTime); |
|
|
|
_ -> |
|
|
|
case TimeOut of |
|
|
|
infinity -> |
|
|
|
loopTry(Key, MFAOrFun, TimeOut, FirstTime); |
|
|
|
_ -> |
|
|
|
LTimeOut = TimeOut - abs(erlang:system_time(millisecond) - FirstTime), |
|
|
|
case LTimeOut =< 0 of |
|
|
|
true -> |
|
|
|
{error, {lock_timeout, Key}}; |
|
|
|
_ -> |
|
|
|
loopTry(Key, MFAOrFun, TimeOut, FirstTime) |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end. |
|
|
|
|
|
|
|
lockApplys(Keys, MFAOrFun, TimeOut, FirstTime) -> |
|
|
|
case ets:insert_new(?EtsGLockKey, Keys) of |
|
|
|
true -> |
|
|
|
try doApply(MFAOrFun) |
|
|
|
catch C:R:S -> |
|
|
|
{error, {lock_apply_error, {C, R, S}}} |
|
|
|
after |
|
|
|
[ets:delete(?EtsGLockKey, element(1, OneKey)) || OneKey <- Keys], |
|
|
|
ok |
|
|
|
end; |
|
|
|
_ -> |
|
|
|
loopTrys(Keys, MFAOrFun, TimeOut, FirstTime) |
|
|
|
end. |
|
|
|
|
|
|
|
loopTrys(Keys, MFAOrFun, TimeOut, FirstTime) -> |
|
|
|
receive |
|
|
|
after ?ReTryTime -> |
|
|
|
[Key | _] = Keys, |
|
|
|
case ets:lookup(?EtsGLockKey, element(1, Key)) of |
|
|
|
[] -> |
|
|
|
lockApplys(Keys, MFAOrFun, TimeOut, FirstTime); |
|
|
|
_ -> |
|
|
|
case TimeOut of |
|
|
|
infinity -> |
|
|
|
loopTrys(Keys, MFAOrFun, TimeOut, FirstTime); |
|
|
|
_ -> |
|
|
|
LTimeOut = TimeOut - abs(erlang:system_time(millisecond) - FirstTime), |
|
|
|
case LTimeOut =< 0 of |
|
|
|
true -> |
|
|
|
{error, {lock_timeout, Keys}}; |
|
|
|
_ -> |
|
|
|
loopTrys(Keys, MFAOrFun, TimeOut, FirstTime) |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end. |
|
|
|
|
|
|
|
doApply({M, F, A}) -> |
|
|
|
apply(M, F, A); |
|
|
|
doApply({Fun, Args}) -> |
|
|
|
apply(Fun, Args). |