diff options
Diffstat (limited to 'lib/cosTime/src/CosTimerEvent_TimerEventHandler_impl.erl')
-rw-r--r-- | lib/cosTime/src/CosTimerEvent_TimerEventHandler_impl.erl | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/lib/cosTime/src/CosTimerEvent_TimerEventHandler_impl.erl b/lib/cosTime/src/CosTimerEvent_TimerEventHandler_impl.erl new file mode 100644 index 0000000000..5885691e87 --- /dev/null +++ b/lib/cosTime/src/CosTimerEvent_TimerEventHandler_impl.erl @@ -0,0 +1,304 @@ +%%-------------------------------------------------------------------- +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% +%%---------------------------------------------------------------------- +%% File : CosTimerEvent_TimerEventHandler_impl.erl +%% Purpose : +%%---------------------------------------------------------------------- + +-module('CosTimerEvent_TimerEventHandler_impl'). + +%%--------------- INCLUDES ----------------------------------- +-include("cosTimeApp.hrl"). + + +%%--------------- EXPORTS ------------------------------------ +%%--------------- External ----------------------------------- +%% Attributes (external) +-export(['_get_status'/2]). +%% Interface functions +-export([time_set/2, set_timer/4]). +-export([cancel_timer/2, set_data/3]). + +%%--------------- gen_server specific exports ---------------- +-export([handle_info/2, code_change/3]). +-export([init/1, terminate/2]). + + +%% Data structures +-record(state, {parent, + parentPid, + event, + status = 'ESTimeCleared', + timer, + time, + timeObj, + myType, + pushConsumer, + uto}). +%% Data structures constructors +-define(get_InitState(P,PP,E,PC,TO), + #state{parent=P, + parentPid=PP, + event=E, + pushConsumer=PC, + timeObj=TO}). + +%% Data structures selectors +-define(get_Status(S), S#state.status). +-define(get_ParentPid(S), S#state.parentPid). +-define(get_Parent(S), S#state.parent). +-define(get_Event(S), S#state.event). +-define(get_Timer(S), S#state.timer). +-define(get_Time(S), S#state.time). +-define(get_TimeObj(S), S#state.timeObj). +-define(get_MyType(S), S#state.myType). +-define(get_PushConsumer(S), S#state.pushConsumer). +-define(get_Uto(S), S#state.uto). + +%% Data structures modifiers +-define(set_Status(S,V), S#state{status=V}). +-define(set_ParentPid(S,PP), S#state{parentPid=PP}). +-define(set_Parent(S,P), S#state{parent=P}). +-define(set_Event(S,E), S#state{event=E}). +-define(set_Timer(S,T), S#state{timer=T}). +-define(set_Time(S,T), S#state{time=T}). +-define(set_MyType(S,Ty), S#state{myType=Ty}). +-define(set_PushConsumer(S,P), S#state{pushConsumer=P}). +-define(set_Uto(S,U,Type), S#state{uto=U, myType=Type}). +-define(set_TimeData(S,U,Ty,Ti),S#state{uto=U, myType=Ty, time=Ti}). + +%% MISC +-define(not_Cancelled(S), S#state.status =/= 'ESTimeCleared'). +-define(is_TimeSet(S), S#state.status == 'ESTimeSet'). +-define(is_UtoSet(S), S#state.uto =/= undefined). +-define(is_NotAbsolute(S), S#state.myType =/= 'TTAbsolute'). + +%%-----------------------------------------------------------% +%% function : handle_info, code_change +%% Arguments: +%% Returns : +%% Effect : Functions demanded by the gen_server module. +%%------------------------------------------------------------ + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +handle_info(Info, State) -> + ?debug_print("INFO: ~p~n", [Info]), + case Info of + {'EXIT', Pid, _Reason} when Pid == ?get_ParentPid(State) -> + ?debug_print("PARENT TERMINATED with reason: ~p~n",[_Reason]), + {noreply, State}; + oe_event when ?not_Cancelled(State) -> + %% Push event + case catch 'CosEventComm_PushConsumer':push(?get_PushConsumer(State), + ?get_Event(State)) of + ok -> + ?debug_print("PUSHED: ~p~n", [?get_Event(State)]), + {noreply, ?set_Status(State, 'ESTriggered')}; + _Other-> + ?debug_print("FAILED PUSH: ~p ~p~n", [?get_Event(State), _Other]), + {noreply, ?set_Status(State, 'ESFailedTrigger')} + end; + oe_periodic_event when ?not_Cancelled(State) -> + %% Push event + catch 'CosEventComm_PushConsumer':push(?get_PushConsumer(State), + ?get_Event(State)), + {noreply, State}; + _ -> + {noreply, State} + end. + +%%----------------------------------------------------------% +%% function : init, terminate +%% Arguments: +%%----------------------------------------------------------- + +init([Parent, ParentPid, PushConsumer, Event, TimeObj]) -> + process_flag(trap_exit, true), + {ok, ?get_InitState(Parent, ParentPid, Event, PushConsumer, TimeObj)}. + +terminate(_Reason, State) -> + clear_timer(State), + ok. + +%%----------------------------------------------------------- +%%------------------------ attributes ----------------------- +%%----------------------------------------------------------- +%%----------------------------------------------------------% +%% Attribute: '_get_status' +%% Type : readonly +%% Returns : 'ESTimeSet' | 'ESTimeCleared' | 'ESTriggered' | +%% 'ESFailedTrigger' +%%----------------------------------------------------------- +'_get_status'(_OE_THIS, State) -> + {reply, ?get_Status(State), State}. + +%%----------------------------------------------------------- +%%------- Exported external functions ----------------------- +%%----------------------------------------------------------- +%%----------------------------------------------------------% +%% function : time_set +%% Arguments: - +%% Returns : {boolean(), CosTime::UTO} +%%----------------------------------------------------------- +time_set(_OE_THIS, State) when ?is_UtoSet(State) -> + {reply, {?is_TimeSet(State), ?get_Uto(State)}, State}; +time_set(_OE_THIS, State) -> + Utc = #'TimeBase_UtcT'{time=0, inacclo = 0,inacchi = 0, tdf = 0}, + {reply, + {?is_TimeSet(State), + 'CosTime_UTO':oe_create([Utc, ?get_TimeObj(State)], [{pseudo,true}|?CREATE_OPTS])}, + State}. + + +%%----------------------------------------------------------- +%% function : set_timer +%% Arguments: TimeType - 'TTAbsolute' | 'TTRelative' | 'TTPeriodic' +%% TriggerTime - CosTime::UTO +%% Returns : ok +%%----------------------------------------------------------- +set_timer(_OE_THIS, State, 'TTAbsolute', TriggerTime) -> + NewState = clear_timer(State), + ?time_TypeCheck(TriggerTime, 'CosTime_UTO'), + case catch {'CosTime_UTO':'_get_time'(TriggerTime), + 'CosTime_UTO':'_get_time'( + 'CosTime_TimeService':universal_time(?get_TimeObj(State)))} of + {Time, CurrentTime} when is_integer(Time) andalso is_integer(CurrentTime) andalso + Time > CurrentTime -> + %% Set a timer to send a message in (Time-CurrentTime)*10^-7 secs. + case timer:send_after(?convert_TimeT2TimerT(Time-CurrentTime), oe_event) of + {ok, TRef} -> + NewState1 = ?set_Timer(NewState, TRef), + NewState2 = ?set_Uto(NewState1, TriggerTime, 'TTAbsolute'), + ?debug_print("TIMER SET: ~p~n", [?convert_TimeT2TimerT(Time-CurrentTime)]), + {reply, ok, ?set_Status(NewState2, 'ESTimeSet')}; + _-> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end; + {Time, CurrentTime} when is_integer(Time) andalso is_integer(CurrentTime) -> + corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}); + _-> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end; +set_timer(_OE_THIS, State, 'TTRelative', TriggerTime) -> + NewState = clear_timer(State), + ?time_TypeCheck(TriggerTime, 'CosTime_UTO'), + case catch {'CosTime_UTO':'_get_time'(TriggerTime), ?get_Time(State)} of + {0,OldTime} when ?is_NotAbsolute(NewState) andalso is_integer(OldTime) -> + %% Set a timer to send a message within Time*10^-7 secs + case timer:send_after(OldTime, oe_event) of + {ok, TRef} -> + NewState1 = ?set_Timer(NewState, TRef), + NewState2 = ?set_Uto(NewState1, TriggerTime, 'TTRelative'), + ?debug_print("TIMER SET: ~p~n", [?convert_TimeT2TimerT(OldTime)]), + {reply, ok, ?set_Status(NewState2, 'ESTimeSet')}; + _-> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end; + {UtoTime,_} when is_integer(UtoTime) -> + %% Set a timer to send a message within Time*10^-7 secs + Time = ?convert_TimeT2TimerT(UtoTime), + case timer:send_after(Time, oe_event) of + {ok, TRef} -> + NewState1 = ?set_Timer(NewState, TRef), + NewState2 = ?set_TimeData(NewState1, TriggerTime, + 'TTRelative', Time), + ?debug_print("TIMER SET: ~p~n", [?convert_TimeT2TimerT(Time)]), + {reply, ok, ?set_Status(NewState2, 'ESTimeSet')}; + _-> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end; + + _-> + {reply, {'EXCEPTION', #'BAD_PARAM'{completion_status=?COMPLETED_NO}}, NewState} + end; +set_timer(_OE_THIS, State, 'TTPeriodic', TriggerTime) -> + NewState = clear_timer(State), + ?time_TypeCheck(TriggerTime, 'CosTime_UTO'), + case catch {'CosTime_UTO':'_get_time'(TriggerTime), ?get_Time(State)} of + {0,OldTime} when ?is_NotAbsolute(NewState) andalso is_integer(OldTime) -> + %% Set a timer to send a message within Time*10^-7 secs + case timer:send_interval(OldTime, oe_periodic_event) of + {ok, TRef} -> + NewState1 = ?set_Timer(NewState, TRef), + NewState2 = ?set_Uto(NewState1, TriggerTime, 'TTPeriodic'), + ?debug_print("TIMER SET: ~p~n", [?convert_TimeT2TimerT(OldTime)]), + {reply, ok, ?set_Status(NewState2, 'ESTimeSet')}; + _-> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end; + {UtoTime,_} when is_integer(UtoTime) -> + %% Set a timer to send a message within Time*10^-7 secs + Time = ?convert_TimeT2TimerT(UtoTime), + case timer:send_interval(Time, oe_periodic_event) of + {ok, TRef} -> + NewState1 = ?set_Timer(NewState, TRef), + NewState2 = ?set_TimeData(NewState1, TriggerTime, + 'TTPeriodic', Time), + ?debug_print("TIMER SET: ~p~n", [?convert_TimeT2TimerT(Time)]), + {reply, ok, ?set_Status(NewState2, 'ESTimeSet')}; + _-> + corba:raise(#'INTERNAL'{completion_status=?COMPLETED_NO}) + end; + + _-> + {reply, {'EXCEPTION', #'BAD_PARAM'{completion_status=?COMPLETED_NO}}, NewState} + end; +set_timer(_OE_THIS, _State, _, _) -> + corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}). + +%%----------------------------------------------------------% +%% function : cancel_timer +%% Arguments: - +%% Returns : boolean() +%%----------------------------------------------------------- +cancel_timer(_OE_THIS, State) -> + NewState=clear_timer(State), + case ?get_Status(NewState) of + 'ESTriggered' -> + {reply, false, NewState}; + 'ESFailedTrigger' -> + {reply, false, NewState}; + _ -> + {reply, true, ?set_Status(NewState, 'ESTimeCleared')} + end. + +%%----------------------------------------------------------% +%% function : set_data +%% Arguments: EventData - any# +%% Returns : ok +%%----------------------------------------------------------- +set_data(_OE_THIS, State, EventData) when is_record(EventData, any) -> + {reply, ok, ?set_Event(State, EventData)}; +set_data(_OE_THIS, _State, _EventData) -> + corba:raise(#'BAD_PARAM'{completion_status=?COMPLETED_NO}). + + +%%--------------- LOCAL FUNCTIONS ---------------------------- +clear_timer(State) when ?get_Timer(State) == undefined -> + State; +clear_timer(State) -> + catch timer:cancel(?get_Timer(State)), + ?set_Timer(State, undefined). + +%%--------------- MISC FUNCTIONS, E.G. DEBUGGING ------------- +%%--------------- END OF MODULE ------------------------------ |