From 80b409d5c88be947b1657a1493f2c4a4946f0a3f Mon Sep 17 00:00:00 2001 From: SisMaker <1713699517@qq.com> Date: Fri, 12 Apr 2024 00:48:48 +0800 Subject: [PATCH] =?UTF-8?q?ft:=20=E4=BC=98=E5=8C=96=E4=B9=8B=E5=90=8E?= =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/eGLock.erl | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 src/eGLock.erl diff --git a/src/eGLock.erl b/src/eGLock.erl new file mode 100644 index 0000000..e85bae9 --- /dev/null +++ b/src/eGLock.erl @@ -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).