@ -0,0 +1,19 @@ | |||
.rebar3 | |||
_* | |||
.eunit | |||
*.o | |||
*.beam | |||
*.plt | |||
*.swp | |||
*.swo | |||
.erlang.cookie | |||
ebin | |||
log | |||
erl_crash.dump | |||
.rebar | |||
logs | |||
_build | |||
.idea | |||
*.iml | |||
rebar3.crashdump | |||
*~ |
@ -0,0 +1,21 @@ | |||
MIT License | |||
Copyright (c) 2022 AICells | |||
Permission is hereby granted, free of charge, to any person obtaining a copy | |||
of this software and associated documentation files (the "Software"), to deal | |||
in the Software without restriction, including without limitation the rights | |||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
copies of the Software, and to permit persons to whom the Software is | |||
furnished to do so, subject to the following conditions: | |||
The above copyright notice and this permission notice shall be included in all | |||
copies or substantial portions of the Software. | |||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
SOFTWARE. |
@ -0,0 +1,9 @@ | |||
gTimer | |||
===== | |||
An OTP application | |||
Build | |||
----- | |||
$ rebar3 compile |
@ -0,0 +1,5 @@ | |||
%% 相关配置模块名 | |||
-define(gTimerCfg, gTimerCfg). | |||
%% 工作者数量 | |||
-define(workCnt, workCnt). |
@ -0,0 +1,10 @@ | |||
{erl_opts, [no_debug_info, {i, "include"}]}. | |||
{deps, [ | |||
{eGbh, ".*", {git, "http://sismaker.tpddns.cn:53000/SisMaker/eGbh.git", {branch, "master"}}}, | |||
{eSync, ".*", {git, "http://sismaker.tpddns.cn:53000/SisMaker/eSync.git", {branch, "master"}}} | |||
]}. | |||
{shell, [ | |||
% {config, "config/sys.config"}, | |||
{apps, [gTimer]} | |||
]}. |
@ -0,0 +1,13 @@ | |||
{application, gTimer, | |||
[{description, "An OTP application"}, | |||
{vsn, "0.1.0"}, | |||
{registered, []}, | |||
{mod, {gTimer_app, []}}, | |||
{applications, [kernel, stdlib]}, | |||
{env,[]}, | |||
{modules, []}, | |||
{licenses, ["MIT"]}, | |||
{links, []} | |||
]}. |
@ -0,0 +1,54 @@ | |||
-module(gTimer). | |||
-include("gTimer.hrl"). | |||
-export([ | |||
start/0 | |||
, stop/0 | |||
, startWork/1 | |||
, setTimer/2 | |||
, getTimer/1 | |||
, delTimer/1 | |||
]). | |||
timerName(Idx) -> | |||
binary_to_atom(<<"$gtWSork_", (integer_to_binary(Idx))/binary>>). | |||
startWork(Cnt) when Cnt > 0 -> | |||
case ?gTimerCfg:getV(?workCnt) of | |||
0 -> | |||
NameList = [{Idx, timerName(Idx)} || Idx <- lists:seq(1, Cnt)], | |||
[supervisor:start_child(gTimer_sup, [WorkName]) || {_Idx, WorkName} <- NameList], | |||
CfgList = [{?workCnt, Cnt} | NameList], | |||
gtKvsToBeam:load(?gTimerCfg, CfgList), | |||
ok1; | |||
_Cnt -> | |||
{error, started} | |||
end. | |||
start() -> | |||
application:ensure_all_started(gTimer). | |||
stop() -> | |||
gtKvsToBeam:load(?gTimerCfg, [{?workCnt, 0}]), | |||
application:stop(gTimer). | |||
setTimer(Time, Msg) -> | |||
Cnt = ?gTimerCfg:getV(?workCnt), | |||
Idx = erlang:phash2(self(), Cnt) + 1, | |||
erlang:start_timer(Time, ?gTimerCfg:getV(Idx), Msg). | |||
getTimer(TimerRef) -> | |||
erlang:read_timer(TimerRef). | |||
delTimer(TimerRef) -> | |||
erlang:cancel_timer(TimerRef). | |||
@ -0,0 +1,15 @@ | |||
-module(gTimer_app). | |||
-behaviour(application). | |||
-include("gTimer.hrl"). | |||
-export([start/2, stop/1]). | |||
start(_StartType, _StartArgs) -> | |||
gtKvsToBeam:load(?gTimerCfg, [{?workCnt, 0}]), | |||
gTimer_sup:start_link(). | |||
stop(_State) -> | |||
ok. | |||
@ -0,0 +1,27 @@ | |||
-module(gTimer_sup). | |||
-behaviour(supervisor). | |||
-export([start_link/0]). | |||
-export([init/1]). | |||
-define(SERVER, ?MODULE). | |||
start_link() -> | |||
supervisor:start_link({local, ?SERVER}, ?MODULE, []). | |||
init([]) -> | |||
SupFlags = #{strategy => simple_one_for_one, intensity => 1000, period => 3600}, | |||
ChildSpecs = [ | |||
#{ | |||
id => gtWork, | |||
start => {gtWork, start_link, []}, | |||
restart => permanent, | |||
shutdown => 3000, | |||
type => worker, | |||
modules => [gtWork] | |||
} | |||
], | |||
{ok, {SupFlags, ChildSpecs}}. | |||
@ -0,0 +1,42 @@ | |||
-module(gtKvsToBeam). | |||
-export([ | |||
load/2 | |||
]). | |||
%% 注意 map类型的数据不能当做key | |||
-type key() :: atom() | binary() | bitstring() | float() | integer() | list() | tuple(). | |||
-type value() :: atom() | binary() | bitstring() | float() | integer() | list() | tuple() | map(). | |||
-spec load(term(), [{key(), value()}]) -> ok. | |||
load(Module, KVs) -> | |||
Forms = forms(Module, KVs), | |||
{ok, Module, Bin} = compile:forms(Forms), | |||
code:soft_purge(Module), | |||
{module, Module} = code:load_binary(Module, atom_to_list(Module), Bin), | |||
ok. | |||
forms(Module, KVs) -> | |||
%% -module(Module). | |||
Mod = erl_syntax:attribute(erl_syntax:atom(module), [erl_syntax:atom(Module)]), | |||
%% -export([getV/0]). | |||
ExportList = [erl_syntax:arity_qualifier(erl_syntax:atom(getV), erl_syntax:integer(1))], | |||
Export = erl_syntax:attribute(erl_syntax:atom(export), [erl_syntax:list(ExportList)]), | |||
%% getV(K) -> V | |||
Function = erl_syntax:function(erl_syntax:atom(getV), lookup_clauses(KVs, [])), | |||
[erl_syntax:revert(X) || X <- [Mod, Export, Function]]. | |||
lookup_clause(Key, Value) -> | |||
Var = erl_syntax:abstract(Key), | |||
Body = erl_syntax:abstract(Value), | |||
erl_syntax:clause([Var], [], [Body]). | |||
lookup_clause_anon() -> | |||
Var = erl_syntax:variable("_"), | |||
Body = erl_syntax:atom(undefined), | |||
erl_syntax:clause([Var], [], [Body]). | |||
lookup_clauses([], Acc) -> | |||
lists:reverse(lists:flatten([lookup_clause_anon() | Acc])); | |||
lookup_clauses([{Key, Value} | T], Acc) -> | |||
lookup_clauses(T, [lookup_clause(Key, Value) | Acc]). |
@ -0,0 +1,51 @@ | |||
-module(gtWork). | |||
-behavior(gen_srv). | |||
-export([ | |||
start_link/1 | |||
]). | |||
-export([ | |||
init/1 | |||
, handleCall/3 | |||
, handleCast/2 | |||
, handleInfo/2 | |||
, terminate/2 | |||
, code_change/3 | |||
]). | |||
-record(state, {}). | |||
%% ******************************************** API ******************************************************************* | |||
start_link(SrvName) -> | |||
gen_srv:start_link({local, SrvName}, ?MODULE, [], []). | |||
%% ******************************************** callback ************************************************************** | |||
init(_Args) -> | |||
{ok, #state{}}. | |||
handleCall(_Msg, _State, _FROM) -> | |||
{reply, ok}. | |||
%% 默认匹配 | |||
handleCast(_Msg, _State) -> | |||
kpS. | |||
handleInfo({timeout, TimerRef, Msg}, _State) -> | |||
%% 确认Msg格式 然后做分发处理 | |||
io:format("the timer time out ~p ~p ~n", [TimerRef, Msg]), | |||
kpS; | |||
handleInfo(_Msg, _State) -> | |||
kpS. | |||
terminate(_Reason, _State) -> | |||
ok. | |||
code_change(_OldVsn, State, _Extra) -> | |||
{ok, State}. | |||
%% ****************************************************** logic ******************************************************** | |||