gproc.erl 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390
  1. %% ``The contents of this file are subject to the Erlang Public License,
  2. %% Version 1.1, (the "License"); you may not use this file except in
  3. %% compliance with the License. You should have received a copy of the
  4. %% Erlang Public License along with this software. If not, it can be
  5. %% retrieved via the world wide web at http://www.erlang.org/.
  6. %%
  7. %% Software distributed under the License is distributed on an "AS IS"
  8. %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  9. %% the License for the specific language governing rights and limitations
  10. %% under the License.
  11. %%
  12. %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
  13. %% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
  14. %% AB. All Rights Reserved.''
  15. %%
  16. %% @author Ulf Wiger <ulf.wiger@erlang-consulting.com>
  17. %%
  18. %% @doc Extended process registry
  19. %% <p>This module implements an extended process registry</p>
  20. %% <p>For a detailed description, see
  21. %% <a href="erlang07-wiger.pdf">erlang07-wiger.pdf</a>.</p>
  22. %%
  23. %% Type and scope for registration and lookup:
  24. %%
  25. %% @type type() = n | p | c | a. n = name; p = property; c = counter;
  26. %% a = aggregate_counter
  27. %% @type scope() = l | g. l = local registration; g = global registration
  28. %%
  29. %% Type and scope for select(), qlc() and stepping:
  30. %%
  31. %% @type sel_scope() = scope | all | global | local.
  32. %% @type sel_type() = type() | names | props | counters | aggr_counters.
  33. %% @type context() = {scope(), type()} | type(). {'all','all'} is the default
  34. %%
  35. %% @type headpat() = {keypat(),pidpat(),ValPat}.
  36. %% @type keypat() = {sel_type() | sel_var(),
  37. %% l | g | sel_var(),
  38. %% any()}.
  39. %% @type pidpat() = pid() | sel_var().
  40. %% sel_var() = DollarVar | '_'.
  41. %% @type sel_pattern() = [{headpat(), Guards, Prod}].
  42. %% @type key() = {type(), scope(), any()}
  43. %% @end
  44. -module(gproc).
  45. -behaviour(gen_server).
  46. -export([start_link/0,
  47. reg/1, reg/2, unreg/1,
  48. mreg/3,
  49. set_value/2,
  50. get_value/1,
  51. where/1,
  52. await/1, await/2,
  53. nb_wait/1,
  54. cancel_wait/2,
  55. lookup_pid/1,
  56. lookup_pids/1,
  57. lookup_value/1,
  58. lookup_values/1,
  59. update_counter/2,
  60. give_away/2,
  61. send/2,
  62. info/1, info/2,
  63. select/1, select/2, select/3,
  64. first/1,
  65. next/2,
  66. prev/2,
  67. last/1,
  68. table/1, table/2]).
  69. %% Convenience functions
  70. -export([add_local_name/1,
  71. add_global_name/1,
  72. add_local_property/2,
  73. add_global_property/2,
  74. add_local_counter/2,
  75. add_global_counter/2,
  76. add_local_aggr_counter/1,
  77. add_global_aggr_counter/1,
  78. lookup_local_name/1,
  79. lookup_global_name/1,
  80. lookup_local_properties/1,
  81. lookup_global_properties/1,
  82. lookup_local_counters/1,
  83. lookup_global_counters/1,
  84. lookup_local_aggr_counter/1,
  85. lookup_global_aggr_counter/1]).
  86. %% Callbacks for behaviour support
  87. -export([whereis_name/1,
  88. unregister_name/1]).
  89. -export([default/1]).
  90. %%% internal exports
  91. -export([init/1,
  92. handle_cast/2,
  93. handle_call/3,
  94. handle_info/2,
  95. code_change/3,
  96. terminate/2]).
  97. %% this shouldn't be necessary
  98. -export([audit_process/1]).
  99. -include("gproc.hrl").
  100. -include_lib("eunit/include/eunit.hrl").
  101. -define(SERVER, ?MODULE).
  102. %%-define(l, l(?LINE)). % when activated, calls a traceable empty function
  103. -define(l, ignore).
  104. -define(CHK_DIST,
  105. case whereis(gproc_dist) of
  106. undefined ->
  107. erlang:error(local_only);
  108. _ ->
  109. ok
  110. end).
  111. -record(state, {}).
  112. %% @spec () -> {ok, pid()}
  113. %%
  114. %% @doc Starts the gproc server.
  115. %%
  116. %% This function is intended to be called from gproc_sup, as part of
  117. %% starting the gproc application.
  118. %% @end
  119. start_link() ->
  120. _ = create_tabs(),
  121. gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
  122. %% spec(Name::any()) -> true
  123. %%
  124. %% @doc Registers a local (unique) name. @equiv reg({n,l,Name})
  125. %% @end
  126. %%
  127. add_local_name(Name) -> reg({n,l,Name}, undefined).
  128. %% spec(Name::any()) -> true
  129. %%
  130. %% @doc Registers a global (unique) name. @equiv reg({n,g,Name})
  131. %% @end
  132. %%
  133. add_global_name(Name) -> reg({n,g,Name}, undefined).
  134. %% spec(Name::any(), Value::any()) -> true
  135. %%
  136. %% @doc Registers a local (non-unique) property. @equiv reg({p,l,Name},Value)
  137. %% @end
  138. %%
  139. add_local_property(Name , Value) -> reg({p,l,Name}, Value).
  140. %% spec(Name::any(), Value::any()) -> true
  141. %%
  142. %% @doc Registers a global (non-unique) property. @equiv reg({p,g,Name},Value)
  143. %% @end
  144. %%
  145. add_global_property(Name, Value) -> reg({p,g,Name}, Value).
  146. %% spec(Name::any(), Initial::integer()) -> true
  147. %%
  148. %% @doc Registers a local (non-unique) counter. @equiv reg({c,l,Name},Value)
  149. %% @end
  150. %%
  151. add_local_counter(Name, Initial) when is_integer(Initial) ->
  152. reg({c,l,Name}, Initial).
  153. %% spec(Name::any(), Initial::integer()) -> true
  154. %%
  155. %% @doc Registers a global (non-unique) counter. @equiv reg({c,g,Name},Value)
  156. %% @end
  157. %%
  158. add_global_counter(Name, Initial) when is_integer(Initial) ->
  159. reg({c,g,Name}, Initial).
  160. %% spec(Name::any()) -> true
  161. %%
  162. %% @doc Registers a local (unique) aggregated counter.
  163. %% @equiv reg({a,l,Name})
  164. %% @end
  165. %%
  166. add_local_aggr_counter(Name) -> reg({a,l,Name}).
  167. %% spec(Name::any()) -> true
  168. %%
  169. %% @doc Registers a global (unique) aggregated counter.
  170. %% @equiv reg({a,g,Name})
  171. %% @end
  172. %%
  173. add_global_aggr_counter(Name) -> reg({a,g,Name}).
  174. %% @spec (Name::any()) -> pid()
  175. %%
  176. %% @doc Lookup a local unique name. Fails if there is no such name.
  177. %% @equiv where({n,l,Name})
  178. %% @end
  179. %%
  180. lookup_local_name(Name) -> where({n,l,Name}).
  181. %% @spec (Name::any()) -> pid()
  182. %%
  183. %% @doc Lookup a global unique name. Fails if there is no such name.
  184. %% @equiv where({n,g,Name})
  185. %% @end
  186. %%
  187. lookup_global_name(Name) -> where({n,g,Name}).
  188. %% @spec (Name::any()) -> integer()
  189. %%
  190. %% @doc Lookup a local (unique) aggregated counter and returns its value.
  191. %% Fails if there is no such object.
  192. %% @equiv where({a,l,Name})
  193. %% @end
  194. %%
  195. lookup_local_aggr_counter(Name) -> lookup_value({a,l,Name}).
  196. %% @spec (Name::any()) -> integer()
  197. %%
  198. %% @doc Lookup a global (unique) aggregated counter and returns its value.
  199. %% Fails if there is no such object.
  200. %% @equiv where({a,g,Name})
  201. %% @end
  202. %%
  203. lookup_global_aggr_counter(Name) -> lookup_value({a,g,Name}).
  204. %% @spec (Property::any()) -> [{pid(), Value}]
  205. %%
  206. %% @doc Look up all local (non-unique) instances of a given Property.
  207. %% Returns a list of {Pid, Value} tuples for all matching objects.
  208. %% @equiv lookup_values({p, l, Property})
  209. %% @end
  210. %%
  211. lookup_local_properties(P) -> lookup_values({p,l,P}).
  212. %% @spec (Property::any()) -> [{pid(), Value}]
  213. %%
  214. %% @doc Look up all global (non-unique) instances of a given Property.
  215. %% Returns a list of {Pid, Value} tuples for all matching objects.
  216. %% @equiv lookup_values({p, g, Property})
  217. %% @end
  218. %%
  219. lookup_global_properties(P) -> lookup_values({p,g,P}).
  220. %% @spec (Counter::any()) -> [{pid(), Value::integer()}]
  221. %%
  222. %% @doc Look up all local (non-unique) instances of a given Counter.
  223. %% Returns a list of {Pid, Value} tuples for all matching objects.
  224. %% @equiv lookup_values({c, l, Counter})
  225. %% @end
  226. %%
  227. lookup_local_counters(P) -> lookup_values({c,l,P}).
  228. %% @spec (Counter::any()) -> [{pid(), Value::integer()}]
  229. %%
  230. %% @doc Look up all global (non-unique) instances of a given Counter.
  231. %% Returns a list of {Pid, Value} tuples for all matching objects.
  232. %% @equiv lookup_values({c, g, Counter})
  233. %% @end
  234. %%
  235. lookup_global_counters(P) -> lookup_values({c,g,P}).
  236. %% @spec reg(Key::key()) -> true
  237. %%
  238. %% @doc
  239. %% @equiv reg(Key, default(Key))
  240. %% @end
  241. reg(Key) ->
  242. reg(Key, default(Key)).
  243. default({T,_,_}) when T==c -> 0;
  244. default(_) -> undefined.
  245. %% @spec await(Key::key()) -> {pid(),Value}
  246. %% @equiv await(Key,infinity)
  247. %%
  248. await(Key) ->
  249. await(Key, infinity).
  250. %% @spec await(Key::key(), Timeout) -> {pid(),Value}
  251. %% Timeout = integer() | infinity
  252. %%
  253. %% @doc Wait for a local name to be registered.
  254. %% The function raises an exception if the timeout expires. Timeout must be
  255. %% either an interger &gt; 0 or 'infinity'.
  256. %% A small optimization: we first perform a lookup, to see if the name
  257. %% is already registered. This way, the cost of the operation will be
  258. %% roughly the same as of where/1 in the case where the name is already
  259. %% registered (the difference: await/2 also returns the value).
  260. %% @end
  261. %%
  262. await({n,g,_} = Key, Timeout) ->
  263. ?CHK_DIST,
  264. request_wait(Key, Timeout);
  265. await({n,l,_} = Key, Timeout) ->
  266. case ets:lookup(?TAB, {Key, n}) of
  267. [{_, Pid, Value}] ->
  268. {Pid, Value};
  269. _ ->
  270. request_wait(Key, Timeout)
  271. end;
  272. await(K, T) ->
  273. erlang:error(badarg, [K, T]).
  274. request_wait({n,C,_} = Key, Timeout) when C==l; C==g ->
  275. TRef = case Timeout of
  276. infinity -> no_timer;
  277. T when is_integer(T), T > 0 ->
  278. erlang:start_timer(T, self(), gproc_timeout);
  279. _ ->
  280. erlang:error(badarg, [Key, Timeout])
  281. end,
  282. WRef = case {call({await,Key,self()}, C), C} of
  283. {{R, {Kg,Pg,Vg}}, g} ->
  284. self() ! {gproc, R, registered, {Kg,Pg,Vg}},
  285. R;
  286. {R,_} ->
  287. R
  288. end,
  289. receive
  290. {gproc, WRef, registered, {_K, Pid, V}} ->
  291. case TRef of
  292. no_timer -> ignore;
  293. _ -> erlang:cancel_timer(TRef)
  294. end,
  295. {Pid, V};
  296. {timeout, TRef, gproc_timeout} ->
  297. cancel_wait(Key, WRef),
  298. erlang:error(timeout, [Key, Timeout])
  299. end.
  300. %% @spec nb_wait(Key::key()) -> Ref
  301. %%
  302. %% @doc Wait for a local name to be registered.
  303. %% The caller can expect to receive a message,
  304. %% {gproc, Ref, registered, {Key, Pid, Value}}, once the name is registered.
  305. %% @end
  306. %%
  307. nb_wait({n,g,_} = Key) ->
  308. ?CHK_DIST,
  309. call({await, Key, self()}, g);
  310. nb_wait({n,l,_} = Key) ->
  311. call({await, Key, self()}, l);
  312. nb_wait(Key) ->
  313. erlang:error(badarg, [Key]).
  314. cancel_wait({_,g,_} = Key, Ref) ->
  315. ?CHK_DIST,
  316. cast({cancel_wait, self(), Key, Ref}, g),
  317. ok;
  318. cancel_wait({_,l,_} = Key, Ref) ->
  319. cast({cancel_wait, self(), Key, Ref}, l),
  320. ok.
  321. %% @spec reg(Key::key(), Value) -> true
  322. %%
  323. %% @doc Register a name or property for the current process
  324. %%
  325. %%
  326. reg({_,g,_} = Key, Value) ->
  327. %% anything global
  328. ?CHK_DIST,
  329. gproc_dist:reg(Key, Value);
  330. reg({p,l,_} = Key, Value) ->
  331. local_reg(Key, Value);
  332. reg({a,l,_} = Key, undefined) ->
  333. call({reg, Key, undefined});
  334. reg({c,l,_} = Key, Value) when is_integer(Value) ->
  335. call({reg, Key, Value});
  336. reg({n,l,_} = Key, Value) ->
  337. call({reg, Key, Value});
  338. reg(_, _) ->
  339. erlang:error(badarg).
  340. %% @spec mreg(type(), scope(), [{Key::any(), Value::any()}]) -> true
  341. %%
  342. %% @doc Register multiple {Key,Value} pairs of a given type and scope.
  343. %%
  344. %% This function is more efficient than calling {@link reg/2} repeatedly.
  345. %% @end
  346. mreg(T, g, KVL) ->
  347. ?CHK_DIST,
  348. gproc_dist:mreg(T, KVL);
  349. mreg(T, l, KVL) when T==a; T==n ->
  350. if is_list(KVL) ->
  351. call({mreg, T, l, KVL});
  352. true ->
  353. erlang:error(badarg)
  354. end;
  355. mreg(p, l, KVL) ->
  356. local_mreg(p, KVL);
  357. mreg(_, _, _) ->
  358. erlang:error(badarg).
  359. %% @spec (Key:: key()) -> true
  360. %%
  361. %% @doc Unregister a name or property.
  362. %% @end
  363. unreg(Key) ->
  364. case Key of
  365. {_, g, _} ->
  366. ?CHK_DIST,
  367. gproc_dist:unreg(Key);
  368. {T, l, _} when T == n;
  369. T == a -> call({unreg, Key});
  370. {_, l, _} ->
  371. case ets:member(?TAB, {Key,self()}) of
  372. true ->
  373. gproc_lib:remove_reg(Key, self());
  374. false ->
  375. erlang:error(badarg)
  376. end
  377. end.
  378. %% @equiv unreg/1
  379. unregister_name(Key) ->
  380. unreg(Key).
  381. %% @spec (select_pattern()) -> list(sel_object())
  382. %% @doc
  383. %% @equiv select(all, Pat)
  384. %% @end
  385. select(Pat) ->
  386. select(all, Pat).
  387. %% @spec (Context::context(), Pat::sel_pattern()) -> [{Key, Pid, Value}]
  388. %%
  389. %% @doc Perform a select operation on the process registry.
  390. %%
  391. %% The physical representation in the registry may differ from the above,
  392. %% but the select patterns are transformed appropriately.
  393. %% @end
  394. select(Context, Pat) ->
  395. ets:select(?TAB, pattern(Pat, Context)).
  396. %% @spec (Context::context(), Pat::sel_patten(), Limit::integer()) ->
  397. %% [{Key, Pid, Value}]
  398. %% @doc Like {@link select/2} but returns Limit objects at a time.
  399. %%
  400. %% See [http://www.erlang.org/doc/man/ets.html#select-3].
  401. %% @end
  402. select(Context, Pat, Limit) ->
  403. ets:select(?TAB, pattern(Pat, Context), Limit).
  404. %%% Local properties can be registered in the local process, since
  405. %%% no other process can interfere.
  406. %%%
  407. local_reg(Key, Value) ->
  408. case gproc_lib:insert_reg(Key, Value, self(), l) of
  409. false -> erlang:error(badarg);
  410. true -> monitor_me()
  411. end.
  412. local_mreg(_, []) -> true;
  413. local_mreg(T, [_|_] = KVL) ->
  414. case gproc_lib:insert_many(T, l, KVL, self()) of
  415. false -> erlang:error(badarg);
  416. {true,_} -> monitor_me()
  417. end.
  418. %% @spec (Key :: key(), Value) -> true
  419. %% @doc Sets the value of the registeration entry given by Key
  420. %%
  421. %% Key is assumed to exist and belong to the calling process.
  422. %% If it doesn't, this function will exit.
  423. %%
  424. %% Value can be any term, unless the object is a counter, in which case
  425. %% it must be an integer.
  426. %% @end
  427. %%
  428. set_value({_,g,_} = Key, Value) ->
  429. ?CHK_DIST,
  430. gproc_dist:set_value(Key, Value);
  431. set_value({a,l,_} = Key, Value) when is_integer(Value) ->
  432. call({set, Key, Value});
  433. set_value({n,l,_} = Key, Value) ->
  434. %% we cannot do this locally, since we have to check that the object
  435. %% exists first - not an atomic update.
  436. call({set, Key, Value});
  437. set_value({p,l,_} = Key, Value) ->
  438. %% we _can_ to this locally, since there is no race condition - no
  439. %% other process can update our properties.
  440. case gproc_lib:do_set_value(Key, Value, self()) of
  441. true -> true;
  442. false ->
  443. erlang:error(badarg)
  444. end;
  445. set_value({c,l,_} = Key, Value) when is_integer(Value) ->
  446. gproc_lib:do_set_counter_value(Key, Value, self());
  447. set_value(_, _) ->
  448. erlang:error(badarg).
  449. %% @spec (Key) -> Value
  450. %% @doc Read the value stored with a key registered to the current process.
  451. %%
  452. %% If no such key is registered to the current process, this function exits.
  453. %% @end
  454. get_value(Key) ->
  455. get_value(Key, self()).
  456. get_value({T,_,_} = Key, Pid) when is_pid(Pid) ->
  457. if T==n orelse T==a ->
  458. case ets:lookup(?TAB, {Key, T}) of
  459. [{_, P, Value}] when P == Pid -> Value;
  460. _ -> erlang:error(badarg)
  461. end;
  462. true ->
  463. ets:lookup_element(?TAB, {Key, Pid}, 3)
  464. end;
  465. get_value(_, _) ->
  466. erlang:error(badarg).
  467. %% @spec (Key) -> Pid
  468. %% @doc Lookup the Pid stored with a key.
  469. %%
  470. lookup_pid({_T,_,_} = Key) ->
  471. case where(Key) of
  472. undefined -> erlang:error(badarg);
  473. P -> P
  474. end.
  475. %% @spec (Key) -> Value
  476. %% @doc Lookup the value stored with a key.
  477. %%
  478. lookup_value({T,_,_} = Key) ->
  479. if T==n orelse T==a ->
  480. ets:lookup_element(?TAB, {Key,T}, 3);
  481. true ->
  482. erlang:error(badarg)
  483. end.
  484. %% @spec (Key::key()) -> pid()
  485. %%
  486. %% @doc Returns the pid registered as Key
  487. %%
  488. %% The type of registration entry must be either name or aggregated counter.
  489. %% Otherwise this function will exit. Use {@link lookup_pids/1} in these
  490. %% cases.
  491. %% @end
  492. %%
  493. where({T,_,_}=Key) ->
  494. if T==n orelse T==a ->
  495. case ets:lookup(?TAB, {Key,T}) of
  496. [{_, P, _Value}] ->
  497. case my_is_process_alive(P) of
  498. true -> P;
  499. false ->
  500. undefined
  501. end;
  502. _ -> % may be [] or [{Key,Waiters}]
  503. undefined
  504. end;
  505. true ->
  506. erlang:error(badarg)
  507. end.
  508. %% @equiv where/1
  509. whereis_name(Key) ->
  510. where(Key).
  511. %% @spec (Key::key()) -> [pid()]
  512. %%
  513. %% @doc Returns a list of pids with the published key Key
  514. %%
  515. %% If the type of registration entry is either name or aggregated counter,
  516. %% this function will return either an empty list, or a list of one pid.
  517. %% For non-unique types, the return value can be a list of any length.
  518. %% @end
  519. %%
  520. lookup_pids({T,_,_} = Key) ->
  521. L = if T==n orelse T==a ->
  522. ets:select(?TAB, [{{{Key,T}, '$1', '_'},[],['$1']}]);
  523. true ->
  524. ets:select(?TAB, [{{{Key,'_'}, '$1', '_'},[],['$1']}])
  525. end,
  526. [P || P <- L, my_is_process_alive(P)].
  527. %% @spec (pid()) -> boolean()
  528. %%
  529. my_is_process_alive(P) when node(P) =:= node() ->
  530. is_process_alive(P);
  531. my_is_process_alive(_) ->
  532. %% remote pid - assume true (too costly to find out)
  533. true.
  534. %% @spec (Key::key()) -> [{pid(), Value}]
  535. %%
  536. %% @doc Retrieve the `{Pid,Value}' pairs corresponding to Key.
  537. %%
  538. %% Key refer to any type of registry object. If it refers to a unique
  539. %% object, the list will be of length 0 or 1. If it refers to a non-unique
  540. %% object, the return value can be a list of any length.
  541. %% @end
  542. %%
  543. lookup_values({T,_,_} = Key) ->
  544. L = if T==n orelse T==a ->
  545. ets:select(?TAB, [{{{Key,T}, '$1', '$2'},[],[{{'$1','$2'}}]}]);
  546. true ->
  547. ets:select(?TAB, [{{{Key,'_'}, '$1', '$2'},[],[{{'$1','$2'}}]}])
  548. end,
  549. [Pair || {P,_} = Pair <- L, my_is_process_alive(P)].
  550. %% @spec (Key::key(), Incr::integer()) -> integer()
  551. %%
  552. %% @doc Updates the counter registered as Key for the current process.
  553. %%
  554. %% This function works like ets:update_counter/3
  555. %% (see [http://www.erlang.org/doc/man/ets.html#update_counter-3]), but
  556. %% will fail if the type of object referred to by Key is not a counter.
  557. %% @end
  558. %%
  559. update_counter({c,l,_} = Key, Incr) when is_integer(Incr) ->
  560. gproc_lib:update_counter(Key, Incr, self());
  561. update_counter({c,g,_} = Key, Incr) when is_integer(Incr) ->
  562. ?CHK_DIST,
  563. gproc_dist:update_counter(Key, Incr);
  564. update_counter(_, _) ->
  565. erlang:error(badarg).
  566. %% @spec (From::key(), To::pid() | key()) -> undefined | pid()
  567. %%
  568. %% @doc Atomically transfers the key `From' to the process identified by `To'.
  569. %%
  570. %% This function transfers any gproc key (name, property, counter, aggr. counter)
  571. %% from one process to another, and returns the pid of the new owner.
  572. %%
  573. %% `To' must be either a pid or a unique name (name or aggregated counter), but
  574. %% does not necessarily have to resolve to an existing process. If there is
  575. %% no process registered with the `To' key, `give_away/2' returns `undefined',
  576. %% and the `From' key is effectively unregistered.
  577. %%
  578. %% It is allowed to give away a key to oneself, but of course, this operation
  579. %% will have no effect.
  580. %%
  581. %% Fails with `badarg' if the calling process does not have a `From' key
  582. %% registered.
  583. %% @end
  584. give_away({_,l,_} = Key, ToPid) when is_pid(ToPid), node(ToPid) == node() ->
  585. call({give_away, Key, ToPid});
  586. give_away({_,l,_} = Key, {n,l,_} = ToKey) ->
  587. call({give_away, Key, ToKey});
  588. give_away({_,g,_} = Key, To) ->
  589. ?CHK_DIST,
  590. gproc_dist:give_away(Key, To).
  591. %% @spec (Key::key(), Msg::any()) -> Msg
  592. %%
  593. %% @doc Sends a message to the process, or processes, corresponding to Key.
  594. %%
  595. %% If Key belongs to a unique object (name or aggregated counter), this
  596. %% function will send a message to the corresponding process, or fail if there
  597. %% is no such process. If Key is for a non-unique object type (counter or
  598. %% property), Msg will be send to all processes that have such an object.
  599. %% @end
  600. %%
  601. send({T,C,_} = Key, Msg) when C==l; C==g ->
  602. if T == n orelse T == a ->
  603. case ets:lookup(?TAB, {Key, T}) of
  604. [{_, Pid, _}] ->
  605. Pid ! Msg;
  606. _ ->
  607. erlang:error(badarg)
  608. end;
  609. T==p orelse T==c ->
  610. %% BUG - if the key part contains select wildcards, we may end up
  611. %% sending multiple messages to the same pid
  612. lists:foreach(fun(Pid) ->
  613. Pid ! Msg
  614. end, lookup_pids(Key)),
  615. Msg;
  616. true ->
  617. erlang:error(badarg)
  618. end;
  619. send(_, _) ->
  620. erlang:error(badarg).
  621. %% @spec (Context :: context()) -> key() | '$end_of_table'
  622. %%
  623. %% @doc Behaves as ets:first(Tab) for a given type of registration object.
  624. %%
  625. %% See [http://www.erlang.org/doc/man/ets.html#first-1].
  626. %% The registry behaves as an ordered_set table.
  627. %% @end
  628. %%
  629. first(Context) ->
  630. {S, T} = get_s_t(Context),
  631. {HeadPat,_} = headpat({S, T}, '_', '_', '_'),
  632. case ets:select(?TAB, [{HeadPat,[],[{element,1,'$_'}]}], 1) of
  633. {[First], _} ->
  634. First;
  635. _ ->
  636. '$end_of_table'
  637. end.
  638. %% @spec (Context :: context()) -> key() | '$end_of_table'
  639. %%
  640. %% @doc Behaves as ets:last(Tab) for a given type of registration object.
  641. %%
  642. %% See [http://www.erlang.org/doc/man/ets.html#last-1].
  643. %% The registry behaves as an ordered_set table.
  644. %% @end
  645. %%
  646. last(Context) ->
  647. {S, T} = get_s_t(Context),
  648. S1 = if S == '_'; S == l -> m; % 'm' comes after 'l'
  649. S == g -> h % 'h' comes between 'g' & 'l'
  650. end,
  651. Beyond = {{T,S1,[]},[]},
  652. step(ets:prev(?TAB, Beyond), S, T).
  653. %% @spec (Context::context(), Key::key()) -> key() | '$end_of_table'
  654. %%
  655. %% @doc Behaves as ets:next(Tab,Key) for a given type of registration object.
  656. %%
  657. %% See [http://www.erlang.org/doc/man/ets.html#next-2].
  658. %% The registry behaves as an ordered_set table.
  659. %% @end
  660. %%
  661. next(Context, K) ->
  662. {S,T} = get_s_t(Context),
  663. step(ets:next(?TAB,K), S, T).
  664. %% @spec (Context::context(), Key::key()) -> key() | '$end_of_table'
  665. %%
  666. %% @doc Behaves as ets:prev(Tab,Key) for a given type of registration object.
  667. %%
  668. %% See [http://www.erlang.org/doc/man/ets.html#prev-2].
  669. %% The registry behaves as an ordered_set table.
  670. %% @end
  671. %%
  672. prev(Context, K) ->
  673. {S, T} = get_s_t(Context),
  674. step(ets:prev(?TAB, K), S, T).
  675. step(Key, '_', '_') ->
  676. case Key of
  677. {{_,_,_},_} -> Key;
  678. _ -> '$end_of_table'
  679. end;
  680. step(Key, '_', T) ->
  681. case Key of
  682. {{T,_,_},_} -> Key;
  683. _ -> '$end_of_table'
  684. end;
  685. step(Key, S, '_') ->
  686. case Key of
  687. {{_, S, _}, _} -> Key;
  688. _ -> '$end_of_table'
  689. end;
  690. step(Key, S, T) ->
  691. case Key of
  692. {{T, S, _}, _} -> Key;
  693. _ -> '$end_of_table'
  694. end.
  695. %% @spec (Pid::pid()) -> ProcessInfo
  696. %% ProcessInfo = [{gproc, [{Key,Value}]} | ProcessInfo]
  697. %%
  698. %% @doc Similar to `process_info(Pid)' but with additional gproc info.
  699. %%
  700. %% Returns the same information as process_info(Pid), but with the
  701. %% addition of a `gproc' information item, containing the `{Key,Value}'
  702. %% pairs registered to the process.
  703. %% @end
  704. info(Pid) when is_pid(Pid) ->
  705. Items = [?MODULE | [ I || {I,_} <- process_info(self())]],
  706. [info(Pid,I) || I <- Items].
  707. %% @spec (Pid::pid(), Item::atom()) -> {Item, Info}
  708. %%
  709. %% @doc Similar to process_info(Pid, Item), but with additional gproc info.
  710. %%
  711. %% For `Item = gproc', this function returns a list of `{Key, Value}' pairs
  712. %% registered to the process Pid. For other values of Item, it returns the
  713. %% same as [http://www.erlang.org/doc/man/erlang.html#process_info-2].
  714. %% @end
  715. info(Pid, ?MODULE) ->
  716. Keys = ets:select(?TAB, [{ {{Pid,'$1'}, r}, [], ['$1'] }]),
  717. {?MODULE, lists:zf(
  718. fun(K) ->
  719. try V = get_value(K, Pid),
  720. {true, {K,V}}
  721. catch
  722. error:_ ->
  723. false
  724. end
  725. end, Keys)};
  726. info(Pid, I) ->
  727. process_info(Pid, I).
  728. %%% ==========================================================
  729. %% @hidden
  730. handle_cast({monitor_me, Pid}, S) ->
  731. erlang:monitor(process, Pid),
  732. {noreply, S};
  733. handle_cast({cancel_wait, Pid, {T,_,_} = Key, Ref}, S) ->
  734. Rev = {Pid,Key},
  735. case ets:lookup(?TAB, {Key,T}) of
  736. [{K, Waiters}] ->
  737. case Waiters -- [{Pid,Ref}] of
  738. [] ->
  739. ets:delete(?TAB, K),
  740. ets:delete(?TAB, Rev);
  741. NewWaiters ->
  742. ets:insert(?TAB, {K, NewWaiters}),
  743. case lists:keymember(Pid, 1, NewWaiters) of
  744. true ->
  745. %% should be extremely unlikely
  746. ok;
  747. false ->
  748. %% delete the reverse entry
  749. ets:delete(?TAB, Rev)
  750. end
  751. end;
  752. _ ->
  753. ignore
  754. end,
  755. {noreply, S}.
  756. %% @hidden
  757. handle_call({reg, {_T,l,_} = Key, Val}, {Pid,_}, S) ->
  758. case try_insert_reg(Key, Val, Pid) of
  759. true ->
  760. gproc_lib:ensure_monitor(Pid,l),
  761. {reply, true, S};
  762. false ->
  763. {reply, badarg, S}
  764. end;
  765. handle_call({unreg, {_,l,_} = Key}, {Pid,_}, S) ->
  766. case ets:member(?TAB, {Pid,Key}) of
  767. true ->
  768. gproc_lib:remove_reg(Key, Pid),
  769. {reply, true, S};
  770. false ->
  771. {reply, badarg, S}
  772. end;
  773. handle_call({await, {_,l,_} = Key, Pid}, From, S) ->
  774. %% Passing the pid explicitly is needed when leader_call is used,
  775. %% since the Pid given as From in the leader is the local gen_leader
  776. %% instance on the calling node.
  777. case gproc_lib:await(Key, Pid, From) of
  778. noreply ->
  779. {noreply, S};
  780. {reply, Reply, _} ->
  781. {reply, Reply, S}
  782. end;
  783. handle_call({mreg, T, l, L}, {Pid,_}, S) ->
  784. try gproc_lib:insert_many(T, l, L, Pid) of
  785. {true,_} -> {reply, true, S};
  786. false -> {reply, badarg, S}
  787. catch
  788. error:_ -> {reply, badarg, S}
  789. end;
  790. handle_call({set, {_,l,_} = Key, Value}, {Pid,_}, S) ->
  791. case gproc_lib:do_set_value(Key, Value, Pid) of
  792. true ->
  793. {reply, true, S};
  794. false ->
  795. {reply, badarg, S}
  796. end;
  797. handle_call({audit_process, Pid}, _, S) ->
  798. case is_process_alive(Pid) of
  799. false ->
  800. process_is_down(Pid);
  801. true ->
  802. ignore
  803. end,
  804. {reply, ok, S};
  805. handle_call({give_away, Key, To}, {Pid,_}, S) ->
  806. Reply = do_give_away(Key, To, Pid),
  807. {reply, Reply, S};
  808. handle_call(_, _, S) ->
  809. {reply, badarg, S}.
  810. %% @hidden
  811. handle_info({'DOWN', _MRef, process, Pid, _}, S) ->
  812. process_is_down(Pid),
  813. {noreply, S};
  814. handle_info(_, S) ->
  815. {noreply, S}.
  816. %% @hidden
  817. code_change(_FromVsn, S, _Extra) ->
  818. %% We have changed local monitor markers from {Pid} to {Pid,l}.
  819. case ets:select(?TAB, [{{'$1'},[],['$1']}]) of
  820. [] ->
  821. ok;
  822. Pids ->
  823. ets:insert(?TAB, [{P,l} || P <- Pids]),
  824. ets:select_delete(?TAB, [{{'_'},[],[true]}])
  825. end,
  826. {ok, S}.
  827. %% @hidden
  828. terminate(_Reason, _S) ->
  829. ok.
  830. call(Req) ->
  831. call(Req, l).
  832. call(Req, l) ->
  833. chk_reply(gen_server:call(?MODULE, Req), Req);
  834. call(Req, g) ->
  835. chk_reply(gproc_dist:leader_call(Req), Req).
  836. chk_reply(Reply, Req) ->
  837. case Reply of
  838. badarg -> erlang:error(badarg, Req);
  839. _ -> Reply
  840. end.
  841. cast(Msg) ->
  842. cast(Msg, l).
  843. cast(Msg, l) ->
  844. gen_server:cast(?MODULE, Msg);
  845. cast(Msg, g) ->
  846. gproc_dist:leader_cast(Msg).
  847. try_insert_reg({T,l,_} = Key, Val, Pid) ->
  848. case gproc_lib:insert_reg(Key, Val, Pid, l) of
  849. false ->
  850. case ets:lookup(?TAB, {Key,T}) of
  851. %% In this particular case, the lookup cannot result in
  852. %% [{_, Waiters}], since the insert_reg/4 function would
  853. %% have succeeded then.
  854. [{_, OtherPid, _}] ->
  855. case is_process_alive(OtherPid) of
  856. true ->
  857. false;
  858. false ->
  859. process_is_down(OtherPid),
  860. true = gproc_lib:insert_reg(Key, Val, Pid, l)
  861. end;
  862. [] ->
  863. false
  864. end;
  865. true ->
  866. true
  867. end.
  868. -spec audit_process(pid()) -> ok.
  869. audit_process(Pid) when is_pid(Pid) ->
  870. gen_server:call(gproc, {audit_process, Pid}, infinity).
  871. -spec process_is_down(pid()) -> ok.
  872. process_is_down(Pid) ->
  873. %% delete the monitor marker
  874. %% io:fwrite(user, "process_is_down(~p) - ~p~n", [Pid,ets:tab2list(?TAB)]),
  875. ets:delete(?TAB, {Pid,l}),
  876. Revs = ets:select(?TAB, [{{{Pid,'$1'},r},
  877. [{'==',{element,2,'$1'},l}], ['$1']}]),
  878. lists:foreach(
  879. fun({n,l,_}=K) ->
  880. Key = {K,n},
  881. case ets:lookup(?TAB, Key) of
  882. [{_, Pid, _}] ->
  883. ets:delete(?TAB, Key);
  884. [{_, Waiters}] ->
  885. case [W || {P,_} = W <- Waiters,
  886. P =/= Pid] of
  887. [] ->
  888. ets:delete(?TAB, Key);
  889. Waiters1 ->
  890. ets:insert(?TAB, {Key, Waiters1})
  891. end;
  892. [] ->
  893. true
  894. end;
  895. ({c,l,C} = K) ->
  896. Key = {K, Pid},
  897. [{_, _, Value}] = ets:lookup(?TAB, Key),
  898. ets:delete(?TAB, Key),
  899. gproc_lib:update_aggr_counter(l, C, -Value);
  900. ({a,l,_} = K) ->
  901. ets:delete(?TAB, {K,a});
  902. ({p,_,_} = K) ->
  903. ets:delete(?TAB, {K, Pid})
  904. end, Revs),
  905. ets:select_delete(?TAB, [{{{Pid,{'_',l,'_'}},'_'}, [], [true]}]),
  906. ok.
  907. do_give_away({T,l,_} = K, To, Pid) when T==n; T==a ->
  908. Key = {K, T},
  909. case ets:lookup(?TAB, Key) of
  910. [{_, Pid, Value}] ->
  911. %% Pid owns the reg; allowed to give_away
  912. case pid_to_give_away_to(To) of
  913. Pid ->
  914. %% Give away to ourselves? Why not? We'll allow it,
  915. %% but nothing needs to be done.
  916. Pid;
  917. ToPid when is_pid(ToPid) ->
  918. ets:insert(?TAB, [{Key, ToPid, Value},
  919. {{ToPid, K}, r}]),
  920. ets:delete(?TAB, {Pid, K}),
  921. gproc_lib:ensure_monitor(ToPid, l),
  922. ToPid;
  923. undefined ->
  924. gproc_lib:remove_reg(K, Pid),
  925. undefined
  926. end;
  927. _ ->
  928. badarg
  929. end;
  930. do_give_away({T,l,_} = K, To, Pid) when T==c; T==p ->
  931. Key = {K, Pid},
  932. case ets:lookup(?TAB, Key) of
  933. [{_, Pid, Value}] ->
  934. case pid_to_give_away_to(To) of
  935. ToPid when is_pid(ToPid) ->
  936. ToKey = {K, ToPid},
  937. case ets:member(?TAB, ToKey) of
  938. true ->
  939. badarg;
  940. false ->
  941. ets:insert(?TAB, [{ToKey, ToPid, Value},
  942. {{ToPid, K}, r}]),
  943. ets:delete(?TAB, {Pid, K}),
  944. ets:delete(?TAB, Key),
  945. gproc_lib:ensure_monitor(ToPid, l),
  946. ToPid
  947. end;
  948. undefined ->
  949. gproc_lib:remove_reg(K, Pid),
  950. undefined
  951. end;
  952. _ ->
  953. badarg
  954. end.
  955. pid_to_give_away_to(P) when is_pid(P), node(P) == node() ->
  956. P;
  957. pid_to_give_away_to({T,l,_} = Key) when T==n; T==a ->
  958. case ets:lookup(?TAB, {Key, T}) of
  959. [{_, Pid, _}] ->
  960. Pid;
  961. _ ->
  962. undefined
  963. end.
  964. create_tabs() ->
  965. case ets:info(?TAB, name) of
  966. undefined ->
  967. ets:new(?TAB, [ordered_set, public, named_table]);
  968. _ ->
  969. ok
  970. end.
  971. %% @hidden
  972. init([]) ->
  973. set_monitors(),
  974. {ok, #state{}}.
  975. set_monitors() ->
  976. set_monitors(ets:select(?TAB, [{{{'$1',l}},[],['$1']}], 100)).
  977. set_monitors('$end_of_table') ->
  978. ok;
  979. set_monitors({Pids, Cont}) ->
  980. [erlang:monitor(process,Pid) || Pid <- Pids],
  981. set_monitors(ets:select(Cont)).
  982. monitor_me() ->
  983. case ets:insert_new(?TAB, {{self(),l}}) of
  984. false -> true;
  985. true ->
  986. cast({monitor_me,self()}),
  987. true
  988. end.
  989. pattern([{'_', Gs, As}], T) ->
  990. ?l,
  991. {HeadPat, Vs} = headpat(T, '$1', '$2', '$3'),
  992. [{HeadPat, rewrite(Gs,Vs), rewrite(As,Vs)}];
  993. pattern([{{A,B,C},Gs,As}], Scope) ->
  994. ?l,
  995. {HeadPat, Vars} = headpat(Scope, A,B,C),
  996. [{HeadPat, rewrite(Gs,Vars), rewrite(As,Vars)}];
  997. pattern([{Head, Gs, As}], Scope) ->
  998. ?l,
  999. {S, T} = get_s_t(Scope),
  1000. case is_var(Head) of
  1001. {true,_N} ->
  1002. HeadPat = {{{T,S,'_'},'_'},'_','_'},
  1003. Vs = [{Head, obj_prod()}],
  1004. %% {HeadPat, Vs} = headpat(Scope, A,B,C),
  1005. %% the headpat function should somehow verify that Head is
  1006. %% consistent with Scope (or should we add a guard?)
  1007. [{HeadPat, rewrite(Gs, Vs), rewrite(As, Vs)}];
  1008. false ->
  1009. erlang:error(badarg)
  1010. end.
  1011. %% This is the expression to use in guards and the RHS to address the whole
  1012. %% object, in its logical representation.
  1013. obj_prod() ->
  1014. {{ {element,1,{element,1,'$_'}},
  1015. {element,2,'$_'},
  1016. {element,3,'$_'} }}.
  1017. obj_prod_l() ->
  1018. [ {element,1,{element,1,'$_'}},
  1019. {element,2,'$_'},
  1020. {element,3,'$_'} ].
  1021. headpat({S, T}, V1,V2,V3) ->
  1022. headpat(type(T), scope(S), V1,V2,V3);
  1023. headpat(T, V1, V2, V3) when is_atom(T) ->
  1024. headpat(type(T), l, V1, V2, V3);
  1025. headpat(_, _, _, _) -> erlang:error(badarg).
  1026. headpat(T, C, V1,V2,V3) ->
  1027. Rf = fun(Pos) ->
  1028. {element,Pos,{element,1,{element,1,'$_'}}}
  1029. end,
  1030. K2 = if T==n orelse T==a -> T;
  1031. true -> '_'
  1032. end,
  1033. {Kp,Vars} = case V1 of
  1034. {Vt,Vc,Vn} ->
  1035. ?l,
  1036. {T1,Vs1} = subst(T,Vt,fun() -> Rf(1) end,[]),
  1037. {C1,Vs2} = subst(C,Vc,fun() -> Rf(2) end,Vs1),
  1038. {{T1,C1,Vn}, Vs2};
  1039. '_' ->
  1040. ?l,
  1041. {{T,C,'_'}, []};
  1042. _ ->
  1043. ?l,
  1044. case is_var(V1) of
  1045. {true,_} ->
  1046. {{T,C,V1}, [{V1, {element,1,
  1047. {element,1,'$_'}}}]};
  1048. false ->
  1049. erlang:error(badarg)
  1050. end
  1051. end,
  1052. {{{Kp,K2},V2,V3}, Vars}.
  1053. %% l(L) -> L.
  1054. subst(X, '_', _F, Vs) ->
  1055. {X, Vs};
  1056. subst(X, V, F, Vs) ->
  1057. case is_var(V) of
  1058. {true,_} ->
  1059. {X, [{V,F()}|Vs]};
  1060. false ->
  1061. {V, Vs}
  1062. end.
  1063. scope('_') -> '_';
  1064. scope(all) -> '_';
  1065. scope(global) -> g;
  1066. scope(local) -> l;
  1067. scope(S) when S==l; S==g -> S.
  1068. type('_') -> '_';
  1069. type(all) -> '_';
  1070. type(T) when T==n; T==p; T==c; T==a -> T;
  1071. type(names) -> n;
  1072. type(props) -> p;
  1073. type(counters) -> c;
  1074. type(aggr_counters) -> a.
  1075. rev_keypat(Context) ->
  1076. {S,T} = get_s_t(Context),
  1077. {T,S,'_'}.
  1078. get_s_t({S,T}) -> {scope(S), type(T)};
  1079. get_s_t(T) when is_atom(T) ->
  1080. {scope(all), type(T)}.
  1081. is_var('$1') -> {true,1};
  1082. is_var('$2') -> {true,2};
  1083. is_var('$3') -> {true,3};
  1084. is_var('$4') -> {true,4};
  1085. is_var('$5') -> {true,5};
  1086. is_var('$6') -> {true,6};
  1087. is_var('$7') -> {true,7};
  1088. is_var('$8') -> {true,8};
  1089. is_var('$9') -> {true,9};
  1090. is_var(X) when is_atom(X) ->
  1091. case atom_to_list(X) of
  1092. "$" ++ Tl ->
  1093. try N = list_to_integer(Tl),
  1094. {true,N}
  1095. catch
  1096. error:_ ->
  1097. false
  1098. end;
  1099. _ ->
  1100. false
  1101. end;
  1102. is_var(_) -> false.
  1103. rewrite(Gs, R) ->
  1104. [rewrite1(G, R) || G <- Gs].
  1105. rewrite1('$_', _) ->
  1106. obj_prod();
  1107. rewrite1('$$', _) ->
  1108. obj_prod_l();
  1109. rewrite1(Guard, R) when is_tuple(Guard) ->
  1110. list_to_tuple([rewrite1(G, R) || G <- tuple_to_list(Guard)]);
  1111. rewrite1(Exprs, R) when is_list(Exprs) ->
  1112. [rewrite1(E, R) || E <- Exprs];
  1113. rewrite1(V, R) when is_atom(V) ->
  1114. case is_var(V) of
  1115. {true,_N} ->
  1116. case lists:keysearch(V, 1, R) of
  1117. {value, {_, V1}} ->
  1118. V1;
  1119. false ->
  1120. V
  1121. end;
  1122. false ->
  1123. V
  1124. end;
  1125. rewrite1(Expr, _) ->
  1126. Expr.
  1127. %% @spec (Context::context()) -> any()
  1128. %%
  1129. %% @doc
  1130. %% @equiv table(Context, [])
  1131. %% @end
  1132. %%
  1133. table(Context) ->
  1134. table(Context, []).
  1135. %% @spec (Context::context(), Opts) -> any()
  1136. %%
  1137. %% @doc QLC table generator for the gproc registry.
  1138. %% Context specifies which subset of the registry should be queried.
  1139. %% See [http://www.erlang.org/doc/man/qlc.html].
  1140. %% @end
  1141. table(Context, Opts) ->
  1142. Ctxt = get_s_t(Context),
  1143. [Traverse, NObjs] = [proplists:get_value(K,Opts,Def) ||
  1144. {K,Def} <- [{traverse,select}, {n_objects,100}]],
  1145. TF = case Traverse of
  1146. first_next ->
  1147. fun() -> qlc_next(Ctxt, first(Ctxt)) end;
  1148. last_prev -> fun() -> qlc_prev(Ctxt, last(Ctxt)) end;
  1149. select ->
  1150. fun(MS) -> qlc_select(select(Ctxt, MS, NObjs)) end;
  1151. {select,MS} ->
  1152. fun() -> qlc_select(select(Ctxt, MS, NObjs)) end;
  1153. _ ->
  1154. erlang:error(badarg, [Ctxt,Opts])
  1155. end,
  1156. InfoFun = fun(indices) -> [2];
  1157. (is_unique_objects) -> is_unique(Ctxt);
  1158. (keypos) -> 1;
  1159. (is_sorted_key) -> true;
  1160. (num_of_objects) ->
  1161. %% this is just a guesstimate.
  1162. trunc(ets:info(?TAB,size) / 2.5)
  1163. end,
  1164. LookupFun =
  1165. case Traverse of
  1166. {select, _MS} -> undefined;
  1167. _ -> fun(Pos, Ks) -> qlc_lookup(Ctxt, Pos, Ks) end
  1168. end,
  1169. qlc:table(TF, [{info_fun, InfoFun},
  1170. {lookup_fun, LookupFun}] ++ [{K,V} || {K,V} <- Opts,
  1171. K =/= traverse,
  1172. K =/= n_objects]).
  1173. qlc_lookup(_Scope, 1, Keys) ->
  1174. lists:flatmap(
  1175. fun(Key) ->
  1176. ets:select(?TAB, [{ {{Key,'_'},'_','_'}, [],
  1177. [{{ {element,1,{element,1,'$_'}},
  1178. {element,2,'$_'},
  1179. {element,3,'$_'} }}] }])
  1180. end, Keys);
  1181. qlc_lookup(Scope, 2, Pids) ->
  1182. lists:flatmap(fun(Pid) ->
  1183. Found =
  1184. ets:select(?TAB, [{ {{Pid, rev_keypat(Scope)}, r},
  1185. [], ['$_']}]),
  1186. lists:flatmap(
  1187. fun({{_,{T,_,_}=K}, r}) ->
  1188. K2 = if T==n orelse T==a -> T;
  1189. true -> Pid
  1190. end,
  1191. case ets:lookup(?TAB, {K,K2}) of
  1192. [{{Key,_},_,Value}] ->
  1193. [{Key, Pid, Value}];
  1194. [] ->
  1195. []
  1196. end
  1197. end, Found)
  1198. end, Pids).
  1199. qlc_next(_, '$end_of_table') -> [];
  1200. qlc_next(Scope, K) ->
  1201. case ets:lookup(?TAB, K) of
  1202. [{{Key,_}, Pid, V}] ->
  1203. [{Key,Pid,V}] ++ fun() -> qlc_next(Scope, next(Scope, K)) end;
  1204. [] ->
  1205. qlc_next(Scope, next(Scope, K))
  1206. end.
  1207. qlc_prev(_, '$end_of_table') -> [];
  1208. qlc_prev(Scope, K) ->
  1209. case ets:lookup(?TAB, K) of
  1210. [{{Key,_},Pid,V}] ->
  1211. [{Key,Pid,V}] ++ fun() -> qlc_prev(Scope, prev(Scope, K)) end;
  1212. [] ->
  1213. qlc_prev(Scope, prev(Scope, K))
  1214. end.
  1215. qlc_select('$end_of_table') ->
  1216. [];
  1217. qlc_select({Objects, Cont}) ->
  1218. Objects ++ fun() -> qlc_select(ets:select(Cont)) end.
  1219. is_unique(names) -> true;
  1220. is_unique(aggr_counters) -> true;
  1221. is_unique({_, names}) -> true;
  1222. is_unique({_, aggr_counters}) -> true;
  1223. is_unique(n) -> true;
  1224. is_unique(a) -> true;
  1225. is_unique({_,n}) -> true;
  1226. is_unique({_,a}) -> true;
  1227. is_unique(_) -> false.