Browse Source

ft: 优化修过

master
SisMaker 1 year ago
parent
commit
5075b58c66
3 changed files with 34 additions and 54 deletions
  1. +1
    -5
      include/eGLock.hrl
  2. +33
    -32
      src/eALock.erl
  3. +0
    -17
      src/eALockMgr.erl

+ 1
- 5
include/eGLock.hrl View File

@ -1,9 +1,6 @@
%% key
-define(EtsGLockKey, '$EtsGLockKey').
%% key
-define(EtsGLockPid, '$EtsGLockPid').
%% :Ms
-define(LockTimeOut, 5000).
@ -11,9 +8,8 @@
-define(ReTryTime, 10).
-define(eELockMgr, eELockMgr).
-define(eALockMgr, eALockMgr).
%%
-define(eALockSize, 1048576).
%%
%% atomics索引
-define(eALockRef, eALockRef).

+ 33
- 32
src/eALock.erl View File

@ -14,67 +14,56 @@ lockApply(KeyOrKeys, MFAOrFun) ->
-spec lockApply(KeyOrKeys :: term() | [term()], MFAOrFun :: {M :: atom(), F :: atom(), Args :: list()} | {Fun :: function(), Args :: list()}, TimeOut :: integer() | infinity) -> term().
lockApply(KeyOrKeys, MFAOrFun, TimeOut) ->
GLockMgrPid = persistent_term:get(?eALockMgr),
ALockRef = persistent_term:get(?eALockRef),
CurPid = self(),
PidInt = eGPidInt:termInt(CurPid),
PidInt = eGPidInt:pidToInt(CurPid),
case is_list(KeyOrKeys) of
true ->
KeyIxs = getKexIxs(KeyOrKeys, []),
lockApplys(KeyIxs, KeyOrKeys, ALockRef, CurPid, PidInt, GLockMgrPid, MFAOrFun, TimeOut);
lockApplys(KeyIxs, KeyOrKeys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut);
_ ->
lockApply(erlang:phash2(KeyOrKeys, ?eALockSize) + 1, KeyOrKeys, ALockRef, CurPid, PidInt, GLockMgrPid, MFAOrFun, TimeOut)
lockApply(erlang:phash2(KeyOrKeys, ?eALockSize) + 1, KeyOrKeys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut)
end.
lockApply(KeyIx, Key, ALockRef, CurPid, PidInt, GLockMgrPid, MFAOrFun, TimeOut) ->
link(GLockMgrPid),
ets:insert(?EtsGLockPid, {CurPid, KeyIx}),
case atomics:compare_exchange(ALockRef, KeyIx, 0, PidInt) of
lockApply(KeyIx, Key, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut) ->
case tryLockOne(KeyIx, ALockRef, PidInt) of
ok ->
try doApply(MFAOrFun)
catch C:R:S ->
{error, {lock_apply_error, {C, R, S}}}
after
atomics:exchange(ALockRef, KeyIx, 0),
ets:delete(?EtsGLockPid, CurPid),
unlink(GLockMgrPid),
ok
end;
_ ->
loopTry(KeyIx, Key, ALockRef, CurPid, PidInt, GLockMgrPid, MFAOrFun, TimeOut)
loopTry(KeyIx, Key, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut)
end.
loopTry(KeyIx, Key, ALockRef, CurPid, PidInt, GLockMgrPid, MFAOrFun, TimeOut) ->
loopTry(KeyIx, Key, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut) ->
receive
after ?ReTryTime ->
LTimeOut = ?CASE(TimeOut == infinity, TimeOut, TimeOut - ?ReTryTime),
case LTimeOut >= 0 of
true ->
case atomics:compare_exchange(ALockRef, KeyIx, 0, PidInt) of
case tryLockOne(KeyIx, ALockRef, PidInt) of
ok ->
try doApply(MFAOrFun)
catch C:R:S ->
{error, {lock_apply_error, {C, R, S}}}
after
atomics:exchange(ALockRef, KeyIx, 0),
ets:delete(?EtsGLockPid, CurPid),
unlink(GLockMgrPid),
ok
end;
_ ->
loopTry(KeyIx, Key, ALockRef, CurPid, PidInt, GLockMgrPid, MFAOrFun, LTimeOut)
loopTry(KeyIx, Key, ALockRef, CurPid, PidInt, MFAOrFun, LTimeOut)
end;
_ ->
ets:delete(?EtsGLockPid, CurPid),
unlink(GLockMgrPid),
{error, {lock_timeout, Key}}
end
end.
lockApplys(KeyIxs, Keys, ALockRef, CurPid, PidInt, GLockMgrPid, MFAOrFun, TimeOut) ->
lockApplys(KeyIxs, Keys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut) ->
CurPid = self(),
link(GLockMgrPid),
ets:insert(?EtsGLockPid, {CurPid, KeyIxs}),
case tryLockAll(KeyIxs, ALockRef, PidInt, []) of
ok ->
try doApply(MFAOrFun)
@ -82,15 +71,13 @@ lockApplys(KeyIxs, Keys, ALockRef, CurPid, PidInt, GLockMgrPid, MFAOrFun, TimeOu
{error, {lock_apply_error, {C, R, S}}}
after
[atomics:exchange(ALockRef, KeyIx, 0) || KeyIx <- KeyIxs],
ets:delete(?EtsGLockPid, CurPid),
unlink(GLockMgrPid),
ok
end;
_ ->
loopTrys(KeyIxs, Keys, ALockRef, CurPid, PidInt, GLockMgrPid, MFAOrFun, TimeOut)
loopTrys(KeyIxs, Keys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut)
end.
loopTrys(KeyIxs, Keys, ALockRef, CurPid, PidInt, GLockMgrPid, MFAOrFun, TimeOut) ->
loopTrys(KeyIxs, Keys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut) ->
receive
after ?ReTryTime ->
LTimeOut = ?CASE(TimeOut == infinity, TimeOut, TimeOut - ?ReTryTime),
@ -103,16 +90,12 @@ loopTrys(KeyIxs, Keys, ALockRef, CurPid, PidInt, GLockMgrPid, MFAOrFun, TimeOut)
{error, {lock_apply_error, {C, R, S}}}
after
[atomics:exchange(ALockRef, KeyIx, 0) || KeyIx <- KeyIxs],
ets:delete(?EtsGLockPid, CurPid),
unlink(GLockMgrPid),
ok
end;
_ ->
loopTrys(KeyIxs, Keys, ALockRef, CurPid, PidInt, GLockMgrPid, MFAOrFun, TimeOut)
loopTrys(KeyIxs, Keys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut)
end;
_ ->
ets:delete(?EtsGLockPid, CurPid),
unlink(GLockMgrPid),
{error, {lock_timeout, Keys}}
end
end.
@ -122,14 +105,32 @@ getKexIxs([Key | Keys], IxAcc) ->
KeyIx = erlang:phash2(Key, ?eALockSize) + 1,
getKexIxs(Keys, ?CASE(lists:member(KeyIx, IxAcc), IxAcc, [KeyIx | IxAcc])).
tryLockOne(KeyIx, ALockRef, PidInt) ->
case atomics:compare_exchange(ALockRef, KeyIx, 0, PidInt) of
ok ->
ok;
OldPidInt ->
case is_process_alive(eGPidInt:intToPid(OldPidInt)) of
true ->
false;
_ ->
case atomics:compare_exchange(ALockRef, KeyIx, OldPidInt, PidInt) of
ok ->
ok;
_ ->
false
end
end
end.
tryLockAll([], _ALockRef, _PidInt, _LockAcc) ->
ok;
tryLockAll([KeyIx | KeyIxs], ALockRef, PidInt, LockAcc) ->
case atomics:compare_exchange(ALockRef, KeyIx, 0, PidInt) of
case tryLockOne(KeyIx, ALockRef, PidInt) of
ok ->
tryLockAll(KeyIxs, ALockRef, PidInt, [KeyIx | LockAcc]);
_ ->
[atomics:exchange(ALockRef, OneLock, 0) || OneLock <- LockAcc],
[atomics:compare_exchange(ALockRef, OneLock, PidInt, 0) || OneLock <- LockAcc],
false
end.

+ 0
- 17
src/eALockMgr.erl View File

@ -23,8 +23,6 @@ init([]) ->
process_flag(trap_exit, true),
ATLockRef = atomics:new(?eALockSize, [{signed, false}]),
persistent_term:put(?eALockRef, ATLockRef),
persistent_term:put(?eALockMgr, self()),
ets:new(?EtsGLockPid, [named_table, set, public, {write_concurrency, auto}]),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
@ -33,21 +31,6 @@ handle_call(_Request, _From, State) ->
handle_cast(_Request, State) ->
{noreply, State}.
handle_info({'EXIT', Pid, _Reason}, State) ->
case ets:take(?EtsGLockPid, Pid) of
[] -> ignore;
[{_Pid, KeyIxOrKeyIxs}] ->
ALockRef = persistent_term:get(?eALockRef),
PidInt = eGPidInt:termInt(Pid),
case is_integer(KeyIxOrKeyIxs) of
true ->
atomics:compare_exchange(ALockRef, KeyIxOrKeyIxs, PidInt, 0);
_ ->
[atomics:compare_exchange(ALockRef, KeyIx, PidInt, 0) || KeyIx <- KeyIxOrKeyIxs],
ok
end
end,
{noreply, State};
handle_info(_Info, State) ->
{noreply, State}.

Loading…
Cancel
Save