anchor.diff:  get_timer2(Ref, [H | T]) when is_record(H, siptimer) ->
       get_timer2(Ref, T).
   
  -
  +%%--------------------------------------------------------------------
  +%% Function: get_timers_appsignal_matching(AppSignal, TimerList)
  +%%           AppSignal  = term()
  +%%           TimerList  = siptimerlist record()
  +%% Descrip.: Locate all timers in TimerList which have their
  +%%           'appsignal' element matching AppSignal.
  +%% Returns : list() of siptimer record()
  +%%--------------------------------------------------------------------
   get_timers_appsignal_matching(AppSignal, TimerList) when is_record(TimerList, siptimerlist) ->
  -    make_siptimerlist(get_timers_something_matching2(appsignal, AppSignal, TimerList#siptimerlist.list, [])).
  -
  -
  +    get_timers_appsignal_matching2(AppSignal, TimerList#siptimerlist.list, []).
  +
  +get_timers_appsignal_matching2(Value, [#siptimer{appsignal = Value}=H | T], Res) ->
  +    get_timers_appsignal_matching2(Value, T, [H | Res]);
  +get_timers_appsignal_matching2(Value, [H | T], Res) when is_record(H, siptimer) ->
  +    get_timers_appsignal_matching2(Value, T, Res);
  +get_timers_appsignal_matching2(_Value, [], Res) ->
  +    lists:reverse(Res).
  +
  +
  +%%--------------------------------------------------------------------
  +%% Function: extract(Values, SipTimer)
  +%%           Values = list() of atom(), ref | timeout | description |
  +%%                    starttime | appsignal
  +%%           TimerList  = siptimerlist record()
  +%% Descrip.: Extract elements from a siptimer record().
  +%% Returns : list() of term()
  +%%--------------------------------------------------------------------
   extract(Values, SipTimer) when is_record(SipTimer, siptimer) ->
       extract(Values, SipTimer, []).
   
   extract([], SipTimer, Res) when is_record(SipTimer, siptimer) ->
  -    Res;
  +    lists:reverse(Res);
   extract([ref | T], SipTimer, Res) when is_record(SipTimer, siptimer) ->
  -    extract(T, SipTimer, lists:append(Res, [SipTimer#siptimer.ref]));
  +    extract(T, SipTimer, [SipTimer#siptimer.ref | Res]);
   extract([timeout | T], SipTimer, Res) when is_record(SipTimer, siptimer) ->
  -    extract(T, SipTimer, lists:append(Res, [SipTimer#siptimer.timeout]));
  +    extract(T, SipTimer, [SipTimer#siptimer.timeout | Res]);
   extract([description | T], SipTimer, Res) when is_record(SipTimer, siptimer) ->
  -    extract(T, SipTimer, lists:append(Res, [SipTimer#siptimer.description]));
  +    extract(T, SipTimer, [SipTimer#siptimer.description | Res]);
   extract([starttime | T], SipTimer, Res) when is_record(SipTimer, siptimer) ->
  -    extract(T, SipTimer, lists:append(Res, [SipTimer#siptimer.starttime]));
  +    extract(T, SipTimer, [SipTimer#siptimer.starttime | Res]);
   extract([appsignal | T], SipTimer, Res) when is_record(SipTimer, siptimer) ->
  -    extract(T, SipTimer, lists:append(Res, [SipTimer#siptimer.appsignal])).
  -
  -cancel_timer(SipTimer, TimerList) when is_record(SipTimer, siptimer), is_record(TimerList, siptimerlist) ->
  -    Timer = SipTimer#siptimer.timer,
  -    Ref = SipTimer#siptimer.ref,
  -    Descr = SipTimer#siptimer.description,
  +    extract(T, SipTimer, [SipTimer#siptimer.appsignal | Res]).
  +
  +%%--------------------------------------------------------------------
  +%% Function: cancel_timers(Timers, TimerList)
  +%%           Timers    = list() of siptimer record()
  +%%           TimerList = siptimerlist record() | none
  +%% Descrip.: Cancel a siptimer, return a new TimerList without the
  +%%           cancelled siptimer.
  +%% Returns : NewTimerList = siptimerlist record()
  +%%--------------------------------------------------------------------
  +cancel_timers([H | T], TimerList) when is_record(H, siptimer), is_record(TimerList, siptimerlist) ->
  +    Timer = H#siptimer.timer,
  +    Ref = H#siptimer.ref,
  +    Descr = H#siptimer.description,
       logger:log(debug, "Siptimer: Cancelling timer ~p:~p", [Ref, Descr]),
  -    timer:cancel(Timer),
  +    case timer:cancel(Timer) of
  +	{ok, cancel} -> ok;
  +	{error, Reason} ->
  +	    logger:log(error, "Siptimer: Warning: Cancel timer ~p:~p failed : ~p",
  +		       [Ref, Descr, Reason])
  +    end,
       remove_queued_result({siptimer, Ref, Descr}),
  -    make_siptimerlist(del_ref(Ref, TimerList#siptimerlist.list)).
  +    NewTimerList = make_siptimerlist( del_ref(Ref, TimerList#siptimerlist.list) ),
  +    cancel_timers(T, NewTimerList);
  +cancel_timers([], TimerList) when is_record(TimerList, siptimerlist) ->
  +    TimerList.
  +
  +%%--------------------------------------------------------------------
  +%% Function: cancel_all_timers(TimerList)
  +%%           TimerList = siptimerlist record() | none
  +%% Descrip.: Cancel all siptimers in TimerList.
  +%% Returns : EmptyList = siptimerlist record()
  +%%--------------------------------------------------------------------
  +cancel_all_timers(TimerList) when is_record(TimerList, siptimerlist) ->
  +    EmptyList = empty(),
  +    logger:log(debug, "Siptimer: Cancelling all timers :"),
  +    cancel_timers(TimerList#siptimerlist.list, EmptyList),
  +    EmptyList.
  +
  +%%--------------------------------------------------------------------
  +%% Function: cancel_timers_with_appsignal(AppSignal, TimerList)
  +%%           AppSignal = term(), appsignal to match on
  +%%           TimerList = siptimerlist record() | none
  +%% Descrip.: Cancel all siptimers in TimerList that has an appsignal
  +%%           matching AppSignal.
  +%% Returns : NewTimerList = siptimerlist record()
  +%%--------------------------------------------------------------------
  +cancel_timers_with_appsignal(AppSignal, TimerList) when is_record(TimerList, siptimerlist) ->
  +    case get_timers_appsignal_matching(AppSignal, TimerList) of
  +	[] ->
  +	    %%    logger:log(debug, "Siptimer: No timers with AppSignal ~p found in TimerList :~n~p",
  +	    %%	       [AppSignal, debugfriendly(TimerList)]),
  +	    TimerList;
  +	CancelTimers when is_list(CancelTimers) ->
  +	    logger:log(debug, "Siptimer: Cancelling all timers with AppSignal ~p :", [AppSignal]),
  +	    cancel_timers(CancelTimers, TimerList)
  +    end.
  +
  +debugfriendly(TimerList) when is_record(TimerList, siptimerlist) ->
  +    debugfriendly2(TimerList#siptimerlist.list, []).
  +
  +debugfriendly2([H | T], Res) when is_record(H, siptimer) ->
  +    RefStr = io_lib:format("~p", [H#siptimer.ref]),
  +    Descr = H#siptimer.description,
  +    SignalStr = io_lib:format("~p", [H#siptimer.appsignal]),
  +    Str = lists:concat([RefStr, ":", Descr, " -> ", SignalStr]),
  +    debugfriendly2(T, [Str | Res]);
  +debugfriendly2([], Res) ->
  +    lists:reverse(Res).
  +
  +%%--------------------------------------------------------------------
  +%% Function: timeout2str(Timeout)
  +%%           Timeout = integer(), milliseconds
  +%% Descrip.: Give string second representation of Timeout.
  +%% Returns : TStr = string()
  +%%--------------------------------------------------------------------
  +timeout2str(500) ->
  +    "0.5";
  +timeout2str(Timeout) ->
  +    integer_to_list(Timeout div 1000).
  +
  +%%--------------------------------------------------------------------
  +%% Function: get_length(TimerList)
  +%%           TimerList = siptimerlist record()
  +%% Descrip.: Return the length of the list of siptimers contained in
  +%%           the siptimerlist record().
  +%% Returns : Len = integer()
  +%%--------------------------------------------------------------------
  +get_length(TimerList) when is_record(TimerList, siptimerlist) ->
  +    length(TimerList#siptimerlist.list).
  +
  +
  +%%====================================================================
  +%% Internal functions
  +%%====================================================================
  +
  +make_siptimerlist([]) ->
  +    #siptimerlist{list=[]};
  +make_siptimerlist(In) ->
  +    #siptimerlist{list=make_siptimerlist2(In, [])}.
  +
  +%% make_siptimerlist2/2 - part of make_siptimerlist/1.
  +%% Make sure all elements are siptimer record().
  +%% Returns : list() of siptimer record()
  +make_siptimerlist2([H | T], Res) when is_record(H, siptimer) ->
  +    make_siptimerlist2(T, [H | Res]);
  +make_siptimerlist2([], Res) ->
  +    lists:reverse(Res).
   
   %% Receive all messages matching Signal from this processes mailbox. When there
   %% are no more signals matching Signal, return ok. This is to remove any signals
  
positive.code: 	 reset_timers/2,
  	 get_timer/2,
  	 get_timers_appsignal_matching/2,
  	 cancel_timer/2,
  	 cancel_all_timers/1,
  	 cancel_timers/2,
  	 cancel_timers_with_appsignal/2,
  	 stop_timers/1,
  	 debugfriendly/1,
  	 timeout2str/1,
  	 extract/2,
  	 empty/0,
  	 get_length/1
  	]).
  
  %%--------------------------------------------------------------------
  %% Records
  %%--------------------------------------------------------------------
  -record(siptimerlist, {list}).
  -record(siptimer, {ref, timer, timeout, description, starttime, appsignal}).
  
  %%====================================================================
  %% External functions
  %%====================================================================
  add_timer(0, _, _, TimerList) when is_record(TimerList, siptimerlist) ->
      TimerList;
  add_timer(Timeout, Description, AppSignal, TimerList) when is_record(TimerList, siptimerlist) ->
      Ref = make_ref(),
      {ok, NewTimerRef} = timer:send_after(Timeout, {siptimer, Ref, Description}),
      TimeoutStr = timeout2str(Timeout),
      logger:log(debug, "Siptimer: Set up timer ~p:~p, ~s seconds", [Ref, Description, TimeoutStr]),
      NewSipTimer = #siptimer{ref=Ref, timer=NewTimerRef, timeout=Timeout, description=Description, starttime=util:timestamp(), appsignal=AppSignal},
      make_siptimerlist(lists:append(TimerList#siptimerlist.list, [NewSipTimer])).
  
  empty() ->
      make_siptimerlist([]).
  
  reset_timers(ResetList, TimerList) when is_record(ResetList, siptimerlist), is_record(TimerList, siptimerlist) ->
      reset_timers2(ResetList#siptimerlist.list, TimerList).
  
  reset_timers2([], TimerList) ->
      TimerList;
  reset_timers2([H | _T], TimerList) when is_record(H, siptimer), is_record(TimerList, siptimerlist) ->
      Ref = H#siptimer.ref,
      case get_timer(Ref, TimerList) of
          none ->
  	    Description = H#siptimer.description,
  	    logger:log(error, "Siptimer: Can't reset timer ~p:~p gone from list :~n~p~n", [Ref, Description, TimerList]),
  	    TimerList;
          ThisTimer ->
              Description = ThisTimer#siptimer.description,
  	    timer:cancel(ThisTimer#siptimer.timer),
  	    remove_queued_result({siptimer, Ref, Description}),
              Timeout = ThisTimer#siptimer.timeout,
  	    OldStarttime = ThisTimer#siptimer.starttime,
  	    SecondsLeft = (OldStarttime + (Timeout div 1000)) - util:timestamp(),
  	    logger:log(debug, "Siptimer: Timer ~p:~p was about to fire in ~p seconds, resetting with new timeout, ~s seconds",
  			[Ref, Description, SecondsLeft, timeout2str(Timeout)]),
  	    {ok, NewTimerRef} = timer:send_after(Timeout, {siptimer, Ref, Description}),
  	    update_timer(ThisTimer#siptimer{timer=NewTimerRef}, TimerList)
      end.
  
  revive_timer(SipTimer, NewTimeout, TimerList) when is_record(SipTimer, siptimer), is_record(TimerList, siptimerlist) ->
      Ref = SipTimer#siptimer.ref,
      case get_timer(Ref, TimerList) of
          none ->
  	    Description = SipTimer#siptimer.description,
  	    logger:log(error, "Siptimer: Can't revive timer ~p:~p gone from list :~n~p~n", [Ref, Description, TimerList]),
  	    TimerList;
          ThisTimer ->
              Description = ThisTimer#siptimer.description,
  	    logger:log(debug, "Siptimer: Reviving timer ~p:~p with new timeout, ~s seconds", [Ref, Description, timeout2str(NewTimeout)]),
  	    {ok, NewTimerRef} = timer:send_after(NewTimeout, {siptimer, Ref, Description}),
  	    update_timer(ThisTimer#siptimer{timeout=NewTimeout,timer=NewTimerRef}, TimerList)
      end.
  	
  update_timer(SipTimer, TList) when is_record(SipTimer, siptimer), is_record(TList, siptimerlist) ->
      Ref = SipTimer#siptimer.ref,
      make_siptimerlist(update_timer2(Ref, SipTimer, TList#siptimerlist.list, TList)).
      
  update_timer2(Ref, _, [], TList) ->
      logger:log(error, "Siptimer: Asked to update a timer, but I can't find it"),
      logger:log(debug, "Siptimer: Asked to update a timer with ref=~p, but I can't find it in list :~n~p",
  		[Ref, debugfriendly(TList)]),
      [];
  update_timer2(Ref, NewT, [H | T], _TList) when is_record(H, siptimer), H#siptimer.ref == Ref ->
      [NewT | T];
  update_timer2(Ref, NewT, [H | T], TList) when is_record(H, siptimer) ->
      lists:append([H], update_timer2(Ref, NewT, T, TList)).
  
  
  get_timer(Ref, TimerList) when is_record(TimerList, siptimerlist) ->
      get_timer2(Ref, TimerList#siptimerlist.list).
  
  
negative.code: %%%-------------------------------------------------------------------
  %%% File     : siptimer.erl
  %%% Author   : Fredrik Thulin <ft@it.su.se>
  %%% Descrip. : Module to manage timers, for use in client and server
  %%%            transactions. Make it easier to cancel timers and
  %%%            revive them when we get provisional responses etc.
  