gproc.erl 102 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186
  1. %% -*- erlang-indent-level: 4; indent-tabs-mode: nil -*-
  2. %% --------------------------------------------------
  3. %% This file is provided to you under the Apache License,
  4. %% Version 2.0 (the "License"); you may not use this file
  5. %% except in compliance with the License. You may obtain
  6. %% a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing,
  11. %% software distributed under the License is distributed on an
  12. %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  13. %% KIND, either express or implied. See the License for the
  14. %% specific language governing permissions and limitations
  15. %% under the License.
  16. %% --------------------------------------------------
  17. %%
  18. %% @author Ulf Wiger <ulf@wiger.net>
  19. %%
  20. %% @doc Extended process registry
  21. %% This module implements an extended process registry
  22. %%
  23. %% For a detailed description, see
  24. %% <a href="erlang07-wiger.pdf">erlang07-wiger.pdf</a>.
  25. %%
  26. %% <b>NOTE:</b> The functions in the Gproc API expect the Gproc application
  27. %% to be running.
  28. %%
  29. %% <h2>Tuning Gproc performance</h2>
  30. %%
  31. %% Gproc relies on a central server and an ordered-set ets table.
  32. %% Effort is made to perform as much work as possible in the client without
  33. %% sacrificing consistency. A few things can be tuned by setting the following
  34. %% application environment variables in the top application of `gproc'
  35. %% (usually `gproc'):
  36. %%
  37. %% * `{ets_options, list()}' - Currently, the options `{write_concurrency, F}'
  38. %% and `{read_concurrency, F}' are allowed. The default is
  39. %% `[{write_concurrency, true}, {read_concurrency, true}]'
  40. %% * `{server_options, list()}' - These will be passed as spawn options when
  41. %% starting the `gproc' and `gproc_dist' servers. Default is `[]'. It is
  42. %% likely that `{priority, high | max}' and/or increasing `min_heap_size'
  43. %% will improve performance.
  44. %%
  45. %% @end
  46. -module(gproc).
  47. -behaviour(gen_server).
  48. -export([start_link/0,
  49. reg/1, reg/2, reg/3, unreg/1, set_attributes/2,
  50. reg_other/2, reg_other/3, reg_other/4, unreg_other/2,
  51. reg_or_locate/1, reg_or_locate/2, reg_or_locate/3,
  52. reg_shared/1, reg_shared/2, reg_shared/3, unreg_shared/1,
  53. set_attributes_shared/2, set_value_shared/2,
  54. ensure_reg/1, ensure_reg/2, ensure_reg/3,
  55. ensure_reg_other/2, ensure_reg_other/3, ensure_reg_other/4,
  56. mreg/3,
  57. munreg/3,
  58. set_value/2,
  59. get_value/1, get_value/2, get_value_shared/1,
  60. get_attribute/2, get_attribute/3, get_attribute_shared/2,
  61. get_attributes/1, get_attributes/2,
  62. where/1,
  63. await/1, await/2, await/3,
  64. wide_await/3,
  65. nb_wait/1, nb_wait/2,
  66. cancel_wait/2, cancel_wait/3,
  67. cancel_wait_or_monitor/1,
  68. monitor/1, monitor/2,
  69. demonitor/2,
  70. lookup_pid/1,
  71. lookup_pids/1,
  72. lookup_value/1,
  73. lookup_values/1,
  74. update_counter/2, update_counter/3,
  75. update_counters/2,
  76. reset_counter/1,
  77. update_shared_counter/2,
  78. give_away/2,
  79. goodbye/0,
  80. send/2,
  81. bcast/2, bcast/3,
  82. info/1, info/2,
  83. i/0,
  84. select/1, select/2, select/3,
  85. select_count/1, select_count/2,
  86. first/1,
  87. next/2,
  88. prev/2,
  89. last/1,
  90. table/0, table/1, table/2]).
  91. %% Environment handling
  92. -export([get_env/3, get_env/4,
  93. get_set_env/3, get_set_env/4,
  94. set_env/5]).
  95. %% Convenience functions
  96. -export([add_local_name/1,
  97. add_global_name/1,
  98. add_local_property/2,
  99. add_global_property/2,
  100. add_local_counter/2,
  101. add_global_counter/2,
  102. add_local_aggr_counter/1,
  103. add_global_aggr_counter/1,
  104. add_shared_local_counter/2,
  105. lookup_local_name/1,
  106. lookup_global_name/1,
  107. lookup_local_properties/1,
  108. lookup_global_properties/1,
  109. lookup_local_counters/1,
  110. lookup_global_counters/1,
  111. lookup_local_resources/1,
  112. lookup_global_resources/1,
  113. lookup_local_aggr_counter/1,
  114. lookup_global_aggr_counter/1]).
  115. %% Callbacks for behaviour support
  116. -export([whereis_name/1,
  117. register_name/2,
  118. unregister_name/1]).
  119. -export([default/1]).
  120. %%% internal exports
  121. -export([init/1,
  122. handle_cast/2,
  123. handle_call/3,
  124. handle_info/2,
  125. code_change/3,
  126. terminate/2]).
  127. %% this shouldn't be necessary
  128. -export([audit_process/1]).
  129. -include("gproc_int.hrl").
  130. -include("gproc.hrl").
  131. -export_type([scope/0, type/0, key/0,
  132. context/0, sel_pattern/0, sel_scope/0, sel_context/0,
  133. reg_id/0, unique_id/0, monitor_type/0]).
  134. -type type() :: n | p | c | a | r | rc.
  135. -type scope() :: l | g.
  136. -type context() :: {scope(),type()} | type().
  137. -type sel_type() :: type()
  138. | names | props | counters | aggr_counters
  139. | resources | resource_counters.
  140. -type sel_var() :: '_' | atom().
  141. -type keypat() :: {sel_type() | sel_var(), l | g | sel_var(), any()}.
  142. -type pidpat() :: pid() | sel_var().
  143. -type headpat() :: {keypat(), pidpat(), any()}.
  144. -type key() :: {type(), scope(), any()}.
  145. -type value() :: any().
  146. -type attr() :: {atom(), any()}.
  147. -type attrs() :: [attr()].
  148. -type sel_pattern() :: [{headpat(), list(), list()}].
  149. -type reg_id() :: {type(), scope(), any()}.
  150. -type unique_id() :: {n | a, scope(), any()}.
  151. -type monitor_type() :: info | standby | follow.
  152. -type sel_scope() :: scope | all | global | local.
  153. -type sel_context() :: {scope(), type()} | type().
  154. %% update_counter increment
  155. -type ctr_incr() :: integer().
  156. -type ctr_thr() :: integer().
  157. -type ctr_setval() :: integer().
  158. -type ctr_update() :: ctr_incr()
  159. | {ctr_incr(), ctr_thr(), ctr_setval()}.
  160. -type increment() :: ctr_incr() | ctr_update() | [ctr_update()].
  161. -define(SERVER, ?MODULE).
  162. %%-define(l, l(?LINE)). % when activated, calls a traceable empty function
  163. -define(l, ignore).
  164. -define(CHK_DIST,
  165. case whereis(gproc_dist) of
  166. undefined ->
  167. ?THROW_GPROC_ERROR(local_only);
  168. _ ->
  169. ok
  170. end).
  171. -define(PID_IS_DEAD(Pid),
  172. (node(Pid) == node() andalso is_process_alive(Pid) == false)).
  173. -record(state, {}).
  174. %% @spec () -> {ok, pid()}
  175. %%
  176. %% @doc Starts the gproc server.
  177. %%
  178. %% This function is intended to be called from gproc_sup, as part of
  179. %% starting the gproc application.
  180. %% @end
  181. start_link() ->
  182. _ = create_tabs(),
  183. SpawnOpts = gproc_lib:valid_opts(server_options, []),
  184. gen_server:start_link({local, ?SERVER}, ?MODULE, [],
  185. [{spawn_opt, SpawnOpts}]).
  186. %% spec(Name::any()) -> true
  187. %%
  188. %% @doc Registers a local (unique) name. @equiv reg({n,l,Name})
  189. %% @end
  190. %%
  191. add_local_name(Name) ->
  192. ?CATCH_GPROC_ERROR(reg1({n,l,Name}, undefined, [], reg), [Name]).
  193. %% spec(Name::any()) -> true
  194. %%
  195. %% @doc Registers a global (unique) name. @equiv reg({n,g,Name})
  196. %% @end
  197. %%
  198. add_global_name(Name) ->
  199. ?CATCH_GPROC_ERROR(reg1({n,g,Name}, undefined, [], reg), [Name]).
  200. %% spec(Name::any(), Value::any()) -> true
  201. %%
  202. %% @doc Registers a local (non-unique) property. @equiv reg({p,l,Name},Value)
  203. %% @end
  204. %%
  205. add_local_property(Name , Value) ->
  206. ?CATCH_GPROC_ERROR(reg1({p,l,Name}, Value, [], reg), [Name, Value]).
  207. %% spec(Name::any(), Value::any()) -> true
  208. %%
  209. %% @doc Registers a global (non-unique) property. @equiv reg({p,g,Name},Value)
  210. %% @end
  211. %%
  212. add_global_property(Name, Value) ->
  213. ?CATCH_GPROC_ERROR(reg1({p,g,Name}, Value, [], reg), [Name, Value]).
  214. %% spec(Name::any(), Initial::integer()) -> true
  215. %%
  216. %% @doc Registers a local (non-unique) counter. @equiv reg({c,l,Name},Value)
  217. %% @end
  218. %%
  219. add_local_counter(Name, Initial) when is_integer(Initial) ->
  220. ?CATCH_GPROC_ERROR(reg1({c,l,Name}, Initial, [], reg), [Name, Initial]).
  221. %% spec(Name::any(), Initial::integer()) -> true
  222. %%
  223. %% @doc Registers a local shared (unique) counter.
  224. %% @equiv reg_shared({c,l,Name},Value)
  225. %% @end
  226. %%
  227. add_shared_local_counter(Name, Initial) when is_integer(Initial) ->
  228. reg_shared({c,l,Name}, Initial).
  229. %% spec(Name::any(), Initial::integer()) -> true
  230. %%
  231. %% @doc Registers a global (non-unique) counter. @equiv reg({c,g,Name},Value)
  232. %% @end
  233. %%
  234. add_global_counter(Name, Initial) when is_integer(Initial) ->
  235. ?CATCH_GPROC_ERROR(reg1({c,g,Name}, Initial, [], reg), [Name, Initial]).
  236. %% spec(Name::any()) -> true
  237. %%
  238. %% @doc Registers a local (unique) aggregated counter.
  239. %% @equiv reg({a,l,Name})
  240. %% @end
  241. %%
  242. add_local_aggr_counter(Name) -> ?CATCH_GPROC_ERROR(reg1({a,l,Name}), [Name]).
  243. %% spec(Name::any()) -> true
  244. %%
  245. %% @doc Registers a global (unique) aggregated counter.
  246. %% @equiv reg({a,g,Name})
  247. %% @end
  248. %%
  249. add_global_aggr_counter(Name) ->
  250. ?CATCH_GPROC_ERROR(reg1({a,g,Name}), [Name]).
  251. %% @spec (Name::any()) -> pid()
  252. %%
  253. %% @doc Lookup a local unique name. Fails if there is no such name.
  254. %% @equiv where({n,l,Name})
  255. %% @end
  256. %%
  257. lookup_local_name(Name) -> where({n,l,Name}).
  258. %% @spec (Name::any()) -> pid()
  259. %%
  260. %% @doc Lookup a global unique name. Fails if there is no such name.
  261. %% @equiv where({n,g,Name})
  262. %% @end
  263. %%
  264. lookup_global_name(Name) -> where({n,g,Name}).
  265. %% @spec (Name::any()) -> integer()
  266. %%
  267. %% @doc Lookup a local (unique) aggregated counter and returns its value.
  268. %% Fails if there is no such object.
  269. %% @equiv where({a,l,Name})
  270. %% @end
  271. %%
  272. lookup_local_aggr_counter(Name) -> lookup_value({a,l,Name}).
  273. %% @spec (Name::any()) -> integer()
  274. %%
  275. %% @doc Lookup a global (unique) aggregated counter and returns its value.
  276. %% Fails if there is no such object.
  277. %% @equiv lookup_value({a,g,Name})
  278. %% @end
  279. %%
  280. lookup_global_aggr_counter(Name) -> lookup_value({a,g,Name}).
  281. %% @spec (Property::any()) -> [{pid(), Value}]
  282. %%
  283. %% @doc Look up all local (non-unique) instances of a given Property.
  284. %% Returns a list of {Pid, Value} tuples for all matching objects.
  285. %% @equiv lookup_values({p, l, Property})
  286. %% @end
  287. %%
  288. lookup_local_properties(P) -> lookup_values({p,l,P}).
  289. %% @spec (Property::any()) -> [{pid(), Value}]
  290. %%
  291. %% @doc Look up all global (non-unique) instances of a given Property.
  292. %% Returns a list of {Pid, Value} tuples for all matching objects.
  293. %% @equiv lookup_values({p, g, Property})
  294. %% @end
  295. %%
  296. lookup_global_properties(P) -> lookup_values({p,g,P}).
  297. %% @spec (Counter::any()) -> [{pid(), Value::integer()}]
  298. %%
  299. %% @doc Look up all local (non-unique) instances of a given Counter.
  300. %% Returns a list of {Pid, Value} tuples for all matching objects.
  301. %% @equiv lookup_values({c, l, Counter})
  302. %% @end
  303. %%
  304. lookup_local_counters(P) -> lookup_values({c,l,P}).
  305. %% @spec (Counter::any()) -> [{pid(), Value::integer()}]
  306. %%
  307. %% @doc Look up all global (non-unique) instances of a given Counter.
  308. %% Returns a list of {Pid, Value} tuples for all matching objects.
  309. %% @equiv lookup_values({c, g, Counter})
  310. %% @end
  311. %%
  312. lookup_global_counters(P) -> lookup_values({c,g,P}).
  313. %% @spec (Resource::any()) -> [{pid(), Value::integer()}]
  314. %%
  315. %% @doc Look up all local (non-unique) instances of a given Resource.
  316. %% Returns a list of {Pid, Value} tuples for all matching objects.
  317. %% @equiv lookup_values({r, l, Resource})
  318. %% @end
  319. %%
  320. lookup_local_resources(P) -> lookup_values({r,l,P}).
  321. %% @spec (Resource::any()) -> [{pid(), Value::integer()}]
  322. %%
  323. %% @doc Look up all global (non-unique) instances of a given Resource.
  324. %% Returns a list of {Pid, Value} tuples for all matching objects.
  325. %% @equiv lookup_values({r, g, Resource})
  326. %% @end
  327. %%
  328. lookup_global_resources(P) -> lookup_values({r,g,P}).
  329. %% @spec get_env(Scope::scope(), App::atom(), Key::atom()) -> term()
  330. %% @equiv get_env(Scope, App, Key, [app_env])
  331. get_env(Scope, App, Key) ->
  332. get_env(Scope, App, Key, [app_env]).
  333. %% @spec (Scope::scope(), App::atom(), Key::atom(), Strategy) -> term()
  334. %% Strategy = [Alternative]
  335. %% Alternative = app_env
  336. %% | os_env
  337. %% | inherit | {inherit, pid()} | {inherit, unique_id()}
  338. %% | init_arg
  339. %% | {mnesia, ActivityType, Oid, Pos}
  340. %% | {default, term()}
  341. %% | error
  342. %% @doc Read an environment value, potentially cached as a `gproc_env' property.
  343. %%
  344. %% This function first tries to read the value of a cached property,
  345. %% `{p, Scope, {gproc_env, App, Key}}'. If this fails, it will try the provided
  346. %% alternative strategy. `Strategy' is a list of alternatives, tried in order.
  347. %% Each alternative can be one of:
  348. %%
  349. %% * `app_env' - try `application:get_env(App, Key)'
  350. %% * `os_env' - try `os:getenv(ENV)', where `ENV' is `Key' converted into an
  351. %% uppercase string
  352. %% * `{os_env, ENV}' - try `os:getenv(ENV)'
  353. %% * `inherit' - inherit the cached value, if any, held by the parent process.
  354. %% * `{inherit, Pid}' - inherit the cached value, if any, held by `Pid'.
  355. %% * `{inherit, Id}' - inherit the cached value, if any, held by the process
  356. %% registered in `gproc' as `Id'.
  357. %% * `init_arg' - try `init:get_argument(Key)'; expects a single value, if any.
  358. %% * `{mnesia, ActivityType, Oid, Pos}' - try
  359. %% `mnesia:activity(ActivityType, fun() -> mnesia:read(Oid) end)'; retrieve
  360. %% the value in position `Pos' if object found.
  361. %% * `{default, Value}' - set a default value to return once alternatives have
  362. %% been exhausted; if not set, `undefined' will be returned.
  363. %% * `error' - raise an exception, `erlang:error(gproc_env, [App, Key, Scope])'.
  364. %%
  365. %% While any alternative can occur more than once, the only one that might make
  366. %% sense to use multiple times is `{default, Value}'.
  367. %%
  368. %% The return value will be one of:
  369. %%
  370. %% * The value of the first matching alternative, or `error' eception,
  371. %% whichever comes first
  372. %% * The last instance of `{default, Value}', or `undefined', if there is no
  373. %% matching alternative, default or `error' entry in the list.
  374. %%
  375. %% The `error' option can be used to assert that a value has been previously
  376. %% cached. Alternatively, it can be used to assert that a value is either cached
  377. %% or at least defined somewhere,
  378. %% e.g. `get_env(l, mnesia, dir, [app_env, error])'.
  379. %% @end
  380. get_env(Scope, App, Key, Strategy)
  381. when Scope==l, is_atom(App), is_atom(Key);
  382. Scope==g, is_atom(App), is_atom(Key) ->
  383. do_get_env(Scope, App, Key, Strategy, false).
  384. %% @spec get_set_env(Scope::scope(), App::atom(), Key::atom()) -> term()
  385. %% @equiv get_set_env(Scope, App, Key, [app_env])
  386. get_set_env(Scope, App, Key) ->
  387. get_set_env(Scope, App, Key, [app_env]).
  388. %% @spec get_set_env(Scope::scope(), App::atom(), Key::atom(), Strategy) ->
  389. %% Value
  390. %% @doc Fetch and cache an environment value, if not already cached.
  391. %%
  392. %% This function does the same thing as {@link get_env/4}, but also updates the
  393. %% cache. Note that the cache will be updated even if the result of the lookup
  394. %% is `undefined'.
  395. %%
  396. %% @see get_env/4.
  397. %% @end
  398. %%
  399. get_set_env(Scope, App, Key, Strategy)
  400. when Scope==l, is_atom(App), is_atom(Key);
  401. Scope==g, is_atom(App), is_atom(Key) ->
  402. do_get_env(Scope, App, Key, Strategy, true).
  403. do_get_env(Context, App, Key, Alternatives, Set) ->
  404. case lookup_env(Context, App, Key, self()) of
  405. undefined ->
  406. check_alternatives(Alternatives, Context, App, Key, undefined, Set);
  407. {ok, Value} ->
  408. Value
  409. end.
  410. %% @spec set_env(Scope::scope(), App::atom(),
  411. %% Key::atom(), Value::term(), Strategy) -> Value
  412. %% Strategy = [Alternative]
  413. %% Alternative = app_env | os_env | {os_env, VAR}
  414. %% | {mnesia, ActivityType, Oid, Pos}
  415. %%
  416. %% @doc Updates the cached value as well as underlying environment.
  417. %%
  418. %% This function should be exercised with caution, as it affects the larger
  419. %% environment outside gproc. This function modifies the cached value, and then
  420. %% proceeds to update the underlying environment (OS environment variable or
  421. %% application environment variable).
  422. %%
  423. %% When the `mnesia' alternative is used, gproc will try to update any existing
  424. %% object, changing only the `Pos' position. If no such object exists, it will
  425. %% create a new object, setting any other attributes (except `Pos' and the key)
  426. %% to `undefined'.
  427. %% @end
  428. %%
  429. set_env(Scope, App, Key, Value, Strategy)
  430. when Scope==l, is_atom(App), is_atom(Key);
  431. Scope==g, is_atom(App), is_atom(Key) ->
  432. case is_valid_set_strategy(Strategy, Value) of
  433. true ->
  434. update_cached_env(Scope, App, Key, Value),
  435. set_strategy(Strategy, App, Key, Value);
  436. false ->
  437. erlang:error(badarg)
  438. end.
  439. check_alternatives([{default, Val}|Alts], Scope, App, Key, _, Set) ->
  440. check_alternatives(Alts, Scope, App, Key, Val, Set);
  441. check_alternatives([H|T], Scope, App, Key, Def, Set) ->
  442. case try_alternative(H, App, Key, Scope) of
  443. undefined ->
  444. check_alternatives(T, Scope, App, Key, Def, Set);
  445. {ok, Value} ->
  446. if Set ->
  447. cache_env(Scope, App, Key, Value),
  448. Value;
  449. true ->
  450. Value
  451. end
  452. end;
  453. check_alternatives([], Scope, App, Key, Def, Set) ->
  454. if Set ->
  455. cache_env(Scope, App, Key, Def);
  456. true ->
  457. ok
  458. end,
  459. Def.
  460. try_alternative(error, App, Key, Scope) ->
  461. erlang:error(gproc_env, [App, Key, Scope]);
  462. try_alternative(inherit, App, Key, Scope) ->
  463. case get('$ancestors') of
  464. [P|_] ->
  465. lookup_env(Scope, App, Key, P);
  466. _ ->
  467. undefined
  468. end;
  469. try_alternative({inherit, P}, App, Key, Scope) when is_pid(P) ->
  470. lookup_env(Scope, App, Key, P);
  471. try_alternative({inherit, P}, App, Key, Scope) ->
  472. case where(P) of
  473. undefined -> undefined;
  474. Pid when is_pid(Pid) ->
  475. lookup_env(Scope, App, Key, Pid)
  476. end;
  477. try_alternative(app_env, App, Key, _Scope) ->
  478. case application:get_env(App, Key) of
  479. undefined -> undefined;
  480. {ok, undefined} -> undefined;
  481. {ok, Value} -> {ok, Value}
  482. end;
  483. try_alternative(os_env, _App, Key, _) ->
  484. case os:getenv(os_env_key(Key)) of
  485. false -> undefined;
  486. Val -> {ok, Val}
  487. end;
  488. try_alternative({os_env, Key}, _, _, _) ->
  489. case os:getenv(Key) of
  490. false -> undefined;
  491. Val -> {ok, Val}
  492. end;
  493. try_alternative(init_arg, _, Key, _) ->
  494. case init:get_argument(Key) of
  495. {ok, [[Value]]} ->
  496. {ok, Value};
  497. error ->
  498. undefined
  499. end;
  500. try_alternative({mnesia,Type,Key,Pos}, _, _, _) ->
  501. case mnesia:activity(Type, fun() -> mnesia:read(Key) end) of
  502. [] -> undefined;
  503. [Found] ->
  504. {ok, element(Pos, Found)}
  505. end.
  506. os_env_key(Key) ->
  507. string:to_upper(atom_to_list(Key)).
  508. lookup_env(Scope, App, Key, P) ->
  509. case ets:lookup(?TAB, {{p, Scope, {gproc_env, App, Key}}, P}) of
  510. [] ->
  511. undefined;
  512. [{_, _, Value}] ->
  513. {ok, Value}
  514. end.
  515. cache_env(Scope, App, Key, Value) ->
  516. ?CATCH_GPROC_ERROR(
  517. reg1({p, Scope, {gproc_env, App, Key}}, Value, [], reg),
  518. [Scope,App,Key,Value]).
  519. update_cached_env(Scope, App, Key, Value) ->
  520. case lookup_env(Scope, App, Key, self()) of
  521. undefined ->
  522. cache_env(Scope, App, Key, Value);
  523. {ok, _} ->
  524. set_value({p, Scope, {gproc_env, App, Key}}, Value)
  525. end.
  526. is_valid_set_strategy([os_env|T], Value) ->
  527. is_string(Value) andalso is_valid_set_strategy(T, Value);
  528. is_valid_set_strategy([{os_env, _}|T], Value) ->
  529. is_string(Value) andalso is_valid_set_strategy(T, Value);
  530. is_valid_set_strategy([app_env|T], Value) ->
  531. is_valid_set_strategy(T, Value);
  532. is_valid_set_strategy([{mnesia,_Type,_Oid,_Pos}|T], Value) ->
  533. is_valid_set_strategy(T, Value);
  534. is_valid_set_strategy([], _) ->
  535. true;
  536. is_valid_set_strategy(_, _) ->
  537. false.
  538. set_strategy([H|T], App, Key, Value) ->
  539. case H of
  540. app_env ->
  541. application:set_env(App, Key, Value);
  542. os_env ->
  543. os:putenv(os_env_key(Key), Value);
  544. {os_env, ENV} ->
  545. os:putenv(ENV, Value);
  546. {mnesia,Type,Oid,Pos} ->
  547. mnesia:activity(
  548. Type,
  549. fun() ->
  550. Rec = case mnesia:read(Oid) of
  551. [] ->
  552. {Tab,K} = Oid,
  553. Tag = mnesia:table_info(Tab, record_name),
  554. Attrs = mnesia:table_info(Tab, attributes),
  555. list_to_tuple(
  556. [Tag,K |
  557. [undefined || _ <- tl(Attrs)]]);
  558. [Old] ->
  559. Old
  560. end,
  561. mnesia:write(setelement(Pos, Rec, Value))
  562. end)
  563. end,
  564. set_strategy(T, App, Key, Value);
  565. set_strategy([], _, _, Value) ->
  566. Value.
  567. is_string(S) ->
  568. try begin _ = iolist_to_binary(S),
  569. true
  570. end
  571. catch
  572. error:_ ->
  573. false
  574. end.
  575. %% @spec reg(Key::key()) -> true
  576. %%
  577. %% @doc
  578. %% @equiv reg(Key, default(Key), [])
  579. %% @end
  580. reg(Key) ->
  581. ?CATCH_GPROC_ERROR(reg1(valid_key(Key)), [Key]).
  582. reg1(Key) ->
  583. reg1(Key, default(Key), [], reg).
  584. %% @spec reg_or_locate(Key::key()) -> {pid(), NewValue}
  585. %%
  586. %% @doc
  587. %% @equiv reg_or_locate(Key, default(Key))
  588. %% @end
  589. reg_or_locate(Key) ->
  590. ?CATCH_GPROC_ERROR(reg_or_locate1(valid_key(Key)), [Key]).
  591. reg_or_locate1(Key) ->
  592. reg_or_locate1(Key, default(Key), self()).
  593. valid_key(Key) ->
  594. gproc_lib:valid_key(Key).
  595. default({T,_,_}) when T==c -> 0;
  596. default(_) -> undefined.
  597. %% @spec await(Key::key()) -> {pid(),Value}
  598. %% @equiv await(Key,infinity)
  599. %%
  600. await(Key) ->
  601. ?CATCH_GPROC_ERROR(await1(Key, infinity), [Key]).
  602. %% @spec await(Key::key(), Timeout) -> {pid(),Value}
  603. %% Timeout = integer() | infinity
  604. %%
  605. %% @doc Wait for a name or aggregated counter to be registered.
  606. %% The function raises an exception if the timeout expires. Timeout must be
  607. %% either an interger &gt; 0 or 'infinity'.
  608. %% A small optimization: we first perform a lookup, to see if the name
  609. %% is already registered. This way, the cost of the operation will be
  610. %% roughly the same as of where/1 in the case where the name is already
  611. %% registered (the difference: await/2 also returns the value).
  612. %% @end
  613. %%
  614. await(Key, Timeout) ->
  615. ?CATCH_GPROC_ERROR(await1(Key, Timeout), [Key, Timeout]).
  616. %% @spec await(Node::node(), Key::key(), Timeout) -> {pid(),Value}
  617. %% Timeout = integer() | infinity
  618. %%
  619. %% @doc Wait for a name or aggregated counter to be registered on `Node'.
  620. %% This function works exactly like {@link await/2}, but queries a remote
  621. %% node instead. An exception is thrown if `Node' cannot be reached. If gproc
  622. %% is not running on a given node, this is treated the same as the node being
  623. %% down.
  624. %% @end
  625. %%
  626. await(Node, Key, Timeout) when Node == node() ->
  627. await(Key, Timeout);
  628. await(Node, Key, Timeout) when is_atom(Node) ->
  629. ?CATCH_GPROC_ERROR(await1(Node, Key, Timeout), [Node, Key, Timeout]).
  630. await1({T,g,_} = Key, Timeout) when T=:=n; T=:=a; T=:=rc ->
  631. ?CHK_DIST,
  632. request_wait(Key, Timeout);
  633. await1({T,l,_} = Key, Timeout) when T=:=n; T=:=a; T=:=rc ->
  634. case ets:lookup(?TAB, {Key, T}) of
  635. [{_, Pid, Value}] ->
  636. case is_process_alive(Pid) of
  637. true ->
  638. {Pid, Value};
  639. false ->
  640. %% we can send an asynchronous audit request, since the purpose is
  641. %% only to ensure that the server handles the audit before it serves
  642. %% our 'await' request. Strictly speaking, we could allow the bad Pid
  643. %% to be returned, as there are no guarantees that whatever Pid we return
  644. %% will still be alive when addressed. Still, we don't want to knowingly
  645. %% serve bad data.
  646. nb_audit_process(Pid),
  647. request_wait(Key, Timeout)
  648. end;
  649. _ ->
  650. request_wait(Key, Timeout)
  651. end;
  652. await1(_, _) ->
  653. ?THROW_GPROC_ERROR(badarg).
  654. await1(N, {n,l,_} = Key, Timeout) when is_atom(N) ->
  655. request_wait(N, Key, Timeout);
  656. await1(_, _, _) ->
  657. ?THROW_GPROC_ERROR(badarg).
  658. request_wait({_,g,_} = Key, Timeout) ->
  659. request_wait(undefined, Key, Timeout);
  660. request_wait(Key, Timeout) ->
  661. request_wait(node(), Key, Timeout).
  662. request_wait(N, {_,C,_} = Key, Timeout) when C==l; C==g ->
  663. TRef = case Timeout of
  664. infinity -> no_timer;
  665. T when is_integer(T), T > 0 ->
  666. erlang:start_timer(T, self(), gproc_timeout);
  667. _ ->
  668. ?THROW_GPROC_ERROR(badarg)
  669. end,
  670. WRef = case {call(N, {await,Key,self()}, C), C} of
  671. {{R, {Kg,Pg,Vg}}, g} ->
  672. self() ! {gproc, R, registered, {Kg,Pg,Vg}},
  673. R;
  674. {R,_} ->
  675. R
  676. end,
  677. receive
  678. {gproc, WRef, registered, {_K, Pid, V}} ->
  679. _ = case TRef of
  680. no_timer -> ignore;
  681. _ -> erlang:cancel_timer(TRef)
  682. end,
  683. {Pid, V};
  684. {timeout, TRef, gproc_timeout} ->
  685. cancel_wait(N, Key, WRef),
  686. ?THROW_GPROC_ERROR(timeout)
  687. end.
  688. %% @spec wide_await(Nodes::[node()], Key::key(), Timeout) -> {pid(),Value}
  689. %% Timeout = integer() | infinity
  690. %%
  691. %% @doc Wait for a local name to be registered on any of `Nodes'.
  692. %% This function works rather like {@link await/2}, but queries all nodes in
  693. %% the `Nodes' list at the same time. The first node to respond with a
  694. %% process registered as `Key' will provide the result. Other results are
  695. %% ignored. `Key' must be a unique name with local scope, i.e. `{n,l,Name}'.
  696. %%
  697. %% An exception is thrown upon timeout, or if no node can be reached (if gproc is
  698. %% not running on a given node, this is treated the same as the node being down).
  699. %% @end
  700. %%
  701. wide_await(Nodes, Key, Timeout) ->
  702. ?CATCH_GPROC_ERROR(wide_await1(Nodes, Key, Timeout), [Nodes, Key, Timeout]).
  703. wide_await1(Nodes, {T,l,_} = Key, Timeout) when T=:=n; T=:=a ->
  704. {_, Ref} = spawn_monitor(fun() ->
  705. wide_request_wait(Nodes, Key, Timeout)
  706. end),
  707. receive
  708. {'DOWN', Ref, _, _, Reason} ->
  709. case Reason of
  710. {ok, {gproc,_,registered,{_,Pid,V}}} ->
  711. {Pid, V};
  712. Other ->
  713. ?THROW_GPROC_ERROR(Other)
  714. end
  715. end;
  716. wide_await1(_, _, _) ->
  717. ?THROW_GPROC_ERROR(badarg).
  718. wide_request_wait(Nodes, {Tk,l,_} = Key, Timeout) when Tk=:=n; Tk=:=a ->
  719. TRef = case Timeout of
  720. infinity -> no_timer;
  721. T when is_integer(T), T > 0 ->
  722. erlang:start_timer(T, self(), gproc_timeout);
  723. _ ->
  724. exit(badarg)
  725. end,
  726. Req = {await, Key, self()},
  727. Refs = lists:map(
  728. fun(Node) ->
  729. S = {?MODULE, Node},
  730. Ref = erlang:monitor(process, S),
  731. ?MAY_FAIL(erlang:send(S, {'$gen_call', {self(), Ref}, Req},
  732. [noconnect])),
  733. {Node, Ref}
  734. end, Nodes),
  735. collect_replies(Refs, Key, TRef).
  736. collect_replies(Refs, Key, TRef) ->
  737. receive
  738. {gproc, _Ref, registered, {_, _, _}} = Result ->
  739. exit({ok, Result});
  740. {'DOWN', Ref, _, _, _} ->
  741. case lists:keydelete(Ref, 2, Refs) of
  742. [] ->
  743. exit(nodedown);
  744. Refs1 ->
  745. collect_replies(Refs1, Key, TRef)
  746. end;
  747. {timeout, TRef, gproc_timeout} ->
  748. exit(timeout);
  749. {Ref, Ref} ->
  750. %% ignore
  751. collect_replies(Refs, Key, TRef)
  752. end.
  753. %% @spec nb_wait(Key::key()) -> Ref
  754. %%
  755. %% @doc Wait for a name or aggregated counter to be registered.
  756. %% The caller can expect to receive a message,
  757. %% {gproc, Ref, registered, {Key, Pid, Value}}, once the name is registered.
  758. %% @end
  759. %%
  760. nb_wait(Key) ->
  761. ?CATCH_GPROC_ERROR(nb_wait1(Key), [Key]).
  762. %% @spec nb_wait(Node::node(), Key::key()) -> Ref
  763. %%
  764. %% @doc Wait for a name or aggregated counter to be registered on `Node'.
  765. %% The caller can expect to receive a message,
  766. %% {gproc, Ref, registered, {Key, Pid, Value}}, once the name is registered.
  767. %% @end
  768. %%
  769. nb_wait(Node, Key) ->
  770. ?CATCH_GPROC_ERROR(nb_wait1(Node, Key), [Node, Key]).
  771. nb_wait1({T,g,_} = Key) when T=:=n; T=:=a; T=:=rc ->
  772. ?CHK_DIST,
  773. call({await, Key, self()}, g);
  774. nb_wait1({T,l,_} = Key) when T=:=n; T=:=a; T=:=rc ->
  775. call({await, Key, self()}, l);
  776. nb_wait1(_) ->
  777. ?THROW_GPROC_ERROR(badarg).
  778. nb_wait1(Node, {T,l,_} = Key) when is_atom(Node), T=:=n;
  779. is_atom(Node), T=:=a;
  780. is_atom(Node), T=:=rc ->
  781. call(Node, {await, Key, self()}, l).
  782. %% @spec cancel_wait(Key::key(), Ref) -> ok
  783. %% Ref = all | reference()
  784. %%
  785. %% @doc Cancels a previous call to nb_wait/1
  786. %%
  787. %% If `Ref = all', all wait requests on `Key' from the calling process
  788. %% are canceled.
  789. %% @end
  790. %%
  791. cancel_wait(Key, Ref) ->
  792. ?CATCH_GPROC_ERROR(cancel_wait1(Key, Ref), [Key, Ref]).
  793. %% @spec cancel_wait(Node::node(), Key::key(), Ref) -> ok
  794. %% Ref = all | reference()
  795. %%
  796. %% @doc Cancels a previous call to nb_wait/2
  797. %%
  798. %% This function works just like {@link cancel_wait/2}, but talks to a remote
  799. %% node.
  800. %% @end
  801. %%
  802. cancel_wait(N, Key, Ref) when N == node() ->
  803. cancel_wait(Key, Ref);
  804. cancel_wait(N, Key, Ref) ->
  805. ?CATCH_GPROC_ERROR(cancel_wait1(N, Key, Ref), [N, Key, Ref]).
  806. cancel_wait1({_,g,_} = Key, Ref) ->
  807. ?CHK_DIST,
  808. cast({cancel_wait, self(), Key, Ref}, g),
  809. ok;
  810. cancel_wait1({_,l,_} = Key, Ref) ->
  811. cast({cancel_wait, self(), Key, Ref}, l),
  812. ok.
  813. cancel_wait1(undefined, {_,g,_} = Key, Ref) ->
  814. cast({cancel_wait, self(), Key, Ref}, g);
  815. cancel_wait1(N, {_,l,_} = Key, Ref) ->
  816. cast(N, {cancel_wait, self(), Key, Ref}, l).
  817. cancel_wait_or_monitor(Key) ->
  818. ?CATCH_GPROC_ERROR(cancel_wait_or_monitor1(Key), [Key]).
  819. cancel_wait_or_monitor1({_,g,_} = Key) ->
  820. ?CHK_DIST,
  821. cast({cancel_wait_or_monitor, self(), Key}, g),
  822. ok;
  823. cancel_wait_or_monitor1({_,l,_} = Key) ->
  824. cast({cancel_wait_or_monitor, self(), Key}, l),
  825. ok.
  826. %% @equiv monitor(Key, info)
  827. monitor(Key) ->
  828. ?CATCH_GPROC_ERROR(monitor1(Key, info), [Key]).
  829. %% @spec monitor(key(), monitor_type()) -> reference()
  830. %%
  831. %% @doc monitor a registered name
  832. %% `monitor(Key, info)' works much like erlang:monitor(process, Pid), but monitors
  833. %% a unique name registered via gproc. A message, `{gproc, unreg, Ref, Key}'
  834. %% will be sent to the requesting process, if the name is unregistered or
  835. %% the registered process dies. If there is a standby monitor (see below), a
  836. %% message `{gproc, {failover, ToPid}, Ref, Key}' is sent to all monitors.
  837. %% If the name is passed to another process using {@link give_away/2}, the event
  838. %% `{gproc, {migrated, ToPid}, Ref, Key}' is sent to all monitors.
  839. %%
  840. %% `monitor(Key, standby)' sets up the monitoring process as a standby for the
  841. %% registered name. If the registered process dies, the first standby process
  842. %% inherits the name, and a message `{gproc, {failover, ToPid}, Ref, Key}' is
  843. %% sent to all monitors, including the one that inherited the name.
  844. %%
  845. %% If the name is not yet registered, the unreg event is sent immediately.
  846. %% If the calling process in this case tried to start a `standby' monitoring,
  847. %% it receives the registered name and the failover event immediately.
  848. %%
  849. %% `monitor(Key, follow)' keeps monitoring the registered name even if it is
  850. %% temporarily unregistered. The messages received are the same as for the other
  851. %% monitor types, but `{gproc, registered, Ref, Key}' is also sent when a new
  852. %% process registers the name.
  853. %% @end
  854. monitor(Key, Type) when Type==info;
  855. Type==follow;
  856. Type==standby ->
  857. ?CATCH_GPROC_ERROR(monitor1(Key, Type), [Key, Type]).
  858. monitor1({T,g,_} = Key, Type) when T==n; T==a; T==rc ->
  859. ?CHK_DIST,
  860. gproc_dist:monitor(Key, Type);
  861. monitor1({T,l,_} = Key, Type) when T==n; T==a; T==rc ->
  862. call({monitor, Key, self(), Type}, l);
  863. monitor1(_, _) ->
  864. ?THROW_GPROC_ERROR(badarg).
  865. %% @spec demonitor(key(), reference()) -> ok
  866. %%
  867. %% @doc Remove a monitor on a registered name
  868. %% This function is the reverse of monitor/1. It removes a monitor previously
  869. %% set on a unique name. This function always succeeds given legal input.
  870. %% @end
  871. demonitor(Key, Ref) ->
  872. ?CATCH_GPROC_ERROR(demonitor1(Key, Ref), [Key, Ref]).
  873. demonitor1({T,g,_} = Key, Ref) when T==n; T==a; T==rc ->
  874. ?CHK_DIST,
  875. gproc_dist:demonitor(Key, Ref);
  876. demonitor1({T,l,_} = Key, Ref) when T==n; T==a; T==rc ->
  877. call({demonitor, Key, Ref, self()}, l);
  878. demonitor1(_, _) ->
  879. ?THROW_GPROC_ERROR(badarg).
  880. %% @spec reg(Key::key(), Value::value()) -> true
  881. %%
  882. %% @doc Register a name or property for the current process
  883. %%
  884. %%
  885. reg(Key, Value) ->
  886. ?CATCH_GPROC_ERROR(reg1(valid_key(Key), Value, [], reg), [Key, Value]).
  887. %% @spec reg(Key::key(), Value::value(), Attrs::attrs()) -> true
  888. %%
  889. %% @doc Register a name or property for the current process
  890. %% `Attrs' (default: `[]') can be inspected using {@link get_attribute/2}.
  891. %%
  892. %% The structure of `Key' is `{Type, Context, Name}', where:
  893. %%
  894. %% * `Context :: l | g' - `l' means 'local' context; `g' means 'global'
  895. %% * `Type :: p | n | c | a | r | rc' specifies the type of entry
  896. %%
  897. %% The semantics of the different types:
  898. %%
  899. %% * `p' - 'property', is non-unique, i.e. different processes can each
  900. %% register a property with the same name.
  901. %% * `n' - 'name, is unique within the given context (local or global).
  902. %% * `c' - 'counter', is similar to a property, but has a numeric value
  903. %% and behaves roughly as an ets counter (see {@link update_counter/2}.)
  904. %% * `a' - 'aggregated counter', is automatically updated by gproc, and
  905. %% reflects the sum of all counter objects with the same name in the given
  906. %% scope. The initial value for an aggregated counter must be `undefined'.
  907. %% * `r' - 'resource property', behaves like a property, but can be tracked
  908. %% with a 'resource counter'. Note that using an `rc' wildcard name
  909. %% pattern (see below) for a resource property is not allowed.
  910. %% * `rc' - 'resource counter', tracks the number of resource properties
  911. %% with the same name. When the resource count reaches `0', any triggers
  912. %% specified using an `on_zero' attribute may be executed (see below).
  913. %% If `Name' is a tuple, the last element of the name can contain a
  914. %% wildcard, using the symbol <code>'\\_'</code>. This will make the resource
  915. %% counter keep track of any resources where all elements match except
  916. %% the last position. For example, <code>{rc,l,{a,b,'\\_'}}</code> would keep
  917. %% track of both `{r,l,{a,b,1}}' and `{r,l,{a,b,2}}'.
  918. %%
  919. %% On-zero triggers:
  920. %%
  921. %% `Msg = {gproc, resource_on_zero, Context, Name, Pid}'
  922. %%
  923. %% * `{send, Key}' - run `gproc:send(Key, Msg)'
  924. %% * `{bcast, Key}' - run `gproc:bcast(Key, Msg)'
  925. %% * `publish' - run
  926. %% `gproc_ps:publish(Context, gproc_resource_on_zero, {Context, Name, Pid})'
  927. %% * `{unreg_shared, Type, Name}' - unregister the shared key
  928. %% `{Type, Context, Name}'
  929. %% @end
  930. reg(Key, Value, Attrs) ->
  931. ?CATCH_GPROC_ERROR(reg1(valid_key(Key), Value, Attrs, reg), [Key, Value, Attrs]).
  932. %% @equiv ensure_reg(Key, default(Key), [])
  933. ensure_reg(Key) ->
  934. ?CATCH_GPROC_ERROR(reg1(valid_key(Key), ensure), [Key]).
  935. %% @equiv ensure_reg(Key, Value, [])
  936. -spec ensure_reg(key(), value()) -> new | updated.
  937. ensure_reg(Key, Value) ->
  938. ?CATCH_GPROC_ERROR(reg1(valid_key(Key), Value, ensure), [Key, Value]).
  939. %% @spec ensure_reg(Key::key(), Value::value(), Attrs::attrs()) ->
  940. %% new | updated
  941. %%
  942. %% @doc Registers a new name or property unless such and entry (by key) has
  943. %% already been registered by the current process. If `Key' already exists,
  944. %% the entry will be updated with the given `Value' and `Attrs'.
  945. %%
  946. %% This function allows the caller to efficiently register an entry without
  947. %% first checking whether it has already been registered. An exception is
  948. %% raised if the name or property is already registered by someone else.
  949. %% @end
  950. -spec ensure_reg(key(), value(), attrs()) -> new | updated.
  951. ensure_reg(Key, Value, Attrs) ->
  952. ?CATCH_GPROC_ERROR(reg1(valid_key(Key), Value, Attrs, ensure), [Key, Value, Attrs]).
  953. reg1(Key, Op) ->
  954. reg1(Key, default(Key), [], Op).
  955. reg1(Key, Value, Op) ->
  956. reg1(Key, Value, [], Op).
  957. reg1({T,g,_} = Key, Value, As, Op) when T==p; T==a; T==c; T==n; T==r; T==rc ->
  958. %% anything global
  959. ?CHK_DIST,
  960. gproc_dist:reg(Key, Value, As, Op);
  961. reg1({p,l,_} = Key, Value, As, Op) ->
  962. local_reg(Key, Value, As, Op);
  963. reg1({a,l,_} = Key, undefined, As, Op) ->
  964. call({reg, Key, undefined, As, Op});
  965. reg1({c,l,_} = Key, Value, As, Op) when is_integer(Value) ->
  966. call({reg, Key, Value, As, Op});
  967. reg1({n,l,_} = Key, Value, As, Op) ->
  968. call({reg, Key, Value, As, Op});
  969. reg1({r,l,_} = Key, Value, As, Op) ->
  970. call({reg, Key, Value, As, Op});
  971. reg1({rc,l,_} = Key, Value, As, Op) ->
  972. call({reg, Key, Value, As, Op});
  973. reg1(_, _, _, _) ->
  974. ?THROW_GPROC_ERROR(badarg).
  975. %% @equiv reg_other(Key, Pid, default(Key), [])
  976. reg_other(Key, Pid) ->
  977. ?CATCH_GPROC_ERROR(reg_other1(valid_key(Key), Pid, reg), [Key, Pid]).
  978. %% @equiv reg_other(Key, Pid, Value, [])
  979. reg_other(Key, Pid, Value) ->
  980. ?CATCH_GPROC_ERROR(reg_other1(valid_key(Key), Pid, Value, [], reg), [Key, Pid, Value]).
  981. %% @spec reg_other(Key, Pid, Value, Attrs) -> true
  982. %% @doc Register name or property to another process.
  983. %%
  984. %% Equivalent to {@link reg/3}, but allows for registration of another process
  985. %% instead of the current process.
  986. %%
  987. %% Note that registering other processes introduces the possibility of
  988. %% confusing race conditions in user code. Letting each process register
  989. %% its own resources is highly recommended.
  990. %%
  991. %% Only the following resource types can be registered through this function:
  992. %%
  993. %% * `n' - unique names
  994. %% * `a' - aggregated counters
  995. %% * `r' - resource properties
  996. %% * `rc' - resource counters
  997. %% @end
  998. reg_other(Key, Pid, Value, Attrs) ->
  999. ?CATCH_GPROC_ERROR(reg_other1(valid_key(Key), Pid, Value, Attrs, reg),
  1000. [Key, Pid, Value, Attrs]).
  1001. ensure_reg_other(Key, Pid) ->
  1002. ?CATCH_GPROC_ERROR(reg_other1(valid_key(Key), Pid, ensure), [Key, Pid]).
  1003. %% @equiv ensure_reg_other(Key, Pid, Value, [])
  1004. ensure_reg_other(Key, Pid, Value) ->
  1005. ?CATCH_GPROC_ERROR(reg_other1(valid_key(Key), Pid, Value, [], ensure),
  1006. [Key, Pid, Value]).
  1007. %% @spec ensure_reg_other(Key::key(), Pid::pid(),
  1008. %% Value::value(), Attrs::attrs()) ->
  1009. %% new | updated
  1010. %%
  1011. %% @doc Register or update name or property to another process.
  1012. %%
  1013. %% Equivalent to {@link reg_other/3}, but allows for registration of another
  1014. %% process instead of the current process. Also see {@link ensure_reg/3}.
  1015. %% @end
  1016. ensure_reg_other(Key, Pid, Value, Attrs) ->
  1017. ?CATCH_GPROC_ERROR(reg_other1(valid_key(Key), Pid, Value, Attrs, ensure),
  1018. [Key, Pid, Value, Attrs]).
  1019. reg_other1(Key, Pid, Op) ->
  1020. reg_other1(Key, Pid, default(Key), [], Op).
  1021. reg_other1({_,g,_} = Key, Pid, Value, As, Op) when is_pid(Pid) ->
  1022. ?CHK_DIST,
  1023. gproc_dist:reg_other(Key, Pid, Value, As, Op);
  1024. reg_other1({T,l,_} = Key, Pid, Value, As, Op) when is_pid(Pid) ->
  1025. if T==n; T==a; T==r; T==rc ->
  1026. call({reg_other, Key, Pid, Value, As, Op});
  1027. true ->
  1028. ?THROW_GPROC_ERROR(badarg)
  1029. end.
  1030. %% @spec reg_or_locate(Key::key(), Value) -> {pid(), NewValue}
  1031. %%
  1032. %% @doc Try registering a unique name, or return existing registration.
  1033. %%
  1034. %% This function tries to register the name `Key', if available.
  1035. %% If such a registration object already exists, the pid and value of
  1036. %% the current registration is returned instead.
  1037. %% @end
  1038. reg_or_locate(Key, Value) ->
  1039. ?CATCH_GPROC_ERROR(reg_or_locate1(valid_key(Key), Value, self()), [Key, Value]).
  1040. %% @spec reg_or_locate(Key::key(), Value, Fun::fun()) -> {pid(), NewValue}
  1041. %%
  1042. %% @doc Spawn a process with a registered name, or return existing registration.
  1043. %%
  1044. %% This function checks whether a local name is registered; if not, it spawns
  1045. %% a new process (with `spawn(Fun)') and gives it the name.
  1046. %% The pid and value of the resulting registration is returned.
  1047. %%
  1048. %% When a global name is registered in this fashion, the process is
  1049. %% spawned on the caller's node, and the group_leader of the spawned
  1050. %% process is set to the group_leader of the calling process.
  1051. %% @end
  1052. reg_or_locate({n,_,_} = Key, Value, F) when is_function(F, 0) ->
  1053. ?CATCH_GPROC_ERROR(reg_or_locate1(valid_key(Key), Value, F), [Key, Value, F]).
  1054. reg_or_locate1({_,g,_} = Key, Value, P) ->
  1055. ?CHK_DIST,
  1056. gproc_dist:reg_or_locate(Key, Value, P);
  1057. reg_or_locate1({T,l,_} = Key, Value, P) when T==n; T==a; T==rc ->
  1058. call({reg_or_locate, Key, Value, P});
  1059. reg_or_locate1(_, _, _) ->
  1060. ?THROW_GPROC_ERROR(badarg).
  1061. %% @spec reg_shared(Key::key()) -> true
  1062. %%
  1063. %% @doc Register a resource, but don't tie it to a particular process.
  1064. %%
  1065. %% `reg_shared({c,l,C}) -> reg_shared({c,l,C}, 0).'
  1066. %% `reg_shared({a,l,A}) -> reg_shared({a,l,A}, undefined).'
  1067. %% @end
  1068. reg_shared(Key) ->
  1069. ?CATCH_GPROC_ERROR(reg_shared1(valid_key(Key)), [Key]).
  1070. %% @private
  1071. reg_shared1({T,_,_} = Key) when T==a; T==p; T==c; T==r ->
  1072. reg_shared(Key, default(Key)).
  1073. %% @spec reg_shared(Key::key(), Value) -> true
  1074. %%
  1075. %% @doc Register a resource, but don't tie it to a particular process.
  1076. %%
  1077. %% Shared resources are all unique. They remain until explicitly unregistered
  1078. %% (using {@link unreg_shared/1}). The types of shared resources currently
  1079. %% supported are `counter' and `aggregated counter'. In listings and query
  1080. %% results, shared resources appear as other similar resources, except that
  1081. %% `Pid == shared'. To wit, update_counter({c,l,myCounter}, shared, 1) would
  1082. %% increment the shared counter `myCounter' with 1, provided it exists.
  1083. %%
  1084. %% A shared aggregated counter will track updates in exactly the same way as
  1085. %% an aggregated counter which is owned by a process.
  1086. %% @end
  1087. %%
  1088. reg_shared(Key, Value) ->
  1089. ?CATCH_GPROC_ERROR(reg_shared1(valid_key(Key), Value, []), [Key, Value]).
  1090. reg_shared(Key, Value, Attrs) when is_list(Attrs) ->
  1091. ?CATCH_GPROC_ERROR(reg_shared1(valid_key(Key), Value, Attrs), [Key, Value, Attrs]).
  1092. %% @private
  1093. reg_shared1({_,g,_} = Key, Value, As) ->
  1094. %% anything global
  1095. ?CHK_DIST,
  1096. gproc_dist:reg_shared(Key, Value, As);
  1097. reg_shared1({a,l,_} = Key, undefined, As) ->
  1098. call({reg_shared, Key, undefined, As, reg});
  1099. reg_shared1({c,l,_} = Key, Value, As) when is_integer(Value) ->
  1100. call({reg_shared, Key, Value, As, reg});
  1101. reg_shared1({p,l,_} = Key, Value, As) ->
  1102. call({reg_shared, Key, Value, As, reg});
  1103. reg_shared1({rc,l,_} = Key, undefined, As) ->
  1104. call({reg_shared, Key, undefined, As, reg});
  1105. reg_shared1(_, _, _) ->
  1106. ?THROW_GPROC_ERROR(badarg).
  1107. %% @spec mreg(type(), scope(), [{Key::any(), Value::any()}]) -> true
  1108. %%
  1109. %% @doc Register multiple {Key,Value} pairs of a given type and scope.
  1110. %%
  1111. %% This function is more efficient than calling {@link reg/2} repeatedly.
  1112. %% It is also atomic in regard to unique names; either all names are registered
  1113. %% or none are.
  1114. %% @end
  1115. mreg(T, C, KVL) ->
  1116. ?CATCH_GPROC_ERROR(mreg1(T, C, KVL), [T, C, KVL]).
  1117. mreg1(T, g, KVL) ->
  1118. ?CHK_DIST,
  1119. gproc_dist:mreg(T, KVL);
  1120. mreg1(T, l, KVL) when T==p; T==n; T==a; T==r ->
  1121. if is_list(KVL) ->
  1122. call({mreg, T, l, KVL});
  1123. true ->
  1124. erlang:error(badarg)
  1125. end;
  1126. mreg1(p, l, KVL) ->
  1127. local_mreg(p, KVL);
  1128. mreg1(_, _, _) ->
  1129. ?THROW_GPROC_ERROR(badarg).
  1130. %% @spec munreg(type(), scope(), [Key::any()]) -> true
  1131. %%
  1132. %% @doc Unregister multiple Key items of a given type and scope.
  1133. %%
  1134. %% This function is usually more efficient than calling {@link unreg/1}
  1135. %% repeatedly.
  1136. %% @end
  1137. munreg(T, C, L) ->
  1138. ?CATCH_GPROC_ERROR(munreg1(T, C, L), [T, C, L]).
  1139. munreg1(T, g, L) ->
  1140. ?CHK_DIST,
  1141. gproc_dist:munreg(T, existing(T,g,L));
  1142. munreg1(T, l, L) when T==p; T==a; T==n; T==rc; T==r ->
  1143. if is_list(L) ->
  1144. call({munreg, T, l, existing(T,l,L)});
  1145. true ->
  1146. erlang:error(badarg)
  1147. end;
  1148. munreg1(p, l, L) ->
  1149. local_munreg(p, existing(p,l,L));
  1150. munreg1(_, _, _) ->
  1151. ?THROW_GPROC_ERROR(badarg).
  1152. existing(T,Scope,L) ->
  1153. Keys = if T==p; T==c; T==r ->
  1154. [{{T,Scope,K}, self()} || K <- L];
  1155. T==a; T==n; T==rc ->
  1156. [{{T,Scope,K}, T} || K <- L]
  1157. end,
  1158. _ = [case ets:member(?TAB, K) of
  1159. false -> erlang:error(badarg);
  1160. true -> true
  1161. end || K <- Keys],
  1162. L.
  1163. %% @spec (Key:: key()) -> true
  1164. %%
  1165. %% @doc Unregister a name or property.
  1166. %% @end
  1167. unreg(Key) ->
  1168. ?CATCH_GPROC_ERROR(unreg1(Key), [Key]).
  1169. unreg1(Key) ->
  1170. case Key of
  1171. {_, g, _} ->
  1172. ?CHK_DIST,
  1173. gproc_dist:unreg(Key);
  1174. {T, l, _} when T == n; T == a; T == r; T == rc ->
  1175. call({unreg, Key});
  1176. {_, l, _} ->
  1177. case ets:member(?TAB, {Key,self()}) of
  1178. true ->
  1179. _ = gproc_lib:remove_reg(Key, self(), unreg),
  1180. true;
  1181. false ->
  1182. ?THROW_GPROC_ERROR(badarg)
  1183. end
  1184. end.
  1185. %% @spec unreg_other(key(), pid()) -> true
  1186. %% @doc Unregister a name registered to another process.
  1187. %%
  1188. %% This function is equivalent to {@link unreg/1}, but specifies another
  1189. %% process as the holder of the registration. An exception is raised if the
  1190. %% name or property is not registered to the given process.
  1191. %% @end
  1192. unreg_other(Key, Pid) ->
  1193. ?CATCH_GPROC_ERROR(unreg_other1(Key, Pid), [Key, Pid]).
  1194. unreg_other1({_,g,_} = Key, Pid) ->
  1195. ?CHK_DIST,
  1196. gproc_dist:unreg_other(Key, Pid);
  1197. unreg_other1({T,l,_} = Key, Pid) when is_pid(Pid) ->
  1198. if T==n; T==a; T==r; T==rc ->
  1199. call({unreg_other, Key, Pid});
  1200. true ->
  1201. ?THROW_GPROC_ERROR(badarg)
  1202. end.
  1203. %% @spec (Key::key(), Props::[{atom(), any()}]) -> true
  1204. %%
  1205. %% @doc Add/modify `{Key, Value}' attributes associated with a registration.
  1206. %%
  1207. %% Gproc registration objects can have `{Key, Value}' attributes associated with
  1208. %% them. These are stored in a way that doesn't affect the cost of name lookup.
  1209. %%
  1210. %% Attributs can be retrieved using `gproc:get_attribute/3' or
  1211. %% `gproc:get_attributes/2'.
  1212. %% @end
  1213. set_attributes(Key, Props) ->
  1214. ?CATCH_GPROC_ERROR(set_attributes1(Key, Props), [Key, Props]).
  1215. set_attributes1(Key, Props) ->
  1216. case Key of
  1217. {_, g, _} ->
  1218. ?CHK_DIST,
  1219. gproc_dist:set_attributes(Key, Props);
  1220. {_, l, _} ->
  1221. call({set_attributes, Key, Props})
  1222. end.
  1223. %% @spec (Key:: key()) -> true
  1224. %%
  1225. %% @doc Unregister a shared resource.
  1226. %% @end
  1227. unreg_shared(Key) ->
  1228. ?CATCH_GPROC_ERROR(unreg_shared1(Key), [Key]).
  1229. %% @private
  1230. unreg_shared1(Key) ->
  1231. case Key of
  1232. {_, g, _} ->
  1233. ?CHK_DIST,
  1234. gproc_dist:unreg_shared(Key);
  1235. {T, l, _} when T == c;
  1236. T == a;
  1237. T == p;
  1238. T == rc -> call({unreg_shared, Key});
  1239. _ ->
  1240. ?THROW_GPROC_ERROR(badarg)
  1241. end.
  1242. %% @spec (Key::key(), Props::[{K,V}]) -> true
  1243. %% @doc Add/modify `{Key, Value}' attributes associated with a shared registration.
  1244. %%
  1245. %% Gproc registration objects can have `{Key, Value}' attributes associated with
  1246. %% them. These are stored in a way that doesn't affect the cost of name lookup.
  1247. %%
  1248. %% Attributes can be retrieved using `gproc:get_attribute/3' or
  1249. %% `gproc:get_attributes/2'.
  1250. %% @end
  1251. %%
  1252. set_attributes_shared(Key, Attrs) ->
  1253. ?CATCH_GPROC_ERROR(set_attributes_shared1(Key, Attrs), [Key, Attrs]).
  1254. set_attributes_shared1(Key, Attrs) ->
  1255. case Key of
  1256. {_, g, _} ->
  1257. ?CHK_DIST,
  1258. gproc_dist:set_attributes_shared(Key, Attrs);
  1259. {_, l, _} ->
  1260. call({set_attributes_shared, Key, Attrs})
  1261. end.
  1262. %% @spec (key(), pid()) -> yes | no
  1263. %%
  1264. %% @doc Behaviour support callback
  1265. %% @end
  1266. register_name({n,_,_} = Name, Pid) when Pid == self() ->
  1267. try reg(Name), yes
  1268. catch
  1269. error:_ ->
  1270. no
  1271. end.
  1272. %% @equiv unreg/1
  1273. unregister_name(Key) ->
  1274. unreg(Key).
  1275. %% @spec select(Arg) -> [Match] | {[Match], Continuation} | '$end_of_table'
  1276. %% where Arg = Continuation
  1277. %% | sel_pattern()
  1278. %% Match = {Key, Pid, Value}
  1279. %% @doc Perform a select operation on the process registry
  1280. %%
  1281. %% When Arg = Contination, resume a gproc:select/1 operation
  1282. %% (see {@link //stdlib/ets:select/1. ets:select/1}
  1283. %%
  1284. %% When Arg = {@type sel_pattern()}, this function executes a select operation,
  1285. %% emulating ets:select/1
  1286. %%
  1287. %% {@link select/2} offers the opportunity to narrow the search
  1288. %% (by limiting to only global or local scope, or a single type of object).
  1289. %% When only a pattern as single argument is given, both global and local scope,
  1290. %% as well as all types of object can be searched. Note that the pattern may
  1291. %% still limit the select operation so that scanning the entire table is avoided.
  1292. %%
  1293. %% The physical representation in the registry may differ from the above,
  1294. %% but the select patterns are transformed appropriately. The logical
  1295. %% representation for the gproc select operations is given by
  1296. %% {@type headpat()}.
  1297. %% @end
  1298. select({?TAB, _, _, _, _, _, _, _} = Continuation) ->
  1299. ets:select(Continuation);
  1300. select(Pat) ->
  1301. select(all, Pat).
  1302. %% @spec (Context::sel_context(), Pat::sel_pattern()) -> [{Key, Pid, Value}]
  1303. %%
  1304. %% @doc Perform a select operation with limited context on the process registry
  1305. %%
  1306. %% The physical representation in the registry may differ from the above,
  1307. %% but the select patterns are transformed appropriately.
  1308. %%
  1309. %% Note that limiting the context is just a convenience function, allowing you
  1310. %% to write a simpler select pattern and still avoid searching the entire
  1311. %% registry. Whenever variables are used in the head pattern, this will result
  1312. %% in a wider scan, even if the values are restricted through a guard (e.g.
  1313. %% <code>select([{'$1','$2','$3'}, [{'==', {element,1,'$1'}, p}], ...])</code>
  1314. %% will count as a wild pattern on the key and result in a full scan).
  1315. %% In this case, specifying a Context will allow gproc to perform some
  1316. %% variable substitution and ensure that the scan is limited.
  1317. %% @end
  1318. select(Context, Pat) ->
  1319. ets:select(?TAB, pattern(Pat, Context)).
  1320. %% @spec (Context::context(), Pat::sel_patten(), Limit::integer()) ->
  1321. %% {[Match],Continuation} | '$end_of_table'
  1322. %% @doc Like {@link select/2} but returns Limit objects at a time.
  1323. %%
  1324. %% See [http://www.erlang.org/doc/man/ets.html#select-3].
  1325. %% @end
  1326. select(Context, Pat, Limit) ->
  1327. ets:select(?TAB, pattern(Pat, Context), Limit).
  1328. %% @spec (sel_pattern()) -> list(sel_object())
  1329. %% @doc
  1330. %% @equiv select_count(all, Pat)
  1331. %% @end
  1332. select_count(Pat) ->
  1333. select_count(all, Pat).
  1334. %% @spec (Context::context(), Pat::sel_pattern()) -> [{Key, Pid, Value}]
  1335. %%
  1336. %% @doc Perform a select_count operation on the process registry.
  1337. %%
  1338. %% The physical representation in the registry may differ from the above,
  1339. %% but the select patterns are transformed appropriately.
  1340. %% @end
  1341. select_count(Context, Pat) ->
  1342. ets:select_count(?TAB, pattern(Pat, Context)).
  1343. %%% Local properties can be registered in the local process, since
  1344. %%% no other process can interfere.
  1345. %%%
  1346. local_reg({_,Scope,_} = Key, Value, As, Op) ->
  1347. case gproc_lib:insert_reg(Key, Value, self(), l) of
  1348. false ->
  1349. case ets:member(?TAB, {Key, self()}) of
  1350. true when Op == ensure ->
  1351. gproc_lib:do_set_value(Key, Value, self()),
  1352. set_attrs(As, Key, self()),
  1353. updated;
  1354. _ ->
  1355. ?THROW_GPROC_ERROR(badarg)
  1356. end;
  1357. true ->
  1358. monitor_me(),
  1359. if As =/= [] ->
  1360. gproc_lib:insert_attr(Key, As, self(), Scope),
  1361. regged_new(Op);
  1362. true ->
  1363. regged_new(Op)
  1364. end
  1365. end.
  1366. regged_new(reg ) -> true;
  1367. regged_new(ensure) -> new.
  1368. local_mreg(_, []) -> true;
  1369. local_mreg(T, [_|_] = KVL) ->
  1370. case gproc_lib:insert_many(T, l, KVL, self()) of
  1371. false -> ?THROW_GPROC_ERROR(badarg);
  1372. {true,_} -> monitor_me()
  1373. end.
  1374. local_munreg(T, L) when T==p; T==c ->
  1375. _ = [gproc_lib:remove_reg({T,l,K}, self(), unreg) || K <- L],
  1376. true.
  1377. %% @spec (Key :: key(), Value) -> true
  1378. %% @doc Sets the value of the registration given by Key
  1379. %%
  1380. %% Key is assumed to exist and belong to the calling process.
  1381. %% If it doesn't, this function will exit.
  1382. %%
  1383. %% Value can be any term, unless the object is a counter, in which case
  1384. %% it must be an integer.
  1385. %% @end
  1386. %%
  1387. set_value(Key, Value) ->
  1388. ?CATCH_GPROC_ERROR(set_value1(Key, Value), [Key, Value]).
  1389. %% @spec (Key :: key(), Value) -> true
  1390. %% @doc Sets the value of the shared registration given by Key
  1391. %%
  1392. %% Key is assumed to exist as a shared entity.
  1393. %% If it doesn't, this function will exit.
  1394. %%
  1395. %% Value can be any term, unless the object is a counter, in which case
  1396. %% it must be an integer.
  1397. %% @end
  1398. %%
  1399. set_value_shared({T,_,_} = Key, Value) when T == c;
  1400. T == a;
  1401. T == p;
  1402. T == r ->
  1403. ?CATCH_GPROC_ERROR(set_value_shared1(Key, Value), [Key, Value]).
  1404. set_value1({_,g,_} = Key, Value) ->
  1405. ?CHK_DIST,
  1406. gproc_dist:set_value(Key, Value);
  1407. set_value1({a,l,_} = Key, Value) when is_integer(Value) ->
  1408. call({set, Key, Value});
  1409. set_value1({n,l,_} = Key, Value) ->
  1410. %% we cannot do this locally, since we have to check that the object
  1411. %% exists first - not an atomic update.
  1412. call({set, Key, Value});
  1413. set_value1({p,l,_} = Key, Value) ->
  1414. %% we _can_ to this locally, since there is no race condition - no
  1415. %% other process can update our properties.
  1416. case gproc_lib:do_set_value(Key, Value, self()) of
  1417. true -> true;
  1418. false ->
  1419. erlang:error(badarg)
  1420. end;
  1421. set_value1({c,l,_} = Key, Value) when is_integer(Value) ->
  1422. gproc_lib:do_set_counter_value(Key, Value, self());
  1423. set_value1(_, _) ->
  1424. ?THROW_GPROC_ERROR(badarg).
  1425. set_value_shared1({_,g,_} = Key, Value) ->
  1426. ?CHK_DIST,
  1427. gproc_dist:set_value_shared(Key, Value);
  1428. set_value_shared1({_,l,_} = Key, Value) ->
  1429. call({set_shared, Key, Value}).
  1430. %% @spec (Key) -> Value
  1431. %% @doc Reads the value stored with a key registered to the current process.
  1432. %%
  1433. %% If no such key is registered to the current process, this function exits.
  1434. %% @end
  1435. get_value(Key) ->
  1436. ?CATCH_GPROC_ERROR(get_value1(Key, self()), [Key]).
  1437. %% @spec (Key) -> Value
  1438. %% @doc Reads the value stored with a shared key.
  1439. %%
  1440. %% If no such shared key is registered, this function exits.
  1441. %% @end
  1442. get_value_shared(Key) ->
  1443. ?CATCH_GPROC_ERROR(get_value1(Key, shared), [Key]).
  1444. %% @spec (Key, Pid) -> Value
  1445. %% @doc Reads the value stored with a key registered to the process Pid.
  1446. %%
  1447. %% If `Pid == shared', the value of a shared key (see {@link reg_shared/1})
  1448. %% will be read.
  1449. %% @end
  1450. %%
  1451. get_value(Key, Pid) ->
  1452. ?CATCH_GPROC_ERROR(get_value1(Key, Pid), [Key, Pid]).
  1453. get_value1({T,_,_} = Key, Pid) when is_pid(Pid) ->
  1454. if T==n; T==a; T==rc ->
  1455. case ets:lookup(?TAB, {Key, T}) of
  1456. [{_, P, Value}] when P == Pid -> Value;
  1457. _ -> ?THROW_GPROC_ERROR(badarg)
  1458. end;
  1459. true ->
  1460. ets:lookup_element(?TAB, {Key, Pid}, 3)
  1461. end;
  1462. get_value1({T,_,_} = K, shared) when T==c; T==a; T==p; T==r ->
  1463. Key = case T of
  1464. c -> {K, shared};
  1465. p -> {K, shared};
  1466. r -> {K, shared};
  1467. a -> {K, a}
  1468. end,
  1469. case ets:lookup(?TAB, Key) of
  1470. [{_, shared, Value}] -> Value;
  1471. _ -> ?THROW_GPROC_ERROR(badarg)
  1472. end;
  1473. get_value1(_, _) ->
  1474. ?THROW_GPROC_ERROR(badarg).
  1475. %% @spec (Key, Attribute::atom()) -> Value
  1476. %% @doc Get attribute value of `Attr' associated with `Key' for most likely Pid.
  1477. %%
  1478. %% The most likely Pid in this case is `self()' for properties and counters,
  1479. %% and the current registration holder in case of names or aggregated counters.
  1480. %% An exception is raised if `Key' is not registered for the given process.
  1481. %% @end
  1482. get_attribute(Key, A) ->
  1483. Pid = case Key of
  1484. {T,_,_} when T==n; T==a; T==rc ->
  1485. where(Key);
  1486. {T,_,_} when T==p; T==c; T==r ->
  1487. self()
  1488. end,
  1489. ?CATCH_GPROC_ERROR(get_attribute1(Key, Pid, A), [Key, A]).
  1490. %% @spec (Key, Pid::pid() | shared, Attr::atom()) -> Value
  1491. %% @doc Get the attribute value of `Attr' associated with `Key' for process Pid.
  1492. %%
  1493. %% If `Pid == shared', the attribute of a shared key (see {@link reg_shared/1})
  1494. %% will be read.
  1495. %% @end
  1496. %%
  1497. get_attribute(Key, Pid, A) ->
  1498. ?CATCH_GPROC_ERROR(get_attribute1(Key, Pid, A), [Key, Pid, A]).
  1499. %% @spec (Key, Attr::atom()) -> Value
  1500. %% @doc Get the attribute value of `Attr' associated with the shared `Key'.
  1501. %%
  1502. %% Equivalent to `get_attribute(Key, shared, Attr)'
  1503. %% (see {@link get_attribute/3}).
  1504. %% @end
  1505. get_attribute_shared(Key, Attr) ->
  1506. ?CATCH_GPROC_ERROR(get_attribute1(Key, shared, Attr), [Key, Attr]).
  1507. %% @private
  1508. get_attribute1({_,_,_} = Key, Pid, A) when is_pid(Pid); Pid==shared ->
  1509. case ets:lookup(?TAB, {Pid, Key}) of
  1510. [{_, Attrs}] ->
  1511. case lists:keyfind(attrs, 1, Attrs) of
  1512. false -> undefined;
  1513. {_, As} ->
  1514. case lists:keyfind(A, 1, As) of
  1515. false -> undefined;
  1516. {_, V} -> V
  1517. end
  1518. end;
  1519. _ -> ?THROW_GPROC_ERROR(badarg)
  1520. end;
  1521. get_attribute1(_, _, _) ->
  1522. ?THROW_GPROC_ERROR(badarg).
  1523. %% @spec get_attributes(Key::key()) -> [{K, V}]
  1524. %% @doc Get attributes associated with registration.
  1525. %% @equiv get_attributes(Key, self())
  1526. %%
  1527. get_attributes(Key) ->
  1528. ?CATCH_GPROC_ERROR(get_attributes1(Key, self()), [Key]).
  1529. %% @spec (Key::key(), Pid::pid() | shared) -> [{K, V}]
  1530. %%
  1531. %% @doc Returns the list of attributes associated with the registration.
  1532. %%
  1533. %% This function raises a `badarg' exception if there is no corresponding
  1534. %% registration.
  1535. %%
  1536. get_attributes(Key, Pid) ->
  1537. ?CATCH_GPROC_ERROR(get_attributes1(Key, Pid), [Key, Pid]).
  1538. get_attributes1({_,_,_} = Key, Pid) when is_pid(Pid); Pid==shared ->
  1539. case ets:lookup(?TAB, {Pid, Key}) of
  1540. [{_, Attrs}] ->
  1541. case lists:keyfind(attrs, 1, Attrs) of
  1542. false -> [];
  1543. {_, As} -> As
  1544. end;
  1545. _ -> ?THROW_GPROC_ERROR(badarg)
  1546. end;
  1547. get_attributes1(_, _) ->
  1548. ?THROW_GPROC_ERROR(badarg).
  1549. %% @spec (Key) -> Pid
  1550. %% @doc Lookup the Pid stored with a key.
  1551. %%
  1552. %% This function raises a `badarg' exception if `Key' is not registered.
  1553. %% @end
  1554. lookup_pid({_T,_,_} = Key) ->
  1555. case where(Key) of
  1556. undefined -> erlang:error(badarg);
  1557. P -> P
  1558. end.
  1559. %% @spec (Key) -> Value
  1560. %% @doc Lookup the value stored with a key.
  1561. %%
  1562. %% This function raises a `badarg' exception if `Key' is not registered.
  1563. %% @end
  1564. lookup_value({T,_,_} = Key) ->
  1565. if T==n orelse T==a orelse T==rc ->
  1566. ets:lookup_element(?TAB, {Key,T}, 3);
  1567. true ->
  1568. erlang:error(badarg)
  1569. end.
  1570. %% @spec (Key::key()) -> pid() | undefined
  1571. %%
  1572. %% @doc Returns the pid registered as Key
  1573. %%
  1574. %% The type of registration must be either name or aggregated counter.
  1575. %% Otherwise this function will raise a `badarg' exception.
  1576. %% Use {@link lookup_pids/1} in these cases.
  1577. %% @end
  1578. %%
  1579. where(Key) ->
  1580. ?CATCH_GPROC_ERROR(where1(Key), [Key]).
  1581. where1({T,_,_}=Key) ->
  1582. if T==n orelse T==a orelse T==rc ->
  1583. case ets:lookup(?TAB, {Key,T}) of
  1584. [{_, P, _Value}] ->
  1585. case my_is_process_alive(P) of
  1586. true -> P;
  1587. false ->
  1588. undefined
  1589. end;
  1590. _ -> % may be [] or [{Key,Waiters}]
  1591. undefined
  1592. end;
  1593. true ->
  1594. ?THROW_GPROC_ERROR(badarg)
  1595. end.
  1596. %% @equiv where/1
  1597. whereis_name(Key) ->
  1598. ?CATCH_GPROC_ERROR(where1(Key), [Key]).
  1599. %% @spec (Key::key()) -> [pid()]
  1600. %%
  1601. %% @doc Returns a list of pids with the published key Key
  1602. %%
  1603. %% If the type of registration is either name or aggregated counter,
  1604. %% this function will return either an empty list, or a list of one pid.
  1605. %% For non-unique types, the return value can be a list of any length.
  1606. %%
  1607. %% Note: shared resources are not associated with any pid, and will
  1608. %% therefore be excluded.
  1609. %% @end
  1610. %%
  1611. lookup_pids({T,_,_} = Key) ->
  1612. L = if T==n orelse T==a orelse T==rc ->
  1613. ets:select(?TAB, [{{{Key,T}, '$1', '_'},
  1614. [{is_pid, '$1'}], ['$1']}]);
  1615. true ->
  1616. ets:select(?TAB, [{{{Key,'_'}, '$1', '_'},
  1617. [{is_pid, '$1'}], ['$1']}])
  1618. end,
  1619. [P || P <- L, my_is_process_alive(P)].
  1620. %% @spec (pid()) -> boolean()
  1621. %%
  1622. my_is_process_alive(P) when node(P) =:= node() ->
  1623. is_process_alive(P);
  1624. my_is_process_alive(_) ->
  1625. %% remote pid - assume true (too costly to find out)
  1626. true.
  1627. %% @spec (Key::key()) -> [{pid(), Value}]
  1628. %%
  1629. %% @doc Retrieve the `{Pid,Value}' pairs corresponding to Key.
  1630. %%
  1631. %% Key refer to any type of registry object. If it refers to a unique
  1632. %% object, the list will be of length 0 or 1. If it refers to a non-unique
  1633. %% object, the return value can be a list of any length.
  1634. %% @end
  1635. %%
  1636. lookup_values({T,_,_} = Key) ->
  1637. L = if T==n orelse T==a orelse T==rc ->
  1638. ets:select(?TAB, [{{{Key,T}, '$1', '$2'},[],[{{'$1','$2'}}]}]);
  1639. true ->
  1640. ets:select(?TAB, [{{{Key,'_'}, '$1', '$2'},[],[{{'$1','$2'}}]}])
  1641. end,
  1642. [Pair || {P,_} = Pair <- L, my_is_process_alive(P)].
  1643. %% @ spec (Key::key(), Incr) -> integer() | [integer()]
  1644. %% Incr = IncrVal | UpdateOp | [UpdateOp]
  1645. %% UpdateOp = IncrVal | {IncrVal, Threshold, SetValue}
  1646. %% IncrVal = integer()
  1647. %%
  1648. %% @doc Updates the counter registered as Key for the current process.
  1649. %%
  1650. %% This function works almost exactly like ets:update_counter/3
  1651. %% (see [http://www.erlang.org/doc/man/ets.html#update_counter-3]), but
  1652. %% will fail if the type of object referred to by Key is not a counter or
  1653. %% a unique name (update_counter/2 can be performed on names as well, but they
  1654. %% do not count as counter objects, and do not affect aggregated counters).
  1655. %%
  1656. %% Aggregated counters with the same name will be updated automatically.
  1657. %% The `UpdateOp' patterns are the same as for `ets:update_counter/3', except
  1658. %% that the position is omitted; in gproc, the value position is always `3'.
  1659. %%
  1660. %% If `Key' refers to a unique name, the operation will depend on the value
  1661. %% part of the registration being an integer(). While non-integer values are
  1662. %% not permitted at all for counter objects, it is the user's responsibility to
  1663. %% ensure that a name, on which `update_counter/2' is to be performed, has the
  1664. %% appropriate value type.
  1665. %% @end
  1666. %%
  1667. -spec update_counter(key(), increment()) -> integer() | [integer()].
  1668. update_counter(Key, Incr) ->
  1669. Pid = case Key of
  1670. {n,_,_} -> n;
  1671. {T,_,_} when T==c; T==r ->
  1672. self()
  1673. end,
  1674. ?CATCH_GPROC_ERROR(update_counter1(Key, Pid, Incr), [Key, Incr]).
  1675. update_counter(Key, Pid, Incr) when is_pid(Pid);
  1676. Pid == shared; Pid == n ->
  1677. ?CATCH_GPROC_ERROR(update_counter1(Key, Pid, Incr), [Key, Pid, Incr]).
  1678. update_counter1({T,l,_} = Key, Pid, Incr) when T==c; T==r; T==n ->
  1679. gproc_lib:update_counter(Key, Incr, Pid);
  1680. update_counter1({T,g,_} = Key, Pid, Incr) when T==c; T==r; T==n ->
  1681. ?CHK_DIST,
  1682. gproc_dist:update_counter(Key, Pid, Incr);
  1683. update_counter1(_, _, _) ->
  1684. ?THROW_GPROC_ERROR(badarg).
  1685. %% @doc Update a list of counters
  1686. %%
  1687. %% This function is not atomic, except (in a sense) for global counters. For local counters,
  1688. %% it is more of a convenience function. For global counters, it is much more efficient
  1689. %% than calling `gproc:update_counter/2' for each individual counter.
  1690. %%
  1691. %% The return value is the corresponding list of `[{Counter, Pid, NewValue}]'.
  1692. %% @end
  1693. -spec update_counters(scope(), [{key(), pid(), increment()}]) ->
  1694. [{key(), pid(), integer()}].
  1695. update_counters(_, []) ->
  1696. [];
  1697. update_counters(l, [_|_] = Cs) ->
  1698. ?CATCH_GPROC_ERROR(update_counters1(Cs), [Cs]);
  1699. update_counters(g, [_|_] = Cs) ->
  1700. ?CHK_DIST,
  1701. gproc_dist:update_counters(Cs).
  1702. update_counters1([{{c,l,_} = Key, Pid, Incr}|T]) ->
  1703. [{Key, Pid, gproc_lib:update_counter(Key, Incr, Pid)}|update_counters1(T)];
  1704. update_counters1([]) ->
  1705. [];
  1706. update_counters1(_) ->
  1707. ?THROW_GPROC_ERROR(badarg).
  1708. %% @spec (Key) -> {ValueBefore, ValueAfter}
  1709. %% Key = {c, Scope, Name} | {n, Scope, Name}
  1710. %% Scope = l | g
  1711. %% ValueBefore = integer()
  1712. %% ValueAfter = integer()
  1713. %%
  1714. %% @doc Reads and resets a counter in a "thread-safe" way
  1715. %%
  1716. %% This function reads the current value of a counter and then resets it to its
  1717. %% initial value. The reset operation is done using {@link update_counter/2},
  1718. %% which allows for concurrent calls to {@link update_counter/2} without losing
  1719. %% updates. Aggregated counters are updated accordingly.
  1720. %%
  1721. %% If `Key' refers to a unique name, the operation will depend on the value
  1722. %% part of the registration being an integer(). While non-integer values are
  1723. %% not permitted at all for counter objects, it is the user's responsibility to
  1724. %% ensure that a name, on which `reset_counter/1' is to be performed, has the
  1725. %% appropriate value type.
  1726. %% @end
  1727. %%
  1728. reset_counter(Key) ->
  1729. ?CATCH_GPROC_ERROR(reset_counter1(Key), [Key]).
  1730. reset_counter1({T,g,_} = Key) when T==c; T==n ->
  1731. ?CHK_DIST,
  1732. gproc_dist:reset_counter(Key);
  1733. reset_counter1({n,l,_} = Key) ->
  1734. [{_, Pid, Current}] = ets:lookup(?TAB, {Key, n}),
  1735. {Current, update_counter(Key, get_initial(Pid, Key) - Current)};
  1736. reset_counter1({c,l,_} = Key) ->
  1737. Current = ets:lookup_element(?TAB, {Key, self()}, 3),
  1738. {Current, update_counter(Key, get_initial(self(), Key) - Current)}.
  1739. get_initial(Pid, Key) ->
  1740. case ets:lookup(?TAB, {Pid, Key}) of
  1741. [{_, r}] -> 0;
  1742. [{_, Opts}] ->
  1743. proplists:get_value(initial, Opts, 0)
  1744. end.
  1745. %% @spec (Key::key(), Incr) -> integer() | [integer()]
  1746. %% Incr = IncrVal | UpdateOp | [UpdateOp]
  1747. %% UpdateOp = IncrVal | {IncrVal, Threshold, SetValue}
  1748. %% IncrVal = integer()
  1749. %%
  1750. %% @doc Updates the shared counter registered as Key.
  1751. %%
  1752. %% This function works almost exactly like ets:update_counter/3
  1753. %% (see [http://www.erlang.org/doc/man/ets.html#update_counter-3]), but
  1754. %% will fail if the type of object referred to by Key is not a counter.
  1755. %%
  1756. %% Aggregated counters with the same name will be updated automatically.
  1757. %% The `UpdateOp' patterns are the same as for `ets:update_counter/3', except
  1758. %% that the position is omitted; in gproc, the value position is always `3'.
  1759. %% @end
  1760. %%
  1761. update_shared_counter(Key, Incr) ->
  1762. ?CATCH_GPROC_ERROR(update_shared_counter1(Key, Incr), [Key, Incr]).
  1763. update_shared_counter1({c,g,_} = Key, Incr) ->
  1764. ?CHK_DIST,
  1765. gproc_dist:update_shared_counter(Key, Incr);
  1766. update_shared_counter1({c,l,_} = Key, Incr) ->
  1767. gproc_lib:update_counter(Key, Incr, shared).
  1768. %% @spec (From::key(), To::pid() | key()) -> undefined | pid()
  1769. %%
  1770. %% @doc Atomically transfers the key `From' to the process identified by `To'.
  1771. %%
  1772. %% This function transfers any gproc key (name, property, counter, aggr counter)
  1773. %% from one process to another, and returns the pid of the new owner.
  1774. %%
  1775. %% `To' must be either a pid or a unique name (name or aggregated counter), but
  1776. %% does not necessarily have to resolve to an existing process. If there is
  1777. %% no process registered with the `To' key, `give_away/2' returns `undefined',
  1778. %% and the `From' key is effectively unregistered.
  1779. %%
  1780. %% It is allowed to give away a key to oneself, but of course, this operation
  1781. %% will have no effect.
  1782. %%
  1783. %% Fails with `badarg' if the calling process does not have a `From' key
  1784. %% registered.
  1785. %% @end
  1786. give_away(Key, ToPid) ->
  1787. ?CATCH_GPROC_ERROR(give_away1(Key, ToPid), [Key, ToPid]).
  1788. give_away1({_,l,_} = Key, ToPid) when is_pid(ToPid), node(ToPid) == node() ->
  1789. call({give_away, Key, ToPid});
  1790. give_away1({_,l,_} = Key, {n,l,_} = ToKey) ->
  1791. call({give_away, Key, ToKey});
  1792. give_away1({_,g,_} = Key, To) ->
  1793. ?CHK_DIST,
  1794. gproc_dist:give_away(Key, To).
  1795. %% @spec () -> ok
  1796. %%
  1797. %% @doc Unregister all items of the calling process and inform gproc
  1798. %% to forget about the calling process.
  1799. %%
  1800. %% This function is more efficient than letting gproc perform these
  1801. %% cleanup operations.
  1802. %% @end
  1803. goodbye() ->
  1804. process_is_down(self()).
  1805. %% @spec (Key::process() | key(), Msg::any()) -> Msg
  1806. %%
  1807. %% @doc Sends a message to the process, or processes, corresponding to Key.
  1808. %%
  1809. %% If Key belongs to a unique object (name or aggregated counter), this
  1810. %% function will send a message to the corresponding process, or fail if there
  1811. %% is no such process. If Key is for a non-unique object type (counter or
  1812. %% property), Msg will be send to all processes that have such an object.
  1813. %%
  1814. %% Key can also be anything that the erlang:send/2, or '!' operator accepts as a process
  1815. %% identifier, namely a pid(), an atom(), or `{Name::atom(), Node::atom()}'.
  1816. %% @end
  1817. %%
  1818. send(P, Msg) when is_pid(P); is_atom(P) ->
  1819. P ! Msg;
  1820. send({Name, Node} = P, Msg) when is_atom(Node), is_atom(Name) ->
  1821. P ! Msg;
  1822. send(Key, Msg) ->
  1823. ?CATCH_GPROC_ERROR(send1(Key, Msg), [Key, Msg]).
  1824. send1({T,C,_} = Key, Msg) when C==l; C==g ->
  1825. if T == n orelse T == a orelse T == rc ->
  1826. case ets:lookup(?TAB, {Key, T}) of
  1827. [{_, Pid, _}] ->
  1828. Pid ! Msg;
  1829. _ ->
  1830. ?THROW_GPROC_ERROR(badarg)
  1831. end;
  1832. T==p orelse T==c orelse T==r ->
  1833. %% BUG - if the key part contains select wildcards, we may end up
  1834. %% sending multiple messages to the same pid
  1835. lists:foreach(fun(Pid) ->
  1836. Pid ! Msg
  1837. end, lookup_pids(Key)),
  1838. Msg;
  1839. true ->
  1840. erlang:error(badarg)
  1841. end;
  1842. send1(_, _) ->
  1843. ?THROW_GPROC_ERROR(badarg).
  1844. %% @spec (Key::key(), Msg::any()) -> Msg
  1845. %%
  1846. %% @equiv bcast(nodes(), Key, Msg)
  1847. %% @end
  1848. %%
  1849. bcast(Key, Msg) ->
  1850. bcast(nodes(), Key, Msg).
  1851. %% @spec (Nodes::[atom()], Key::key(), Msg::any()) -> Msg
  1852. %%
  1853. %% @doc Sends a message to processes corresponding to Key on Nodes.
  1854. %%
  1855. %% This function complements `send/2' and works on locally registered resources
  1856. %% that `send/2' supports. Messages are routed via a special broadcast server
  1857. %% on each node to ensure that ordering is preserved. Distributed delivery
  1858. %% is asynchronous and carries the same guarantees as normal message passing
  1859. %% (with the added proviso that the broadcast server also needs to be available).
  1860. %% @see send/2
  1861. %% @end
  1862. %%
  1863. bcast(Ns, Key, Msg) ->
  1864. ?CATCH_GPROC_ERROR(bcast1(Ns, Key, Msg), [Key, Msg]).
  1865. bcast1(Ns, {T,l,_} = Key, Msg) when T==p; T==a; T==c; T==n; T==r; T==rc ->
  1866. send1(Key, Msg),
  1867. gen_server:abcast(Ns -- [node()], gproc_bcast, {send, Key, Msg}),
  1868. Msg.
  1869. %% @spec (Context :: context()) -> key() | '$end_of_table'
  1870. %%
  1871. %% @doc Behaves as ets:first(Tab) for a given type of registration.
  1872. %%
  1873. %% See [http://www.erlang.org/doc/man/ets.html#first-1].
  1874. %% The registry behaves as an ordered_set table.
  1875. %% @end
  1876. %%
  1877. first(Context) ->
  1878. {S, T} = get_s_t(Context),
  1879. {HeadPat,_} = headpat({S, T}, '_', '_', '_'),
  1880. case ets:select(?TAB, [{HeadPat,[],[{element,1,'$_'}]}], 1) of
  1881. {[First], _} ->
  1882. First;
  1883. _ ->
  1884. '$end_of_table'
  1885. end.
  1886. %% @spec (Context :: context()) -> key() | '$end_of_table'
  1887. %%
  1888. %% @doc Behaves as ets:last(Tab) for a given type of registration.
  1889. %%
  1890. %% See [http://www.erlang.org/doc/man/ets.html#last-1].
  1891. %% The registry behaves as an ordered_set table.
  1892. %% @end
  1893. %%
  1894. last(Context) ->
  1895. {S, T} = get_s_t(Context),
  1896. S1 = if S == '_'; S == l -> m; % 'm' comes after 'l'
  1897. S == g -> h % 'h' comes between 'g' & 'l'
  1898. end,
  1899. Beyond = {{T,S1,[]},[]},
  1900. step(ets:prev(?TAB, Beyond), S, T).
  1901. %% @spec (Context::context(), Key::key()) -> key() | '$end_of_table'
  1902. %%
  1903. %% @doc Behaves as ets:next(Tab,Key) for a given type of registration.
  1904. %%
  1905. %% See [http://www.erlang.org/doc/man/ets.html#next-2].
  1906. %% The registry behaves as an ordered_set table.
  1907. %% @end
  1908. %%
  1909. next(Context, K) ->
  1910. {S,T} = get_s_t(Context),
  1911. {Prev,Unwrap} =
  1912. case K of
  1913. {{_,_,_},_} ->
  1914. {K, false};
  1915. {_,_,_} ->
  1916. {{K,[]}, true} % [] is higher than pid(), shared, p, c...
  1917. end,
  1918. unwrap(Unwrap, step(ets:next(?TAB,Prev), S, T)).
  1919. unwrap(true, {{_,_,_} = R,_}) ->
  1920. R;
  1921. unwrap(_, R) ->
  1922. R.
  1923. %% @spec (Context::context(), Key::key()) -> key() | '$end_of_table'
  1924. %%
  1925. %% @doc Behaves as ets:prev(Tab,Key) for a given type of registration.
  1926. %%
  1927. %% See [http://www.erlang.org/doc/man/ets.html#prev-2].
  1928. %% The registry behaves as an ordered_set table.
  1929. %% @end
  1930. %%
  1931. prev(Context, K) ->
  1932. {S, T} = get_s_t(Context),
  1933. {Prev, Unwrap} =
  1934. case K of
  1935. {{_,_,_},_} -> {K, false};
  1936. {_,_,_} ->
  1937. {{K,1}, true}
  1938. end,
  1939. unwrap(Unwrap, step(ets:prev(?TAB, Prev), S, T)).
  1940. step(Key, '_', '_') ->
  1941. case Key of
  1942. {{_,_,_},_} -> Key;
  1943. _ -> '$end_of_table'
  1944. end;
  1945. step(Key, '_', T) ->
  1946. case Key of
  1947. {{T,_,_},_} -> Key;
  1948. _ -> '$end_of_table'
  1949. end;
  1950. step(Key, S, '_') ->
  1951. case Key of
  1952. {{_, S, _}, _} -> Key;
  1953. _ -> '$end_of_table'
  1954. end;
  1955. step(Key, S, T) ->
  1956. case Key of
  1957. {{T, S, _}, _} -> Key;
  1958. _ -> '$end_of_table'
  1959. end.
  1960. %% @spec (Pid::pid()) -> ProcessInfo
  1961. %% ProcessInfo = [{gproc, [{Key,Value}]} | ProcessInfo]
  1962. %%
  1963. %% @doc Similar to `process_info(Pid)' but with additional gproc info.
  1964. %%
  1965. %% Returns the same information as process_info(Pid), but with the
  1966. %% addition of a `gproc' information item, containing the `{Key,Value}'
  1967. %% pairs registered to the process.
  1968. %% @end
  1969. info(Pid) when is_pid(Pid) ->
  1970. Items = [?MODULE | [ I || {I,_} <- process_info(self())]],
  1971. [info(Pid,I) || I <- Items].
  1972. %% @spec (Pid::pid(), Item::atom()) -> {Item, Info}
  1973. %%
  1974. %% @doc Similar to process_info(Pid, Item), but with additional gproc info.
  1975. %%
  1976. %% For `Item = gproc', this function returns a list of `{Key, Value}' pairs
  1977. %% registered to the process Pid. For other values of Item, it returns the
  1978. %% same as [http://www.erlang.org/doc/man/erlang.html#process_info-2].
  1979. %% @end
  1980. info(Pid, gproc) ->
  1981. gproc_info(Pid, '_');
  1982. info(Pid, {gproc, Pat}) ->
  1983. gproc_info(Pid, Pat);
  1984. info(Pid, current_function) ->
  1985. {_, T} = process_info(Pid, backtrace),
  1986. info_cur_f(T, process_info(Pid, current_function));
  1987. info(Pid, I) ->
  1988. process_info(Pid, I).
  1989. %% We don't want to return the internal gproc:info() function as current
  1990. %% function, so we grab the 'backtrace' and extract the call stack from it,
  1991. %% filtering out the functions gproc:info/_ and gproc:'-info/1-lc...' entries.
  1992. %%
  1993. %% This is really an indication that wrapping the process_info() BIF was a
  1994. %% bad idea to begin with... :P
  1995. %%
  1996. info_cur_f(T, Default) ->
  1997. {match, Matches} = re:run(T,<<"\\(([^\\)]+):(.+)/([0-9]+)">>,
  1998. [global,{capture,[1,2,3],list}]),
  1999. case lists:dropwhile(fun(["gproc","info",_]) -> true;
  2000. (["gproc","'-info/1-lc" ++ _, _]) -> true;
  2001. (["erlang","process_info", _]) -> true;
  2002. (_) -> false
  2003. end, Matches) of
  2004. [] ->
  2005. Default;
  2006. [[M,F,A]|_] ->
  2007. {current_function,
  2008. {to_atom(M), to_atom(F), list_to_integer(A)}}
  2009. end.
  2010. to_atom(S) ->
  2011. case erl_scan:string(S) of
  2012. {ok, [{atom,_,A}|_],_} ->
  2013. A;
  2014. _ ->
  2015. list_to_atom(S)
  2016. end.
  2017. gproc_info(Pid, Pat) ->
  2018. Keys = ets:select(?TAB, [{ {{Pid,Pat}, '_'}, [], [{element,2,
  2019. {element,1,'$_'}}] }]),
  2020. {?MODULE, lists:zf(
  2021. fun(K) ->
  2022. try V = get_value(K, Pid),
  2023. {true, {K,V}}
  2024. catch
  2025. error:_ ->
  2026. false
  2027. end
  2028. end, Keys)}.
  2029. %% @spec () -> ok
  2030. %%
  2031. %% @doc Similar to the built-in shell command `i()' but inserts information
  2032. %% about names and properties registered in Gproc, where applicable.
  2033. %% @end
  2034. i() ->
  2035. gproc_info:i().
  2036. %%% ==========================================================
  2037. %% @hidden
  2038. handle_cast({monitor_me, Pid}, S) ->
  2039. erlang:monitor(process, Pid),
  2040. {noreply, S};
  2041. handle_cast({audit_process, Pid}, S) ->
  2042. case is_process_alive(Pid) of
  2043. false ->
  2044. process_is_down(Pid);
  2045. true ->
  2046. ignore
  2047. end,
  2048. {noreply, S};
  2049. handle_cast({cancel_wait, Pid, {T,_,_} = Key, Ref}, S) ->
  2050. _ = case ets:lookup(?TAB, {Key,T}) of
  2051. [{_, Waiters}] ->
  2052. gproc_lib:remove_wait(Key, Pid, Ref, Waiters);
  2053. _ ->
  2054. ignore
  2055. end,
  2056. {noreply, S};
  2057. handle_cast({cancel_wait_or_monitor, Pid, {T,_,_} = Key}, S) ->
  2058. _ = case ets:lookup(?TAB, {Key, T}) of
  2059. [{_, Waiters}] ->
  2060. gproc_lib:remove_wait(Key, Pid, all, Waiters);
  2061. [{_, OtherPid, _}] ->
  2062. gproc_lib:remove_monitors(Key, OtherPid, Pid);
  2063. _ ->
  2064. ok
  2065. end,
  2066. {noreply, S}.
  2067. %% @hidden
  2068. handle_call({reg, {_T,l,_} = Key, Val, Attrs, Op}, {Pid,_}, S) ->
  2069. handle_reg_call(Key, Pid, Val, Attrs, Op, S);
  2070. handle_call({reg_other, {_T,l,_} = Key, Pid, Val, Attrs, Op}, _, S) ->
  2071. handle_reg_call(Key, Pid, Val, Attrs, Op, S);
  2072. handle_call({set_attributes, {_,l,_} = Key, Attrs}, {Pid,_}, S) ->
  2073. case gproc_lib:insert_attr(Key, Attrs, Pid, l) of
  2074. false -> {reply, badarg, S};
  2075. L when is_list(L) ->
  2076. {reply, true, S}
  2077. end;
  2078. handle_call({set_attributes_shared, {_,l,_} = Key, Attrs}, _, S) ->
  2079. case gproc_lib:insert_attr(Key, Attrs, shared, l) of
  2080. false ->
  2081. {reply, badarg, S};
  2082. L when is_list(L) ->
  2083. {reply, true, S}
  2084. end;
  2085. handle_call({reg_or_locate, {T,l,_} = Key, Val, P}, _, S) ->
  2086. Reg = fun() ->
  2087. Pid = if is_function(P, 0) ->
  2088. spawn(P);
  2089. is_pid(P) ->
  2090. P
  2091. end,
  2092. true = gproc_lib:insert_reg(Key, Val, Pid, l),
  2093. _ = gproc_lib:ensure_monitor(Pid, l),
  2094. {reply, {Pid, Val}, S}
  2095. end,
  2096. case ets:lookup(?TAB, {Key, T}) of
  2097. [] ->
  2098. Reg();
  2099. [{_, _Waiters}] ->
  2100. Reg();
  2101. [{_, OtherPid, OtherValue}] ->
  2102. {reply, {OtherPid, OtherValue}, S}
  2103. end;
  2104. handle_call({monitor, {T,l,_} = Key, Pid, Type}, _From, S)
  2105. when T==n; T==a; T==rc ->
  2106. Ref = make_ref(),
  2107. Lookup = ets:lookup(?TAB, {Key, T}),
  2108. IsRegged = is_regged(Lookup),
  2109. _ = case {IsRegged, Type} of
  2110. {false, info} ->
  2111. Pid ! {gproc, unreg, Ref, Key};
  2112. {false, follow} ->
  2113. Pid ! {gproc, unreg, Ref, Key},
  2114. _ = gproc_lib:ensure_monitor(Pid, l),
  2115. case Lookup of
  2116. [{K, Waiters}] ->
  2117. NewWaiters = [{Pid,Ref,follow}|Waiters],
  2118. ets:insert(?TAB, {K, NewWaiters}),
  2119. ets:insert_new(?TAB, {{Pid,Key}, []});
  2120. [] ->
  2121. ets:insert(?TAB, {{Key,T}, [{Pid,Ref,follow}]}),
  2122. ets:insert_new(?TAB, {{Pid,Key}, []})
  2123. end;
  2124. {false, standby} ->
  2125. Evt = {failover, Pid},
  2126. true = gproc_lib:insert_reg(Key, undefined, Pid, l, Evt),
  2127. Pid ! {gproc, Evt, Ref, Key},
  2128. _ = gproc_lib:ensure_monitor(Pid, l);
  2129. {true, _} ->
  2130. [{_, RegPid, _}] = Lookup,
  2131. _ = gproc_lib:ensure_monitor(Pid, l),
  2132. case ets:lookup(?TAB, {RegPid, Key}) of
  2133. [{K,r}] ->
  2134. ets:insert(?TAB, {K, [{monitor, [{Pid,Ref,Type}]}]}),
  2135. ets:insert_new(?TAB, {{Pid,Key}, []});
  2136. [{K, Opts}] ->
  2137. ets:insert(?TAB, {K, gproc_lib:add_monitor(
  2138. Opts, Pid, Ref, Type)}),
  2139. ets:insert_new(?TAB, {{Pid,Key}, []})
  2140. end
  2141. end,
  2142. {reply, Ref, S};
  2143. handle_call({demonitor, {T,l,_} = Key, Ref, Pid}, _From, S)
  2144. when T==n; T==a; T==rc ->
  2145. _ = case ets:lookup(?TAB, {Key, T}) of
  2146. [] ->
  2147. ok; % be nice
  2148. [{_, Waiters}] ->
  2149. case lists:filter(fun({P, R, _}) ->
  2150. P =/= Pid orelse R =/= Ref
  2151. end, Waiters) of
  2152. [] ->
  2153. ets:delete(?TAB, {Pid, Key}),
  2154. ets:delete(?TAB, {Key, T});
  2155. NewWaiters ->
  2156. case lists:keymember(Pid, 1, NewWaiters) of
  2157. true ->
  2158. ok;
  2159. false ->
  2160. ets:delete(?TAB, {Pid, Key})
  2161. end,
  2162. ets:insert(?TAB, {{Key, T}, Waiters})
  2163. end;
  2164. [{_, RegPid, _}] ->
  2165. case ets:lookup(?TAB, {RegPid, Key}) of
  2166. [{_K,r}] ->
  2167. ok; % be nice
  2168. [{K, Opts}] ->
  2169. Opts1 = gproc_lib:remove_monitor(Opts, Pid, Ref),
  2170. ets:insert(?TAB, {K, Opts1}),
  2171. case gproc_lib:does_pid_monitor(Pid, Opts1) of
  2172. true ->
  2173. ok;
  2174. false ->
  2175. ets:delete(?TAB, {Pid, Key})
  2176. end
  2177. end
  2178. end,
  2179. {reply, ok, S};
  2180. handle_call({reg_shared, {_T,l,_} = Key, Val, Attrs, Op}, _From, S) ->
  2181. case try_insert_reg(Key, Val, shared) of
  2182. true ->
  2183. _ = if Attrs =/= [] ->
  2184. gproc_lib:insert_attr(Key, Attrs, shared, l);
  2185. true -> true
  2186. end,
  2187. {reply, true, S};
  2188. already_registered when Op == ensure ->
  2189. case gproc_lib:do_set_value(Key, Val, shared) of
  2190. true ->
  2191. {reply, updated, S};
  2192. false ->
  2193. {reply, badarg, S}
  2194. end;
  2195. _ ->
  2196. {reply, badarg, S}
  2197. end;
  2198. handle_call({unreg, {_,l,_} = Key}, {Pid,_}, S) ->
  2199. handle_unreg_call(Key, Pid, S);
  2200. handle_call({unreg_other, {_,l,_} = Key, Pid}, _, S) ->
  2201. handle_unreg_call(Key, Pid, S);
  2202. handle_call({unreg_shared, {_,l,_} = Key}, _, S) ->
  2203. _ = case ets:lookup(?TAB, {shared, Key}) of
  2204. [{_, r}] ->
  2205. _ = gproc_lib:remove_reg(Key, shared, unreg, []);
  2206. [{_, Opts}] ->
  2207. _ = gproc_lib:remove_reg(Key, shared, unreg, Opts);
  2208. [] ->
  2209. %% don't crash if shared key already unregged.
  2210. ok
  2211. end,
  2212. {reply, true, S};
  2213. handle_call({await, {_,l,_} = Key, Pid}, From, S) ->
  2214. %% Passing the pid explicitly is needed when leader_call is used,
  2215. %% since the Pid given as From in the leader is the local gen_leader
  2216. %% instance on the calling node.
  2217. case gproc_lib:await(Key, Pid, From) of
  2218. noreply ->
  2219. {noreply, S};
  2220. {reply, Reply, _} ->
  2221. {reply, Reply, S}
  2222. end;
  2223. handle_call({mreg, T, l, L}, {Pid,_}, S) ->
  2224. try gproc_lib:insert_many(T, l, L, Pid) of
  2225. {true,_} -> {reply, true, S};
  2226. false -> {reply, badarg, S}
  2227. catch
  2228. throw:?GPROC_THROW(_) ->
  2229. {reply, badarg, S};
  2230. error:_ ->
  2231. {reply, badarg, S}
  2232. end;
  2233. handle_call({munreg, T, l, L}, {Pid,_}, S) ->
  2234. _ = gproc_lib:remove_many(T, l, L, Pid),
  2235. {reply, true, S};
  2236. handle_call({set, {_,l,_} = Key, Value}, {Pid,_}, S) ->
  2237. case gproc_lib:do_set_value(Key, Value, Pid) of
  2238. true ->
  2239. {reply, true, S};
  2240. false ->
  2241. {reply, badarg, S}
  2242. end;
  2243. handle_call({set_shared, {_,l,_} = Key, Value}, {_,_}, S) ->
  2244. case gproc_lib:do_set_value(Key, Value, shared) of
  2245. true ->
  2246. {reply, true, S};
  2247. false ->
  2248. {reply, badarg, S}
  2249. end;
  2250. handle_call({audit_process, Pid}, _, S) ->
  2251. _ = case is_process_alive(Pid) of
  2252. false ->
  2253. process_is_down(Pid);
  2254. true ->
  2255. ignore
  2256. end,
  2257. {reply, ok, S};
  2258. handle_call({give_away, Key, To}, {Pid,_}, S) ->
  2259. Reply = do_give_away(Key, To, Pid),
  2260. {reply, Reply, S};
  2261. handle_call(_, _, S) ->
  2262. {reply, badarg, S}.
  2263. %% @hidden
  2264. handle_info({'DOWN', _MRef, process, Pid, _}, S) ->
  2265. _ = process_is_down(Pid),
  2266. {noreply, S};
  2267. handle_info(_, S) ->
  2268. {noreply, S}.
  2269. %% @hidden
  2270. code_change(_FromVsn, S, _Extra) ->
  2271. %% We have changed local monitor markers from {Pid} to {Pid,l}.
  2272. _ = case ets:select(?TAB, [{{'$1'},[],['$1']}]) of
  2273. [] ->
  2274. ok;
  2275. Pids ->
  2276. ets:insert(?TAB, [{P,l} || P <- Pids]),
  2277. ets:select_delete(?TAB, [{{'_'},[],[true]}])
  2278. end,
  2279. {ok, S}.
  2280. %% @hidden
  2281. terminate(_Reason, _S) ->
  2282. ok.
  2283. %% handle_call body common to reg and reg_other.
  2284. %%
  2285. handle_reg_call(Key, Pid, Val, Attrs, Op, S) ->
  2286. case try_insert_reg(Key, Val, Pid) of
  2287. true ->
  2288. _ = gproc_lib:ensure_monitor(Pid,l),
  2289. _ = set_attrs(Attrs, Key, Pid),
  2290. {reply, regged_new(Op), S};
  2291. already_registered when Op == ensure ->
  2292. case gproc_lib:do_set_value(Key, Val, Pid) of
  2293. true ->
  2294. _ = set_attrs(Attrs, Key, Pid),
  2295. {reply, updated, S};
  2296. false ->
  2297. %% actually pretty bad, if it ever happens
  2298. {reply, badarg, S}
  2299. end;
  2300. already_registered ->
  2301. {reply, badarg, S};
  2302. false ->
  2303. {reply, badarg, S}
  2304. end.
  2305. set_attrs([], _, _) ->
  2306. true;
  2307. set_attrs([_|_] = Attrs, Key, Pid) ->
  2308. gproc_lib:insert_attr(Key, Attrs, Pid, l).
  2309. handle_unreg_call(Key, Pid, S) ->
  2310. case ets:lookup(?TAB, {Pid,Key}) of
  2311. [{_, r}] ->
  2312. _ = gproc_lib:remove_reg(Key, Pid, unreg, []),
  2313. {reply, true, S};
  2314. [{_, Opts}] when is_list(Opts) ->
  2315. _ = gproc_lib:remove_reg(Key, Pid, unreg, Opts),
  2316. {reply, true, S};
  2317. [] ->
  2318. {reply, badarg, S}
  2319. end.
  2320. call(Req) ->
  2321. call(Req, l).
  2322. call(Req, l) ->
  2323. chk_reply(gen_server:call(?MODULE, Req));
  2324. call(Req, g) ->
  2325. chk_reply(gproc_dist:leader_call(Req)).
  2326. call(N, Req, l) ->
  2327. chk_reply(gen_server:call({?MODULE, N}, Req));
  2328. call(undefined, Req, g) ->
  2329. %% we always call the leader
  2330. chk_reply(gproc_dist:leader_call(Req)).
  2331. chk_reply(Reply) ->
  2332. case Reply of
  2333. badarg -> ?THROW_GPROC_ERROR(badarg);
  2334. _ -> Reply
  2335. end.
  2336. cast(Msg) ->
  2337. cast(Msg, l).
  2338. cast(Msg, l) ->
  2339. gen_server:cast(?MODULE, Msg);
  2340. cast(Msg, g) ->
  2341. gproc_dist:leader_cast(Msg).
  2342. cast(N, Msg, l) ->
  2343. gen_server:cast({?MODULE, N}, Msg).
  2344. try_insert_reg({T,l,_} = Key, Val, Pid) ->
  2345. case gproc_lib:insert_reg(Key, Val, Pid, l) of
  2346. false ->
  2347. case ets:lookup(?TAB, {Key,T}) of
  2348. %% In this particular case, the lookup cannot result in
  2349. %% [{_, Waiters}], since the insert_reg/4 function would
  2350. %% have succeeded then.
  2351. [{_, Pid, _}] ->
  2352. already_registered;
  2353. [{_, OtherPid, _}] ->
  2354. case is_process_alive(OtherPid) of
  2355. true ->
  2356. false;
  2357. false ->
  2358. process_is_down(OtherPid), % may result in failover
  2359. try_insert_reg(Key, Val, Pid)
  2360. end;
  2361. [] ->
  2362. false
  2363. end;
  2364. true ->
  2365. true
  2366. end.
  2367. %% try_insert_shared({c,l,_} = Key, Val) ->
  2368. %% ets:insert_new(?TAB, [{{Key,shared}, shared, Val}, {{shared, Key}, []}]);
  2369. %% try_insert_shared({a,l,_} = Key, Val) ->
  2370. %% ets:insert_new(?TAB, [{{Key, a}, shared, Val}, {{shared, Key}, []}]).
  2371. -spec audit_process(pid()) -> ok.
  2372. audit_process(Pid) when is_pid(Pid) ->
  2373. ok = gen_server:call(gproc, {audit_process, Pid}, infinity).
  2374. nb_audit_process(Pid) when is_pid(Pid) ->
  2375. ok = gen_server:cast(gproc, {audit_process, Pid}).
  2376. -spec process_is_down(pid()) -> ok.
  2377. process_is_down(Pid) when is_pid(Pid) ->
  2378. %% delete the monitor marker
  2379. %% io:fwrite(user, "process_is_down(~p) - ~p~n", [Pid,ets:tab2list(?TAB)]),
  2380. Marker = {Pid,l},
  2381. case ets:member(?TAB, Marker) of
  2382. false ->
  2383. ok;
  2384. true ->
  2385. Revs = ets:select(?TAB, [{{{Pid,'$1'}, '$2'},
  2386. [{'==',{element,2,'$1'},l}],
  2387. [{{'$1','$2'}}]}]),
  2388. lists:foreach(
  2389. fun({{n,l,_}=K, R}) ->
  2390. Key = {K,n},
  2391. case ets:lookup(?TAB, Key) of
  2392. [{_, Pid, V}] ->
  2393. ets:delete(?TAB, Key),
  2394. opt_notify(R, K, Pid, V);
  2395. [{_, Waiters}] ->
  2396. case [W || W <- Waiters,
  2397. element(1,W) =/= Pid] of
  2398. [] ->
  2399. ets:delete(?TAB, Key);
  2400. Waiters1 ->
  2401. ets:insert(?TAB, {Key, Waiters1})
  2402. end;
  2403. [{_, OtherPid, _}] when Pid =/= OtherPid ->
  2404. case ets:lookup(?TAB, {OtherPid, K}) of
  2405. [{RK, Opts}] when is_list(Opts) ->
  2406. Opts1 = gproc_lib:remove_monitor_pid(
  2407. Opts, Pid),
  2408. ets:insert(?TAB, {RK, Opts1});
  2409. _ ->
  2410. true
  2411. end;
  2412. [] ->
  2413. true
  2414. end;
  2415. ({{c,l,C} = K, _}) ->
  2416. Key = {K, Pid},
  2417. [{_, _, Value}] = ets:lookup(?TAB, Key),
  2418. ets:delete(?TAB, Key),
  2419. gproc_lib:update_aggr_counter(l, C, -Value);
  2420. ({{r,l,Rsrc} = K, _}) ->
  2421. Key = {K, Pid},
  2422. ets:delete(?TAB, Key),
  2423. gproc_lib:decrement_resource_count(l, Rsrc);
  2424. ({{rc,l,_} = K, R}) ->
  2425. remove_aggregate(rc, K, R, Pid);
  2426. ({{a,l,_} = K, R}) ->
  2427. remove_aggregate(a, K, R, Pid);
  2428. ({{p,_,_} = K, _}) ->
  2429. ets:delete(?TAB, {K, Pid})
  2430. end, Revs),
  2431. ets:select_delete(?TAB, [{{{Pid,{'_',l,'_'}},'_'}, [], [true]}]),
  2432. ets:delete(?TAB, Marker),
  2433. ok
  2434. end.
  2435. remove_aggregate(T, K, R, Pid) ->
  2436. case ets:lookup(?TAB, {K,T}) of
  2437. [{_, Pid, V}] ->
  2438. ets:delete(?TAB, {K,T}),
  2439. opt_notify(R, K, Pid, V);
  2440. [{_, OtherPid, _}] when Pid =/= OtherPid ->
  2441. case ets:lookup(?TAB, {OtherPid, K}) of
  2442. [{RK, Opts}] when is_list(Opts) ->
  2443. Opts1 = gproc_lib:remove_monitor_pid(
  2444. Opts, Pid),
  2445. ets:insert(?TAB, {RK, Opts1});
  2446. _ ->
  2447. true
  2448. end;
  2449. [] ->
  2450. opt_notify(R, K, Pid, undefined)
  2451. end.
  2452. opt_notify(r, _, _, _) ->
  2453. ok;
  2454. opt_notify(Opts, {T,_,_} = Key, Pid, Value) ->
  2455. case gproc_lib:standbys(Opts) of
  2456. [] ->
  2457. keep_followers(Opts, Key),
  2458. gproc_lib:notify(unreg, Key, Opts);
  2459. SBs ->
  2460. case pick_standby(SBs) of
  2461. false ->
  2462. keep_followers(Opts, Key),
  2463. gproc_lib:notify(unreg, Key, Opts),
  2464. ok;
  2465. {ToPid, Ref} ->
  2466. ets:insert(?TAB, [{{Key,T}, ToPid, Value},
  2467. {{ToPid, Key},
  2468. gproc_lib:remove_monitor(
  2469. Opts, ToPid, Ref)}]),
  2470. _ = gproc_lib:remove_reverse_mapping(
  2471. {failover,ToPid}, Pid, Key),
  2472. _ = gproc_lib:ensure_monitor(ToPid, l),
  2473. ok
  2474. end
  2475. end.
  2476. keep_followers(Opts, {T,_,_} = Key) ->
  2477. case gproc_lib:followers(Opts) of
  2478. [] ->
  2479. ok;
  2480. [_|_] = F ->
  2481. ets:insert(?TAB, {{Key,T}, F})
  2482. end.
  2483. pick_standby([{Pid, Ref, standby}|T]) when node(Pid) =:= node() ->
  2484. case is_process_alive(Pid) of
  2485. true ->
  2486. {Pid, Ref};
  2487. false ->
  2488. pick_standby(T)
  2489. end;
  2490. pick_standby([_|T]) ->
  2491. pick_standby(T);
  2492. pick_standby([]) ->
  2493. false.
  2494. do_give_away({T,l,_} = K, To, Pid) when T==n; T==a; T==rc ->
  2495. Key = {K, T},
  2496. case ets:lookup(?TAB, Key) of
  2497. [{_, Pid, Value}] ->
  2498. %% Pid owns the reg; allowed to give_away
  2499. case pid_to_give_away_to(To) of
  2500. Pid ->
  2501. %% Give away to ourselves? Why not? We'll allow it,
  2502. %% but nothing needs to be done.
  2503. Pid;
  2504. ToPid when is_pid(ToPid) ->
  2505. ets:insert(?TAB, [{Key, ToPid, Value},
  2506. {{ToPid, K}, []}]),
  2507. _ = gproc_lib:remove_reverse_mapping({migrated,ToPid}, Pid, K),
  2508. _ = gproc_lib:ensure_monitor(ToPid, l),
  2509. ToPid;
  2510. undefined ->
  2511. _ = gproc_lib:remove_reg(K, Pid, unreg),
  2512. undefined
  2513. end;
  2514. _ ->
  2515. badarg
  2516. end;
  2517. do_give_away({T,l,_} = K, To, Pid) when T==c; T==p; T==r ->
  2518. Key = {K, Pid},
  2519. case ets:lookup(?TAB, Key) of
  2520. [{_, Pid, Value}] ->
  2521. case pid_to_give_away_to(To) of
  2522. ToPid when is_pid(ToPid) ->
  2523. ToKey = {K, ToPid},
  2524. case ets:member(?TAB, ToKey) of
  2525. true ->
  2526. badarg;
  2527. false ->
  2528. ets:insert(?TAB, [{ToKey, ToPid, Value},
  2529. {{ToPid, K}, []}]),
  2530. ets:delete(?TAB, {Pid, K}),
  2531. ets:delete(?TAB, Key),
  2532. _ = gproc_lib:ensure_monitor(ToPid, l),
  2533. ToPid
  2534. end;
  2535. undefined ->
  2536. _ = gproc_lib:remove_reg(K, Pid, {migrated, undefined}),
  2537. undefined
  2538. end;
  2539. _ ->
  2540. badarg
  2541. end.
  2542. pid_to_give_away_to(P) when is_pid(P), node(P) == node() ->
  2543. P;
  2544. pid_to_give_away_to({T,l,_} = Key) when T==n; T==a; T==rc ->
  2545. case ets:lookup(?TAB, {Key, T}) of
  2546. [{_, Pid, _}] ->
  2547. Pid;
  2548. _ ->
  2549. undefined
  2550. end.
  2551. create_tabs() ->
  2552. Opts = gproc_lib:valid_opts(ets_options, [{write_concurrency,true},
  2553. {read_concurrency, true}]),
  2554. case ets:info(?TAB, name) of
  2555. undefined ->
  2556. ets:new(?TAB, [ordered_set, public, named_table | Opts]);
  2557. _ ->
  2558. ok
  2559. end.
  2560. %% @hidden
  2561. init([]) ->
  2562. set_monitors(),
  2563. {ok, #state{}}.
  2564. set_monitors() ->
  2565. set_monitors(ets:select(?TAB, [{{{'$1',l}},[],['$1']}], 100)).
  2566. set_monitors('$end_of_table') ->
  2567. ok;
  2568. set_monitors({Pids, Cont}) ->
  2569. _ = [erlang:monitor(process,Pid) || Pid <- Pids],
  2570. set_monitors(ets:select(Cont)).
  2571. monitor_me() ->
  2572. case ets:insert_new(?TAB, {{self(),l}}) of
  2573. false -> true;
  2574. true ->
  2575. cast({monitor_me,self()}),
  2576. true
  2577. end.
  2578. pattern([{'_', Gs, As}], T) ->
  2579. ?l,
  2580. {HeadPat, Vs} = headpat(T, '$1', '$2', '$3'),
  2581. [{HeadPat, rewrite(Gs,Vs), rewrite(As,Vs)}];
  2582. pattern([{{A,B,C},Gs,As}], Scope) ->
  2583. ?l,
  2584. {HeadPat, Vars} = headpat(Scope, A,B,C),
  2585. [{HeadPat, rewrite(Gs,Vars), rewrite(As,Vars)}];
  2586. pattern([{Head, Gs, As}], Scope) ->
  2587. ?l,
  2588. {S, T} = get_s_t(Scope),
  2589. case is_var(Head) of
  2590. {true,_N} ->
  2591. HeadPat = {{{T,S,'_'},'_'},'_','_'},
  2592. Vs = [{Head, obj_prod()}],
  2593. %% the headpat function should somehow verify that Head is
  2594. %% consistent with Scope (or should we add a guard?)
  2595. [{HeadPat, rewrite(Gs, Vs), rewrite(As, Vs)}];
  2596. false ->
  2597. erlang:error(badarg)
  2598. end.
  2599. %% This is the expression to use in guards and the RHS to address the whole
  2600. %% object, in its logical representation.
  2601. obj_prod() ->
  2602. {{ {element,1,{element,1,'$_'}},
  2603. {element,2,'$_'},
  2604. {element,3,'$_'} }}.
  2605. obj_prod_l() ->
  2606. [ {element,1,{element,1,'$_'}},
  2607. {element,2,'$_'},
  2608. {element,3,'$_'} ].
  2609. headpat({S, T}, V1,V2,V3) ->
  2610. headpat(type(T), scope(S), V1,V2,V3);
  2611. headpat(T, V1, V2, V3) when is_atom(T) ->
  2612. headpat(type(T), l, V1, V2, V3);
  2613. headpat(_, _, _, _) -> erlang:error(badarg).
  2614. headpat(T, C, V1,V2,V3) ->
  2615. Rf = fun(Pos) ->
  2616. {element,Pos,{element,1,{element,1,'$_'}}}
  2617. end,
  2618. K2 = if T==n orelse T==a orelse T==rc -> T;
  2619. true -> '_'
  2620. end,
  2621. {Kp,Vars} = case V1 of
  2622. {Vt,Vc,Vn} ->
  2623. ?l,
  2624. {T1,Vs1} = subst(T,Vt,fun() -> Rf(1) end,[]),
  2625. {C1,Vs2} = subst(C,Vc,fun() -> Rf(2) end,Vs1),
  2626. {{T1,C1,Vn}, Vs2};
  2627. '_' ->
  2628. ?l,
  2629. {{T,C,'_'}, []};
  2630. _ ->
  2631. ?l,
  2632. case is_var(V1) of
  2633. {true,_} ->
  2634. {{T,C,V1}, [{V1, {element,1,
  2635. {element,1,'$_'}}}]};
  2636. false ->
  2637. erlang:error(badarg)
  2638. end
  2639. end,
  2640. {{{Kp,K2},V2,V3}, Vars}.
  2641. %% l(L) -> L.
  2642. subst(X, '_', _F, Vs) ->
  2643. {X, Vs};
  2644. subst(X, V, F, Vs) ->
  2645. case is_var(V) of
  2646. {true,_} ->
  2647. {X, [{V,F()}|Vs]};
  2648. false ->
  2649. {V, Vs}
  2650. end.
  2651. scope('_') -> '_';
  2652. scope(all) -> '_';
  2653. scope(global) -> g;
  2654. scope(local) -> l;
  2655. scope(S) when S==l; S==g -> S.
  2656. type('_') -> '_';
  2657. type(all) -> '_';
  2658. type(T) when T==n; T==p; T==c; T==a; T==r; T==rc -> T;
  2659. type(names) -> n;
  2660. type(props) -> p;
  2661. type(resources) -> r;
  2662. type(counters) -> c;
  2663. type(aggr_counters) -> a;
  2664. type(resource_counters) -> rc.
  2665. rev_keypat(Context) ->
  2666. {S,T} = get_s_t(Context),
  2667. {T,S,'_'}.
  2668. get_s_t({S,T}) -> {scope(S), type(T)};
  2669. get_s_t(T) when is_atom(T) ->
  2670. {scope(all), type(T)}.
  2671. is_var('$1') -> {true,1};
  2672. is_var('$2') -> {true,2};
  2673. is_var('$3') -> {true,3};
  2674. is_var('$4') -> {true,4};
  2675. is_var('$5') -> {true,5};
  2676. is_var('$6') -> {true,6};
  2677. is_var('$7') -> {true,7};
  2678. is_var('$8') -> {true,8};
  2679. is_var('$9') -> {true,9};
  2680. is_var(X) when is_atom(X) ->
  2681. case atom_to_list(X) of
  2682. "\$" ++ Tl ->
  2683. try N = list_to_integer(Tl),
  2684. {true,N}
  2685. catch
  2686. error:_ ->
  2687. false
  2688. end;
  2689. _ ->
  2690. false
  2691. end;
  2692. is_var(_) -> false.
  2693. rewrite(Gs, R) ->
  2694. [rewrite1(G, R) || G <- Gs].
  2695. rewrite1('$_', _) ->
  2696. obj_prod();
  2697. rewrite1('$$', _) ->
  2698. obj_prod_l();
  2699. rewrite1(Guard, R) when is_tuple(Guard) ->
  2700. list_to_tuple([rewrite1(G, R) || G <- tuple_to_list(Guard)]);
  2701. rewrite1(Exprs, R) when is_list(Exprs) ->
  2702. [rewrite1(E, R) || E <- Exprs];
  2703. rewrite1(V, R) when is_atom(V) ->
  2704. case is_var(V) of
  2705. {true,_N} ->
  2706. case lists:keysearch(V, 1, R) of
  2707. {value, {_, V1}} ->
  2708. V1;
  2709. false ->
  2710. V
  2711. end;
  2712. false ->
  2713. V
  2714. end;
  2715. rewrite1(Expr, _) ->
  2716. Expr.
  2717. %% @spec () -> any()
  2718. %%
  2719. %% @doc
  2720. %% @equiv table({all, all})
  2721. %% @end
  2722. table() ->
  2723. table({all, all}).
  2724. %% @spec (Context::context()) -> any()
  2725. %%
  2726. %% @doc
  2727. %% @equiv table(Context, [])
  2728. %% @end
  2729. %%
  2730. table(Context) ->
  2731. table(Context, []).
  2732. %% @spec (Context::context(), Opts) -> any()
  2733. %%
  2734. %% @doc QLC table generator for the gproc registry.
  2735. %% Context specifies which subset of the registry should be queried.
  2736. %% See [http://www.erlang.org/doc/man/qlc.html].
  2737. %%
  2738. %% NOTE: By default, the gproc table generator will not filter out entries
  2739. %% belonging to processes that have just died, but which have yet to be cleared
  2740. %% out of the registry. Use the option `check_pids' (or `{check_pids, true}')
  2741. %% if you want to filter out dead entries already in the query. There will be
  2742. %% some overhead associated with doing so, and given that the process monitoring
  2743. %% is asynchronous, there can never be any guarantee that there are no dead
  2744. %% entries in the list by the time your program processes it.
  2745. %%
  2746. %% @end
  2747. table(Context, Opts) ->
  2748. Ctxt = {_, Type} = get_s_t(Context),
  2749. [Traverse, NObjs] = [proplists:get_value(K,Opts,Def) ||
  2750. {K,Def} <- [{traverse,select}, {n_objects,100}]],
  2751. CheckPids = proplists:get_bool(check_pids, Opts),
  2752. TF = case Traverse of
  2753. first_next ->
  2754. fun() -> qlc_next(Ctxt, first(Ctxt), CheckPids) end;
  2755. last_prev -> fun() -> qlc_prev(Ctxt, last(Ctxt), CheckPids) end;
  2756. select ->
  2757. fun(MS) -> qlc_select(
  2758. CheckPids,
  2759. select(Ctxt, wrap_qlc_ms_prod(CheckPids, MS),
  2760. NObjs))
  2761. end;
  2762. {select,MS} ->
  2763. fun() -> qlc_select(
  2764. CheckPids,
  2765. select(Ctxt, wrap_qlc_ms_prod(CheckPids, MS),
  2766. NObjs))
  2767. end;
  2768. _ ->
  2769. erlang:error(badarg, [Ctxt,Opts])
  2770. end,
  2771. InfoFun = fun(indices) -> [2];
  2772. (is_unique_objects) -> is_unique(Type);
  2773. (keypos) -> 1;
  2774. (is_sorted_key) -> true;
  2775. (num_of_objects) ->
  2776. %% this is just a guesstimate.
  2777. trunc(ets:info(?TAB,size) / 2.5)
  2778. end,
  2779. LookupFun =
  2780. case Traverse of
  2781. {select, _MS} -> undefined;
  2782. _ -> fun(Pos, Ks) -> qlc_lookup(Ctxt, Pos, Ks, CheckPids) end
  2783. end,
  2784. qlc:table(TF, [{info_fun, InfoFun},
  2785. {lookup_fun, LookupFun}] ++ [{K,V} || {K,V} <- Opts,
  2786. K =/= traverse,
  2787. K =/= n_objects]).
  2788. wrap_qlc_ms_prod(false, Pats) ->
  2789. Pats;
  2790. wrap_qlc_ms_prod(true, Pats) ->
  2791. [ wrap_qlc_ms_prod_(P) || P <- Pats ].
  2792. wrap_qlc_ms_prod_({H, Gs, [P]}) ->
  2793. {H, Gs, [{{ {element, 2, '$_'}, P }}]}.
  2794. qlc_lookup(_Scope, 1, Keys, Check) ->
  2795. lists:flatmap(
  2796. fun(Key) ->
  2797. remove_dead(
  2798. Check,
  2799. ets:select(?TAB, [{ {{Key,'_'},'_','_'}, [],
  2800. [{{ {element,1,{element,1,'$_'}},
  2801. {element,2,'$_'},
  2802. {element,3,'$_'} }}] }]))
  2803. end, Keys);
  2804. qlc_lookup(Scope, 2, Pids, Check) ->
  2805. lists:flatmap(fun(Pid) ->
  2806. qlc_lookup_pid(Pid, Scope, Check)
  2807. end, Pids).
  2808. remove_dead(false, Objs) ->
  2809. Objs;
  2810. remove_dead(true, Objs) ->
  2811. [ Reg || {_, Pid, _} = Reg <- Objs,
  2812. not ?PID_IS_DEAD(Pid) ].
  2813. %% While it may seem obsessive not to do the sensible pid liveness check here
  2814. %% every time, we make it optional for consistency; this way, we can devise
  2815. %% a test case that verifies the difference between having the option and not.
  2816. qlc_lookup_pid(Pid, Scope, Check) ->
  2817. case Check andalso ?PID_IS_DEAD(Pid) of
  2818. true ->
  2819. [];
  2820. false ->
  2821. Found =
  2822. ets:select(?TAB, [{{{Pid, rev_keypat(Scope)}, '_'},
  2823. [], ['$_']}]),
  2824. lists:flatmap(
  2825. fun({{_,{T,_,_}=K}, _}) ->
  2826. K2 = if T==n orelse T==a orelse T==rc -> T;
  2827. true -> Pid
  2828. end,
  2829. case ets:lookup(?TAB, {K,K2}) of
  2830. [{{Key,_},_,Value}] ->
  2831. [{Key, Pid, Value}];
  2832. [] ->
  2833. []
  2834. end
  2835. end, Found)
  2836. end.
  2837. qlc_next(_, '$end_of_table', _) -> [];
  2838. qlc_next(Scope, K, Check) ->
  2839. case ets:lookup(?TAB, K) of
  2840. [{{Key,_}, Pid, V}] ->
  2841. case Check andalso ?PID_IS_DEAD(Pid) of
  2842. true ->
  2843. qlc_next(Scope, next(Scope, K), Check);
  2844. false ->
  2845. [{Key,Pid,V}] ++ fun() ->
  2846. qlc_next(Scope, next(Scope, K),
  2847. Check)
  2848. end
  2849. end;
  2850. [] ->
  2851. qlc_next(Scope, next(Scope, K), Check)
  2852. end.
  2853. qlc_prev(_, '$end_of_table', _) -> [];
  2854. qlc_prev(Scope, K, Check) ->
  2855. case ets:lookup(?TAB, K) of
  2856. [{{Key,_},Pid,V}] ->
  2857. case Check andalso ?PID_IS_DEAD(Pid) of
  2858. true ->
  2859. qlc_prev(Scope, prev(Scope, K), Check);
  2860. false ->
  2861. [{Key,Pid,V}] ++ fun() ->
  2862. qlc_prev(Scope, prev(Scope, K),
  2863. Check)
  2864. end
  2865. end;
  2866. [] ->
  2867. qlc_prev(Scope, prev(Scope, K), Check)
  2868. end.
  2869. qlc_select(_, '$end_of_table') ->
  2870. [];
  2871. qlc_select(true, {Objects, Cont}) ->
  2872. case [O || {Pid,O} <- Objects,
  2873. not ?PID_IS_DEAD(Pid)] of
  2874. [] ->
  2875. %% re-run search
  2876. qlc_select(true, ets:select(Cont));
  2877. Found ->
  2878. Found ++ fun() -> qlc_select(true, ets:select(Cont)) end
  2879. end;
  2880. qlc_select(false, {Objects, Cont}) ->
  2881. Objects ++ fun() -> qlc_select(false, ets:select(Cont)) end.
  2882. is_unique(n) -> true;
  2883. is_unique(a) -> true;
  2884. is_unique(_) -> false.
  2885. is_regged([{_, _, _}]) ->
  2886. true;
  2887. is_regged(_) ->
  2888. false.