gproc.erl 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427
  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. Rev = {Pid,Key},
  692. case ets:lookup(?TAB, {Key,T}) of
  693. [{K, Waiters}] ->
  694. case Waiters -- [{Pid,Ref}] of
  695. [] ->
  696. ets:delete(?TAB, K),
  697. ets:delete(?TAB, Rev);
  698. NewWaiters ->
  699. ets:insert(?TAB, {K, NewWaiters}),
  700. case lists:keymember(Pid, 1, NewWaiters) of
  701. true ->
  702. %% should be extremely unlikely
  703. ok;
  704. false ->
  705. %% delete the reverse entry
  706. ets:delete(?TAB, Rev)
  707. end
  708. end;
  709. _ ->
  710. ignore
  711. end,
  712. {noreply, S}.
  713. %% @hidden
  714. handle_call({reg, {_T,l,_} = Key, Val}, {Pid,_}, S) ->
  715. case try_insert_reg(Key, Val, Pid) of
  716. true ->
  717. gproc_lib:ensure_monitor(Pid,l),
  718. {reply, true, S};
  719. false ->
  720. {reply, badarg, S}
  721. end;
  722. handle_call({unreg, {_,l,_} = Key}, {Pid,_}, S) ->
  723. case ets:member(?TAB, {Pid,Key}) of
  724. true ->
  725. gproc_lib:remove_reg(Key, Pid),
  726. {reply, true, S};
  727. false ->
  728. {reply, badarg, S}
  729. end;
  730. handle_call({await, {_,l,_} = Key, Pid}, {_, Ref}, S) ->
  731. %% Passing the pid explicitly is needed when leader_call is used,
  732. %% since the Pid given as From in the leader is the local gen_leader
  733. %% instance on the calling node.
  734. case gproc_lib:await(Key, {Pid, Ref}) of
  735. noreply ->
  736. {noreply, S};
  737. {reply, Reply, _} ->
  738. {reply, Reply, S}
  739. end;
  740. %% Rev = {{Pid,Key}, r},
  741. %% case ets:lookup(?TAB, {Key,T}) of
  742. %% [{_, P, Value}] ->
  743. %% %% for symmetry, we always reply with Ref and then send a message
  744. %% gen_server:reply(From, Ref),
  745. %% Pid ! {gproc, Ref, registered, {Key, P, Value}},
  746. %% {noreply, S};
  747. %% [{K, Waiters}] ->
  748. %% NewWaiters = [{Pid,Ref} | Waiters],
  749. %% ets:insert(?TAB, [{K, NewWaiters}, Rev]),
  750. %% gproc_lib:ensure_monitor(Pid,l),
  751. %% {reply, Ref, S};
  752. %% [] ->
  753. %% ets:insert(?TAB, [{{Key,T}, [{Pid,Ref}]}, Rev]),
  754. %% gproc_lib:ensure_monitor(Pid,l),
  755. %% {reply, Ref, S}
  756. %% end;
  757. handle_call({mreg, T, l, L}, {Pid,_}, S) ->
  758. try gproc_lib:insert_many(T, l, L, Pid) of
  759. {true,_} -> {reply, true, S};
  760. false -> {reply, badarg, S}
  761. catch
  762. error:_ -> {reply, badarg, S}
  763. end;
  764. handle_call({set, {_,l,_} = Key, Value}, {Pid,_}, S) ->
  765. case gproc_lib:do_set_value(Key, Value, Pid) of
  766. true ->
  767. {reply, true, S};
  768. false ->
  769. {reply, badarg, S}
  770. end;
  771. handle_call({audit_process, Pid}, _, S) ->
  772. case is_process_alive(Pid) of
  773. false ->
  774. process_is_down(Pid);
  775. true ->
  776. ignore
  777. end,
  778. {reply, ok, S};
  779. handle_call(_, _, S) ->
  780. {reply, badarg, S}.
  781. %% @hidden
  782. handle_info({'DOWN', _MRef, process, Pid, _}, S) ->
  783. process_is_down(Pid),
  784. {noreply, S};
  785. handle_info(_, S) ->
  786. {noreply, S}.
  787. %% @hidden
  788. code_change(_FromVsn, S, _Extra) ->
  789. %% We have changed local monitor markers from {Pid} to {Pid,l}.
  790. case ets:select(?TAB, [{{'$1'},[],['$1']}]) of
  791. [] ->
  792. ok;
  793. Pids ->
  794. ets:insert(?TAB, [{P,l} || P <- Pids]),
  795. ets:select_delete(?TAB, [{{'_'},[],[true]}])
  796. end,
  797. {ok, S}.
  798. %% @hidden
  799. terminate(_Reason, _S) ->
  800. ok.
  801. call(Req) ->
  802. call(Req, l).
  803. call(Req, l) ->
  804. chk_reply(gen_server:call(?MODULE, Req), Req);
  805. call(Req, g) ->
  806. chk_reply(gproc_dist:leader_call(Req), Req).
  807. chk_reply(Reply, Req) ->
  808. case Reply of
  809. badarg -> erlang:error(badarg, Req);
  810. Reply -> Reply
  811. end.
  812. cast(Msg) ->
  813. cast(Msg, l).
  814. cast(Msg, l) ->
  815. gen_server:cast(?MODULE, Msg);
  816. cast(Msg, g) ->
  817. gproc_dist:leader_cast(Msg).
  818. try_insert_reg({T,l,_} = Key, Val, Pid) ->
  819. case gproc_lib:insert_reg(Key, Val, Pid, l) of
  820. false ->
  821. case ets:lookup(?TAB, {Key,T}) of
  822. %% In this particular case, the lookup cannot result in
  823. %% [{_, Waiters}], since the insert_reg/4 function would
  824. %% have succeeded then.
  825. [{_, OtherPid, _}] ->
  826. case is_process_alive(OtherPid) of
  827. true ->
  828. false;
  829. false ->
  830. process_is_down(OtherPid),
  831. true = gproc_lib:insert_reg(Key, Val, Pid, l)
  832. end;
  833. [] ->
  834. false
  835. end;
  836. true ->
  837. true
  838. end.
  839. -spec audit_process(pid()) -> ok.
  840. audit_process(Pid) when is_pid(Pid) ->
  841. gen_server:call(gproc, {audit_process, Pid}, infinity).
  842. -spec process_is_down(pid()) -> ok.
  843. process_is_down(Pid) ->
  844. %% delete the monitor marker
  845. %% io:fwrite(user, "process_is_down(~p) - ~p~n", [Pid,ets:tab2list(?TAB)]),
  846. ets:delete(?TAB, {Pid,l}),
  847. Revs = ets:select(?TAB, [{{{Pid,'$1'},r},
  848. [{'==',{element,2,'$1'},l}], ['$1']}]),
  849. lists:foreach(
  850. fun({n,l,_}=K) ->
  851. Key = {K,n},
  852. case ets:lookup(?TAB, Key) of
  853. [{_, Pid, _}] ->
  854. ets:delete(?TAB, Key);
  855. [{_, Waiters}] ->
  856. case [W || {P,_} = W <- Waiters,
  857. P =/= Pid] of
  858. [] ->
  859. ets:delete(?TAB, Key);
  860. Waiters1 ->
  861. ets:insert(?TAB, {Key, Waiters1})
  862. end;
  863. [] ->
  864. true
  865. end;
  866. ({c,l,C} = K) ->
  867. Key = {K, Pid},
  868. [{_, _, Value}] = ets:lookup(?TAB, Key),
  869. ets:delete(?TAB, Key),
  870. gproc_lib:update_aggr_counter(l, C, -Value);
  871. ({a,l,_} = K) ->
  872. ets:delete(?TAB, {K,a});
  873. ({p,_,_} = K) ->
  874. ets:delete(?TAB, {K, Pid})
  875. end, Revs),
  876. ets:select_delete(?TAB, [{{{Pid,{'_',l,'_'}},'_'}, [], [true]}]),
  877. ok.
  878. create_tabs() ->
  879. case ets:info(?TAB, name) of
  880. undefined ->
  881. ets:new(?TAB, [ordered_set, public, named_table]);
  882. _ ->
  883. ok
  884. end.
  885. %% @hidden
  886. init([]) ->
  887. set_monitors(),
  888. {ok, #state{}}.
  889. set_monitors() ->
  890. set_monitors(ets:select(?TAB, [{{{'$1',l}},[],['$1']}], 100)).
  891. set_monitors('$end_of_table') ->
  892. ok;
  893. set_monitors({Pids, Cont}) ->
  894. [erlang:monitor(process,Pid) || Pid <- Pids],
  895. set_monitors(ets:select(Cont)).
  896. monitor_me() ->
  897. case ets:insert_new(?TAB, {{self(),l}}) of
  898. false -> true;
  899. true ->
  900. cast({monitor_me,self()}),
  901. true
  902. end.
  903. pattern([{'_', Gs, As}], T) ->
  904. ?l,
  905. {HeadPat, Vs} = headpat(T, '$1', '$2', '$3'),
  906. [{HeadPat, rewrite(Gs,Vs), rewrite(As,Vs)}];
  907. pattern([{{A,B,C},Gs,As}], Scope) ->
  908. ?l,
  909. {HeadPat, Vars} = headpat(Scope, A,B,C),
  910. [{HeadPat, rewrite(Gs,Vars), rewrite(As,Vars)}];
  911. pattern([{Head, Gs, As}], Scope) ->
  912. ?l,
  913. case is_var(Head) of
  914. {true,_N} ->
  915. HeadPat = {{{type(Scope),'_','_'},'_'},'_','_'},
  916. Vs = [{Head, obj_prod()}],
  917. %% {HeadPat, Vs} = headpat(Scope, A,B,C),
  918. %% the headpat function should somehow verify that Head is
  919. %% consistent with Scope (or should we add a guard?)
  920. [{HeadPat, rewrite(Gs, Vs), rewrite(As, Vs)}];
  921. false ->
  922. erlang:error(badarg)
  923. end.
  924. %% This is the expression to use in guards and the RHS to address the whole
  925. %% object, in its logical representation.
  926. obj_prod() ->
  927. {{ {element,1,{element,1,'$_'}},
  928. {element,2,'$_'},
  929. {element,3,'$_'} }}.
  930. obj_prod_l() ->
  931. [ {element,1,{element,1,'$_'}},
  932. {element,2,'$_'},
  933. {element,3,'$_'} ].
  934. headpat({S, T}, V1,V2,V3) when S==global; S==local; S==all ->
  935. headpat(type(T), scope(S), V1,V2,V3);
  936. headpat(T, V1, V2, V3) when is_atom(T) ->
  937. headpat(type(T), l, V1, V2, V3);
  938. headpat(_, _, _, _) -> erlang:error(badarg).
  939. headpat(T, C, V1,V2,V3) ->
  940. Rf = fun(Pos) ->
  941. {element,Pos,{element,1,{element,1,'$_'}}}
  942. end,
  943. K2 = if T==n orelse T==a -> T;
  944. true -> '_'
  945. end,
  946. {Kp,Vars} = case V1 of
  947. {Vt,Vc,Vn} ->
  948. ?l,
  949. {T1,Vs1} = subst(T,Vt,fun() -> Rf(1) end,[]),
  950. {C1,Vs2} = subst(C,Vc,fun() -> Rf(2) end,Vs1),
  951. {{T1,C1,Vn}, Vs2};
  952. '_' ->
  953. ?l,
  954. {{T,C,'_'}, []};
  955. _ ->
  956. ?l,
  957. case is_var(V1) of
  958. {true,_} ->
  959. {{T,C,V1}, [{V1, {element,1,
  960. {element,1,'$_'}}}]};
  961. false ->
  962. erlang:error(badarg)
  963. end
  964. end,
  965. {{{Kp,K2},V2,V3}, Vars}.
  966. %% l(L) -> L.
  967. subst(X, '_', _F, Vs) ->
  968. {X, Vs};
  969. subst(X, V, F, Vs) ->
  970. case is_var(V) of
  971. {true,_} ->
  972. {X, [{V,F()}|Vs]};
  973. false ->
  974. {V, Vs}
  975. end.
  976. scope(all) -> '_';
  977. scope(global) -> g;
  978. scope(local) -> l.
  979. type(all) -> '_';
  980. type(T) when T==n; T==p; T==c; T==a -> T;
  981. type(names) -> n;
  982. type(props) -> p;
  983. type(counters) -> c;
  984. type(aggr_counters) -> a.
  985. keypat(Context) ->
  986. {S,T} = get_s_t(Context),
  987. {{T,S,'_'},'_'}.
  988. get_s_t({S,T}) -> {scope(S), type(T)};
  989. get_s_t(T) when is_atom(T) ->
  990. {l, type(T)}.
  991. is_var('$1') -> {true,1};
  992. is_var('$2') -> {true,2};
  993. is_var('$3') -> {true,3};
  994. is_var('$4') -> {true,4};
  995. is_var('$5') -> {true,5};
  996. is_var('$6') -> {true,6};
  997. is_var('$7') -> {true,7};
  998. is_var('$8') -> {true,8};
  999. is_var('$9') -> {true,9};
  1000. is_var(X) when is_atom(X) ->
  1001. case atom_to_list(X) of
  1002. "$" ++ Tl ->
  1003. try N = list_to_integer(Tl),
  1004. {true,N}
  1005. catch
  1006. error:_ ->
  1007. false
  1008. end;
  1009. _ ->
  1010. false
  1011. end;
  1012. is_var(_) -> false.
  1013. rewrite(Gs, R) ->
  1014. [rewrite1(G, R) || G <- Gs].
  1015. rewrite1('$_', _) ->
  1016. obj_prod();
  1017. rewrite1('$$', _) ->
  1018. obj_prod_l();
  1019. rewrite1(Guard, R) when is_tuple(Guard) ->
  1020. list_to_tuple([rewrite1(G, R) || G <- tuple_to_list(Guard)]);
  1021. rewrite1(Exprs, R) when is_list(Exprs) ->
  1022. [rewrite1(E, R) || E <- Exprs];
  1023. rewrite1(V, R) when is_atom(V) ->
  1024. case is_var(V) of
  1025. {true,_N} ->
  1026. case lists:keysearch(V, 1, R) of
  1027. {value, {_, V1}} ->
  1028. V1;
  1029. false ->
  1030. V
  1031. end;
  1032. false ->
  1033. V
  1034. end;
  1035. rewrite1(Expr, _) ->
  1036. Expr.
  1037. %% @spec (Context::context()) -> any()
  1038. %%
  1039. %% @doc
  1040. %% @equiv table(Context, [])
  1041. %% @end
  1042. %%
  1043. table(Context) ->
  1044. table(Context, []).
  1045. %% @spec (Context::context(), Opts) -> any()
  1046. %%
  1047. %% @doc QLC table generator for the gproc registry.
  1048. %% Context specifies which subset of the registry should be queried.
  1049. %% See [http://www.erlang.org/doc/man/qlc.html].
  1050. %% @end
  1051. table(Ctxt, Opts) ->
  1052. [Traverse, NObjs] = [proplists:get_value(K,Opts,Def) ||
  1053. {K,Def} <- [{traverse,select}, {n_objects,100}]],
  1054. TF = case Traverse of
  1055. first_next ->
  1056. fun() -> qlc_next(Ctxt, first(Ctxt)) end;
  1057. last_prev -> fun() -> qlc_prev(Ctxt, last(Ctxt)) end;
  1058. select ->
  1059. fun(MS) -> qlc_select(select(Ctxt, MS, NObjs)) end;
  1060. {select,MS} ->
  1061. fun() -> qlc_select(select(Ctxt, MS, NObjs)) end;
  1062. _ ->
  1063. erlang:error(badarg, [Ctxt,Opts])
  1064. end,
  1065. InfoFun = fun(indices) -> [2];
  1066. (is_unique_objects) -> is_unique(Ctxt);
  1067. (keypos) -> 1;
  1068. (is_sorted_key) -> true;
  1069. (num_of_objects) ->
  1070. %% this is just a guesstimate.
  1071. trunc(ets:info(?TAB,size) / 2.5)
  1072. end,
  1073. LookupFun =
  1074. case Traverse of
  1075. {select, _MS} -> undefined;
  1076. _ -> fun(Pos, Ks) -> qlc_lookup(Ctxt, Pos, Ks) end
  1077. end,
  1078. qlc:table(TF, [{info_fun, InfoFun},
  1079. {lookup_fun, LookupFun}] ++ [{K,V} || {K,V} <- Opts,
  1080. K =/= traverse,
  1081. K =/= n_objects]).
  1082. qlc_lookup(_Scope, 1, Keys) ->
  1083. lists:flatmap(
  1084. fun(Key) ->
  1085. ets:select(?TAB, [{ {{Key,'_'},'_','_'}, [],
  1086. [{{ {element,1,{element,1,'$_'}},
  1087. {element,2,'$_'},
  1088. {element,3,'$_'} }}] }])
  1089. end, Keys);
  1090. qlc_lookup(Scope, 2, Pids) ->
  1091. lists:flatmap(fun(Pid) ->
  1092. Found =
  1093. ets:select(?TAB, [{ {{Pid,keypat(Scope)}},
  1094. [], ['$_']}]),
  1095. lists:flatmap(
  1096. fun({{_,{T,_,_}=K}}) ->
  1097. K2 = if T==n orelse T==a -> T;
  1098. true -> Pid
  1099. end,
  1100. case ets:lookup(?TAB, {K,K2}) of
  1101. [{{Key,_},_,Value}] ->
  1102. [{Key, Pid, Value}];
  1103. [] ->
  1104. []
  1105. end
  1106. end, Found)
  1107. end, Pids).
  1108. qlc_next(_, '$end_of_table') -> [];
  1109. qlc_next(Scope, K) ->
  1110. case ets:lookup(?TAB, K) of
  1111. [{{Key,_}, Pid, V}] ->
  1112. [{Key,Pid,V}] ++ fun() -> qlc_next(Scope, next(Scope, K)) end;
  1113. [] ->
  1114. qlc_next(Scope, next(Scope, K))
  1115. end.
  1116. qlc_prev(_, '$end_of_table') -> [];
  1117. qlc_prev(Scope, K) ->
  1118. case ets:lookup(?TAB, K) of
  1119. [{{Key,_},Pid,V}] ->
  1120. [{Key,Pid,V}] ++ fun() -> qlc_prev(Scope, prev(Scope, K)) end;
  1121. [] ->
  1122. qlc_prev(Scope, prev(Scope, K))
  1123. end.
  1124. qlc_select('$end_of_table') ->
  1125. [];
  1126. qlc_select({Objects, Cont}) ->
  1127. Objects ++ fun() -> qlc_select(ets:select(Cont)) end.
  1128. is_unique(names) -> true;
  1129. is_unique(aggr_counters) -> true;
  1130. is_unique({_, names}) -> true;
  1131. is_unique({_, aggr_counters}) -> true;
  1132. is_unique(n) -> true;
  1133. is_unique(a) -> true;
  1134. is_unique({_,n}) -> true;
  1135. is_unique({_,a}) -> true;
  1136. is_unique(_) -> false.
  1137. %% =============== EUNIT tests
  1138. reg_test_() ->
  1139. {setup,
  1140. fun() ->
  1141. application:start(gproc)
  1142. end,
  1143. fun(_) ->
  1144. application:stop(gproc)
  1145. end,
  1146. [
  1147. {spawn, ?_test(t_simple_reg())}
  1148. , ?_test(t_is_clean())
  1149. , {spawn, ?_test(t_simple_prop())}
  1150. , ?_test(t_is_clean())
  1151. , {spawn, ?_test(t_await())}
  1152. , ?_test(t_is_clean())
  1153. , {spawn, ?_test(t_simple_mreg())}
  1154. , ?_test(t_is_clean())
  1155. , {spawn, ?_test(t_gproc_crash())}
  1156. , ?_test(t_is_clean())
  1157. , {spawn, ?_test(t_cancel_wait_and_register())}
  1158. , ?_test(t_is_clean())
  1159. ]}.
  1160. t_simple_reg() ->
  1161. ?assert(gproc:reg({n,l,name}) =:= true),
  1162. ?assert(gproc:where({n,l,name}) =:= self()),
  1163. ?assert(gproc:unreg({n,l,name}) =:= true),
  1164. ?assert(gproc:where({n,l,name}) =:= undefined).
  1165. t_simple_prop() ->
  1166. ?assert(gproc:reg({p,l,prop}) =:= true),
  1167. ?assert(t_other_proc(fun() ->
  1168. ?assert(gproc:reg({p,l,prop}) =:= true)
  1169. end) =:= ok),
  1170. ?assert(gproc:unreg({p,l,prop}) =:= true).
  1171. t_other_proc(F) ->
  1172. {_Pid,Ref} = spawn_monitor(fun() -> exit(F()) end),
  1173. receive
  1174. {'DOWN',Ref,_,_,R} ->
  1175. R
  1176. after 10000 ->
  1177. erlang:error(timeout)
  1178. end.
  1179. t_await() ->
  1180. Me = self(),
  1181. {_Pid,Ref} = spawn_monitor(
  1182. fun() -> exit(?assert(gproc:await({n,l,t_await}) =:= {Me,val})) end),
  1183. ?assert(gproc:reg({n,l,t_await},val) =:= true),
  1184. receive
  1185. {'DOWN', Ref, _, _, R} ->
  1186. ?assertEqual(R, ok)
  1187. after 10000 ->
  1188. erlang:error(timeout)
  1189. end.
  1190. t_is_clean() ->
  1191. sys:get_status(gproc), % in order to synch
  1192. T = ets:tab2list(gproc),
  1193. ?assert(T =:= []).
  1194. t_simple_mreg() ->
  1195. ok.
  1196. t_gproc_crash() ->
  1197. P = spawn_helper(),
  1198. ?assert(gproc:where({n,l,P}) =:= P),
  1199. exit(whereis(gproc), kill),
  1200. give_gproc_some_time(100),
  1201. ?assert(whereis(gproc) =/= undefined),
  1202. %%
  1203. %% Check that the registration is still there using an ets:lookup(),
  1204. %% Once we've killed the process, gproc will always return undefined
  1205. %% if the process is not alive, regardless of whether the registration
  1206. %% is still there. So, here, the lookup should find something...
  1207. %%
  1208. ?assert(ets:lookup(gproc,{{n,l,P},n}) =/= []),
  1209. ?assert(gproc:where({n,l,P}) =:= P),
  1210. exit(P, kill),
  1211. %% ...and here, it shouldn't.
  1212. %% (sleep for a while first to let gproc handle the EXIT
  1213. give_gproc_some_time(10),
  1214. ?assert(ets:lookup(gproc,{{n,l,P},n}) =:= []).
  1215. t_cancel_wait_and_register() ->
  1216. Alias = {n, l, foo},
  1217. Me = self(),
  1218. P = spawn(fun() ->
  1219. {'EXIT',_} = (catch gproc:await(Alias, 100)),
  1220. ?assert(element(1,sys:get_status(gproc)) == status),
  1221. Me ! {self(), go_ahead},
  1222. timer:sleep(infinity)
  1223. end),
  1224. receive
  1225. {P, go_ahead} ->
  1226. ?assertEqual(gproc:reg(Alias, undefined), true),
  1227. exit(P, kill),
  1228. timer:sleep(500),
  1229. ?assert(element(1,sys:get_status(gproc)) == status)
  1230. end.
  1231. spawn_helper() ->
  1232. Parent = self(),
  1233. P = spawn(fun() ->
  1234. ?assert(gproc:reg({n,l,self()}) =:= true),
  1235. Ref = erlang:monitor(process, Parent),
  1236. Parent ! {ok,self()},
  1237. receive
  1238. {'DOWN', Ref, _, _, _} ->
  1239. ok
  1240. end
  1241. end),
  1242. receive
  1243. {ok,P} ->
  1244. P
  1245. end.
  1246. give_gproc_some_time(T) ->
  1247. timer:sleep(T),
  1248. sys:get_status(gproc).