gproc.erl 39 KB

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