소스 검색

ft: 添加新的接口 删除基于ets表的实现

master
SisMaker 1 년 전
부모
커밋
2596354225
7개의 변경된 파일105개의 추가작업 그리고 183개의 파일을 삭제
  1. +0
    -2
      README.md
  2. +2
    -8
      include/eGLock.hrl
  3. +0
    -98
      src/eELock.erl
  4. +0
    -44
      src/eELockMgr.erl
  5. +97
    -17
      src/eGLock.erl
  6. +3
    -3
      src/eGLockMgr.erl
  7. +3
    -11
      src/eGLock_sup.erl

+ 0
- 2
README.md 파일 보기

@ -12,5 +12,3 @@ Build
----
eALock 基于atmoics
eELock 基于Ets表
eALock 更优

+ 2
- 8
include/eGLock.hrl 파일 보기

@ -1,15 +1,9 @@
%% key
-define(EtsGLockKey, '$EtsGLockKey').
%% :Ms
-define(LockTimeOut, 5000).
%% :Ms
-define(ReTryTime, 10).
-define(eELockMgr, eELockMgr).
%%
-define(eALockSize, 1048576).
-define(eGLockSize, 1048576).
%% atomics索引
-define(eALockRef, eALockRef).
-define(eGLockRef, eGLockRef).

+ 0
- 98
src/eELock.erl 파일 보기

@ -1,98 +0,0 @@
-module(eELock).
-include("eGLock.hrl").
-define(CASE(Cond, Then, That), case Cond of true -> Then; _ -> That end).
-export([
lockApply/2
, lockApply/3
]).
-spec lockApply(KeyOrKeys :: term() | [term()], MFAOrFun :: {M :: atom(), F :: atom(), Args :: list()} | {Fun :: function(), Args :: list()}) -> term().
lockApply(KeyOrKeys, MFAOrFun) ->
lockApply(KeyOrKeys, MFAOrFun, ?LockTimeOut).
-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(?eELockMgr),
link(GLockMgrPid),
Pid = self(),
case is_list(KeyOrKeys) of
true ->
KeyPids = [{OneKey, Pid} || OneKey <- KeyOrKeys],
[FirstKey | _] = KeyOrKeys,
lockApplys(KeyPids, KeyOrKeys, FirstKey, GLockMgrPid, MFAOrFun, TimeOut);
_ ->
lockApply({KeyOrKeys, Pid}, KeyOrKeys, GLockMgrPid, MFAOrFun, TimeOut)
end.
lockApply(KeyPid, Key, GLockMgrPid, MFAOrFun, TimeOut) ->
case ets:insert_new(?EtsGLockKey, KeyPid) of
true ->
try doApply(MFAOrFun)
catch C:R:S ->
{error, {lock_apply_error, {C, R, S}}}
after
ets:delete(?EtsGLockKey, Key),
unlink(GLockMgrPid),
ok
end;
_ ->
loopTry(KeyPid, Key, GLockMgrPid, MFAOrFun, TimeOut)
end.
loopTry(KeyPid, Key, GLockMgrPid, MFAOrFun, TimeOut) ->
receive
after ?ReTryTime ->
LTimeOut = ?CASE(TimeOut == infinity, TimeOut, TimeOut - ?ReTryTime),
case LTimeOut >= 0 of
true ->
case ets:lookup(?EtsGLockKey, Key) of
[] ->
lockApply(KeyPid, Key, GLockMgrPid, MFAOrFun, LTimeOut);
_ ->
loopTry(KeyPid, Key, GLockMgrPid, MFAOrFun, LTimeOut)
end;
_ ->
unlink(GLockMgrPid),
{error, {lock_timeout, Key}}
end
end.
lockApplys(KeyPids, Keys, FirstKey, GLockMgrPid, MFAOrFun, TimeOut) ->
case ets:insert_new(?EtsGLockKey, KeyPids) of
true ->
try doApply(MFAOrFun)
catch C:R:S ->
{error, {lock_apply_error, {C, R, S}}}
after
[ets:delete(?EtsGLockKey, OneKey) || OneKey <- Keys],
unlink(GLockMgrPid),
ok
end;
_ ->
loopTrys(KeyPids, Keys, FirstKey, GLockMgrPid, MFAOrFun, TimeOut)
end.
loopTrys(KeyPids, Keys, FirstKey, GLockMgrPid, MFAOrFun, TimeOut) ->
receive
after ?ReTryTime ->
LTimeOut = ?CASE(TimeOut == infinity, TimeOut, TimeOut - ?ReTryTime),
case LTimeOut >= 0 of
true ->
case ets:lookup(?EtsGLockKey, FirstKey) of
[] ->
lockApplys(KeyPids, Keys, FirstKey, GLockMgrPid, MFAOrFun, LTimeOut);
_ ->
loopTrys(KeyPids, Keys, FirstKey, GLockMgrPid, MFAOrFun, LTimeOut)
end;
_ ->
unlink(GLockMgrPid),
{error, {lock_timeout, Keys}}
end
end.
doApply({M, F, A}) ->
apply(M, F, A);
doApply({Fun, Args}) ->
apply(Fun, Args).

+ 0
- 44
src/eELockMgr.erl 파일 보기

@ -1,44 +0,0 @@
-module(eELockMgr).
-behaviour(gen_server).
-include("eGLock.hrl").
-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
code_change/3]).
-define(SERVER, ?MODULE).
-record(state, {}).
%%%===================================================================
%%% Spawning and gen_server implementation
%%%===================================================================
start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
init([]) ->
process_flag(trap_exit, true),
persistent_term:put(?eELockMgr, self()),
ets:new(?EtsGLockKey, [named_table, set, public, {write_concurrency, auto}, {read_concurrency, true}]),
{ok, #state{}}.
handle_call(_Request, _From, State) ->
{reply, ok, State}.
handle_cast(_Request, State) ->
{noreply, State}.
handle_info({'EXIT', Pid, _Reason}, State) ->
ets:match_delete(?EtsGLockKey, {'_', Pid}),
{noreply, State};
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.

src/eALock.erl → src/eGLock.erl 파일 보기

@ -1,31 +1,112 @@
-module(eALock).
-module(eGLock).
-include("eGLock.hrl").
-define(CASE(Cond, Then, That), case Cond of true -> Then; _ -> That end).
-export([
lockApply/2
tryLock/1
, tryLock/2
, releaseLock/1
, lockApply/2
, lockApply/3
]).
-spec tryLock(KeyOrKeys :: term() | [term()]) -> ok | timeout.
tryLock(KeyOrKeys) ->
tryLock(KeyOrKeys, ?LockTimeOut).
tryLock(KeyOrKeys, TimeOut) ->
ALockRef = persistent_term:get(?eGLockRef),
PidInt = eGPidInt:pidToInt(self()),
case is_list(KeyOrKeys) of
true ->
KeyIxs = getKexIxs(KeyOrKeys, []),
tryLocks(KeyIxs, ALockRef, PidInt, TimeOut);
_ ->
tryLock(erlang:phash2(KeyOrKeys, ?eGLockSize) + 1, ALockRef, PidInt, TimeOut)
end.
tryLock(KeyIx, ALockRef, PidInt, TimeOut) ->
case tryLockOne(KeyIx, ALockRef, PidInt) of
ok ->
ok;
_ ->
loopLock(KeyIx, ALockRef, PidInt, TimeOut)
end.
loopLock(KeyIx, ALockRef, PidInt, TimeOut) ->
receive
after ?ReTryTime ->
LTimeOut = ?CASE(TimeOut == infinity, TimeOut, TimeOut - ?ReTryTime),
case LTimeOut >= 0 of
true ->
case tryLockOne(KeyIx, ALockRef, PidInt) of
ok ->
ok;
_ ->
loopLock(KeyIx, ALockRef, PidInt, LTimeOut)
end;
_ ->
timeout
end
end.
tryLocks(KeyIxs, ALockRef, PidInt, TimeOut) ->
case tryLockAll(KeyIxs, ALockRef, PidInt, []) of
ok ->
ok;
_ ->
loopLocks(KeyIxs, ALockRef, PidInt, TimeOut)
end.
loopLocks(KeyIxs, ALockRef, PidInt, TimeOut) ->
receive
after ?ReTryTime ->
LTimeOut = ?CASE(TimeOut == infinity, TimeOut, TimeOut - ?ReTryTime),
case LTimeOut >= 0 of
true ->
case tryLockAll(KeyIxs, ALockRef, PidInt, []) of
ok ->
ok;
_ ->
loopLocks(KeyIxs, ALockRef, PidInt, LTimeOut)
end;
_ ->
timeout
end
end.
-spec releaseLock(KeyOrKeys :: term() | [term()]) -> ok.
releaseLock(KeyOrKeys) ->
ALockRef = persistent_term:get(?eGLockRef),
PidInt = eGPidInt:pidToInt(self()),
case is_list(KeyOrKeys) of
true ->
KeyIxs = getKexIxs(KeyOrKeys, []),
[atomics:compare_exchange(ALockRef, OneKeyIx, PidInt, 0) || OneKeyIx <- KeyIxs],
ok;
_ ->
atomics:compare_exchange(ALockRef, rlang:phash2(KeyOrKeys, ?eGLockSize) + 1, PidInt, 0),
ok
end.
-spec lockApply(KeyOrKeys :: term() | [term()], MFAOrFun :: {M :: atom(), F :: atom(), Args :: list()} | {Fun :: function(), Args :: list()}) -> term().
lockApply(KeyOrKeys, MFAOrFun) ->
lockApply(KeyOrKeys, MFAOrFun, ?LockTimeOut).
-spec lockApply(KeyOrKeys :: term() | [term()], MFAOrFun :: {M :: atom(), F :: atom(), Args :: list()} | {Fun :: function(), Args :: list()}, TimeOut :: integer() | infinity) -> term().
lockApply(KeyOrKeys, MFAOrFun, TimeOut) ->
ALockRef = persistent_term:get(?eALockRef),
CurPid = self(),
PidInt = eGPidInt:pidToInt(CurPid),
ALockRef = persistent_term:get(?eGLockRef),
PidInt = eGPidInt:pidToInt(self()),
case is_list(KeyOrKeys) of
true ->
KeyIxs = getKexIxs(KeyOrKeys, []),
lockApplys(KeyIxs, KeyOrKeys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut);
lockApplys(KeyIxs, KeyOrKeys, ALockRef, PidInt, MFAOrFun, TimeOut);
_ ->
lockApply(erlang:phash2(KeyOrKeys, ?eALockSize) + 1, KeyOrKeys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut)
lockApply(erlang:phash2(KeyOrKeys, ?eGLockSize) + 1, KeyOrKeys, ALockRef, PidInt, MFAOrFun, TimeOut)
end.
lockApply(KeyIx, Key, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut) ->
lockApply(KeyIx, Key, ALockRef, PidInt, MFAOrFun, TimeOut) ->
case tryLockOne(KeyIx, ALockRef, PidInt) of
ok ->
try doApply(MFAOrFun)
@ -36,10 +117,10 @@ lockApply(KeyIx, Key, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut) ->
ok
end;
_ ->
loopTry(KeyIx, Key, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut)
loopApply(KeyIx, Key, ALockRef, PidInt, MFAOrFun, TimeOut)
end.
loopTry(KeyIx, Key, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut) ->
loopApply(KeyIx, Key, ALockRef, PidInt, MFAOrFun, TimeOut) ->
receive
after ?ReTryTime ->
LTimeOut = ?CASE(TimeOut == infinity, TimeOut, TimeOut - ?ReTryTime),
@ -55,15 +136,14 @@ loopTry(KeyIx, Key, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut) ->
ok
end;
_ ->
loopTry(KeyIx, Key, ALockRef, CurPid, PidInt, MFAOrFun, LTimeOut)
loopApply(KeyIx, Key, ALockRef, PidInt, MFAOrFun, LTimeOut)
end;
_ ->
{error, {lock_timeout, Key}}
end
end.
lockApplys(KeyIxs, Keys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut) ->
CurPid = self(),
lockApplys(KeyIxs, Keys, ALockRef, PidInt, MFAOrFun, TimeOut) ->
case tryLockAll(KeyIxs, ALockRef, PidInt, []) of
ok ->
try doApply(MFAOrFun)
@ -74,10 +154,10 @@ lockApplys(KeyIxs, Keys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut) ->
ok
end;
_ ->
loopTrys(KeyIxs, Keys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut)
loopApplys(KeyIxs, Keys, ALockRef, PidInt, MFAOrFun, TimeOut)
end.
loopTrys(KeyIxs, Keys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut) ->
loopApplys(KeyIxs, Keys, ALockRef, PidInt, MFAOrFun, TimeOut) ->
receive
after ?ReTryTime ->
LTimeOut = ?CASE(TimeOut == infinity, TimeOut, TimeOut - ?ReTryTime),
@ -93,7 +173,7 @@ loopTrys(KeyIxs, Keys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut) ->
ok
end;
_ ->
loopTrys(KeyIxs, Keys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut)
loopApplys(KeyIxs, Keys, ALockRef, PidInt, MFAOrFun, LTimeOut)
end;
_ ->
{error, {lock_timeout, Keys}}
@ -102,7 +182,7 @@ loopTrys(KeyIxs, Keys, ALockRef, CurPid, PidInt, MFAOrFun, TimeOut) ->
getKexIxs([], IxAcc) -> IxAcc;
getKexIxs([Key | Keys], IxAcc) ->
KeyIx = erlang:phash2(Key, ?eALockSize) + 1,
KeyIx = erlang:phash2(Key, ?eGLockSize) + 1,
getKexIxs(Keys, ?CASE(lists:member(KeyIx, IxAcc), IxAcc, [KeyIx | IxAcc])).
tryLockOne(KeyIx, ALockRef, PidInt) ->

src/eALockMgr.erl → src/eGLockMgr.erl 파일 보기

@ -1,4 +1,4 @@
-module(eALockMgr).
-module(eGLockMgr).
-behaviour(gen_server).
@ -21,8 +21,8 @@ start_link() ->
init([]) ->
process_flag(trap_exit, true),
ATLockRef = atomics:new(?eALockSize, [{signed, false}]),
persistent_term:put(?eALockRef, ATLockRef),
ATLockRef = atomics:new(?eGLockSize, [{signed, false}]),
persistent_term:put(?eGLockRef, ATLockRef),
{ok, #state{}}.
handle_call(_Request, _From, State) ->

+ 3
- 11
src/eGLock_sup.erl 파일 보기

@ -15,20 +15,12 @@ init([]) ->
SupFlags = #{strategy => one_for_all, intensity => 100, period => 3600},
ChildSpecs = [
#{
id => ?eELockMgr,
start => {eELockMgr, start_link, []},
id => eGLockMgr,
start => {eGLockMgr, start_link, []},
restart => permanent,
shutdown => 3000,
type => worker,
modules => [eELockMgr]
},
#{
id => eALockMgr,
start => {eALockMgr, start_link, []},
restart => permanent,
shutdown => 3000,
type => worker,
modules => [eALockMgr]
modules => [eGLockMgr]
}
],
{ok, {SupFlags, ChildSpecs}}.

불러오는 중...
취소
저장