Generated on 2009-08-09 21:22:55 with etap 0.3.4.
| Name | Total lines | Lines of code | Total coverage | Code coverage | ||||
| couch_ref_counter | ?? | ?? | ?? |
|
....1 % Licensed under the Apache License, Version 2.0 (the "License"); you may not ....2 % use this file except in compliance with the License. You may obtain a copy of ....3 % the License at ....4 % ....5 % http://www.apache.org/licenses/LICENSE-2.0 ....6 % ....7 % Unless required by applicable law or agreed to in writing, software ....8 % distributed under the License is distributed on an "AS IS" BASIS, WITHOUT ....9 % WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the ...10 % License for the specific language governing permissions and limitations under ...11 % the License. ...12 ...13 -module(couch_ref_counter). ...14 -behaviour(gen_server). ...15 ...16 -export([start/1, init/1, terminate/2, handle_call/3, handle_cast/2, code_change/3, handle_info/2]). ...17 -export([drop/1,drop/2,add/1,add/2,count/1]). ...18 ...19 start(ChildProcs) -> ...20 gen_server:start(couch_ref_counter, {self(), ChildProcs}, []). ...21 ...22 ...23 drop(RefCounterPid) -> ...24 drop(RefCounterPid, self()). ...25 ...26 drop(RefCounterPid, Pid) -> ...27 gen_server:cast(RefCounterPid, {drop, Pid}). ...28 ...29 ...30 add(RefCounterPid) -> ...31 add(RefCounterPid, self()). ...32 ...33 add(RefCounterPid, Pid) -> ...34 gen_server:call(RefCounterPid, {add, Pid}). ...35 ...36 count(RefCounterPid) -> ...37 gen_server:call(RefCounterPid, count). ...38 ...39 % server functions ...40 ...41 -record(srv, ...42 { ...43 referrers=dict:new() % a dict of each ref counting proc. ...44 }). ...45 ...46 init({Pid, ChildProcs}) -> ...47 [link(ChildProc) || ChildProc <- ChildProcs], ...48 Referrers = dict:from_list([{Pid, {erlang:monitor(process, Pid), 1}}]), ...49 {ok, #srv{referrers=Referrers}}. ...50 ...51 ...52 terminate(Reason, _Srv) -> ...53 couch_util:terminate_linked(Reason), ...54 ok. ...55 ...56 ...57 handle_call({add, Pid},_From, #srv{referrers=Referrers}=Srv) -> ...58 Referrers2 = ...59 case dict:find(Pid, Referrers) of ...60 error -> ...61 dict:store(Pid, {erlang:monitor(process, Pid), 1}, Referrers); ...62 {ok, {MonRef, RefCnt}} -> ...63 dict:store(Pid, {MonRef, RefCnt + 1}, Referrers) ...64 end, ...65 {reply, ok, Srv#srv{referrers=Referrers2}}; ...66 handle_call(count, _From, Srv) -> ...67 {monitors, Monitors} = process_info(self(), monitors), ...68 {reply, length(Monitors), Srv}. ...69 ...70 ...71 handle_cast({drop, Pid}, #srv{referrers=Referrers}=Srv) -> ...72 Referrers2 = ...73 case dict:find(Pid, Referrers) of ...74 {ok, {MonRef, 1}} -> ...75 erlang:demonitor(MonRef, [flush]), ...76 dict:erase(Pid, Referrers); ...77 {ok, {MonRef, Num}} -> ...78 dict:store(Pid, {MonRef, Num-1}, Referrers); ...79 error -> ...80 Referrers ...81 end, ...82 maybe_close_async(Srv#srv{referrers=Referrers2}). ...83 ...84 ...85 code_change(_OldVsn, State, _Extra) -> ...86 {ok, State}. ...87 ...88 handle_info({'DOWN', MonRef, _, Pid, _}, #srv{referrers=Referrers}=Srv) -> ...89 {ok, {MonRef, _RefCount}} = dict:find(Pid, Referrers), ...90 maybe_close_async(Srv#srv{referrers=dict:erase(Pid, Referrers)}). ...91 ...92 ...93 should_close() -> ...94 case process_info(self(), monitors) of ...95 {monitors, []} -> ...96 true; ...97 _ -> ...98 false ...99 end. ..100 ..101 maybe_close_async(Srv) -> ..102 case should_close() of ..103 true -> ..104 {stop,normal,Srv}; ..105 false -> ..106 {noreply,Srv} ..107 end.
Generated using etap 0.3.4.