|
1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Offers a base class for an asynchronous state machine |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 */ |
|
21 |
|
22 #include "StateMachine.h" |
|
23 #include "AsynchEvent.h" |
|
24 |
|
25 |
|
26 #ifdef _DEBUG |
|
27 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module |
|
28 // (if it could happen through user error then you should give it an explicit, documented, category + code) |
|
29 _LIT(KSpecAssert_ElemStateMachStM, "ElemStateMachStM"); |
|
30 #endif |
|
31 |
|
32 EXPORT_C CStateMachine::CStateMachine() : |
|
33 CActive( EPriorityStandard ) |
|
34 { |
|
35 CActiveScheduler::Add(this); |
|
36 } |
|
37 |
|
38 EXPORT_C CStateMachine::~CStateMachine() |
|
39 { |
|
40 delete iFragment; |
|
41 } |
|
42 |
|
43 EXPORT_C HBufC8* CStateMachine::ReAllocL( TInt aNewLength ) |
|
44 /** |
|
45 * Re-allocates the instance fragment |
|
46 * |
|
47 * @param aNewLength a length to put into the buffer |
|
48 * @return a pointer to the allocated fragment |
|
49 */ |
|
50 { |
|
51 if ( !iFragment ) |
|
52 { |
|
53 iFragment = HBufC8::NewL( aNewLength ); |
|
54 } |
|
55 else |
|
56 { |
|
57 TInt n = iFragment->Length(); |
|
58 if ( (iFragment->Des().MaxLength() - n) < aNewLength ) |
|
59 { |
|
60 iFragment = iFragment->ReAllocL( aNewLength + n ); |
|
61 } |
|
62 } |
|
63 return iFragment; |
|
64 } |
|
65 |
|
66 EXPORT_C void CStateMachine::Start( TRequestStatus* aClientStatus, CAsynchEvent* aErrorEvent, MStateMachineNotify* aStateMachineNotify ) |
|
67 /** |
|
68 * Starts the state machine |
|
69 * |
|
70 * @param aClientStatus the client request to complete on completion |
|
71 * @param aErrorEvent an error event to execute on error |
|
72 * @param aStateMachineNotify a notifier to receive state achine events |
|
73 */ |
|
74 { |
|
75 //history is set beforehand |
|
76 iLastError = KErrNone; |
|
77 iClientStatus = aClientStatus; |
|
78 if (iClientStatus != NULL) |
|
79 *iClientStatus = KRequestPending; |
|
80 iErrorEvent = aErrorEvent; |
|
81 iSuspendRequest = EFalse; |
|
82 iStateMachineNotify = aStateMachineNotify; |
|
83 //jump to RunL |
|
84 TRequestStatus* p=&iStatus; |
|
85 if ( !IsActive() ) |
|
86 { |
|
87 SetActive(); |
|
88 } |
|
89 User::RequestComplete( p, KErrNone ); |
|
90 } |
|
91 |
|
92 EXPORT_C void CStateMachine::Cancel( TInt aLastError ) |
|
93 /** |
|
94 * Cancels the state machine with an error |
|
95 * |
|
96 * @param aLastError a desired error code. |
|
97 * if the last eror is KErrNone the state machine |
|
98 * will be cancelled and client request will be completed with KErrCancel. |
|
99 * In any other case the active event will become the error event and the |
|
100 * processing continues. |
|
101 */ |
|
102 { |
|
103 iSuspendRequest = EFalse; |
|
104 if ( aLastError == KErrNone ) |
|
105 { |
|
106 iErrorEvent = 0; |
|
107 } |
|
108 //cancel the current activity |
|
109 CActive::Cancel(); |
|
110 iLastError = KErrCancel; |
|
111 iActiveEvent = iErrorEvent; |
|
112 if ( iActiveEvent ) |
|
113 { |
|
114 //jump to RunL //!!This makes the cancel asynchronous |
|
115 TRequestStatus* p=&iStatus; |
|
116 SetActive(); |
|
117 User::RequestComplete( p, KErrNone ); |
|
118 } |
|
119 } |
|
120 |
|
121 EXPORT_C void CStateMachine::DoCancel() |
|
122 /** |
|
123 * completes the cancel request |
|
124 * |
|
125 */ |
|
126 { |
|
127 if ( !iErrorEvent ) //otherwise the "cancel" completes after the error event has been sent |
|
128 { |
|
129 OnCompletion(); |
|
130 } |
|
131 } |
|
132 |
|
133 EXPORT_C void CStateMachine::OnError() |
|
134 /** |
|
135 * Called from ::RunL when an error occures |
|
136 * |
|
137 */ |
|
138 { |
|
139 if ( iLastError != KErrNone ) |
|
140 { |
|
141 if ( iActiveEvent != iErrorEvent ) |
|
142 { |
|
143 iActiveEvent = 0; |
|
144 } |
|
145 } |
|
146 else |
|
147 { |
|
148 iLastError = iStatus.Int(); |
|
149 iActiveEvent = iErrorEvent; |
|
150 } |
|
151 } |
|
152 |
|
153 EXPORT_C void CStateMachine::RunL() |
|
154 /** |
|
155 * Called on completion of one active event |
|
156 * |
|
157 */ |
|
158 { |
|
159 if ( iStatus.Int() != KErrNone ) |
|
160 {//error |
|
161 OnError(); |
|
162 } |
|
163 if ( iActiveEvent ) |
|
164 {//process iActiveEvent if not iSuspendRequest |
|
165 if ( iSuspendRequest ) |
|
166 { |
|
167 if ( iStateMachineNotify ) |
|
168 {//return value ignored |
|
169 iStateMachineNotify->OnCompletion( this ); |
|
170 } |
|
171 } |
|
172 else |
|
173 { |
|
174 SetActive(); |
|
175 iActiveEvent = iActiveEvent->ProcessL( iStatus ); |
|
176 } |
|
177 } |
|
178 else |
|
179 {//complete the state machine task |
|
180 OnCompletion(); |
|
181 } |
|
182 } |
|
183 |
|
184 EXPORT_C TInt CStateMachine::RunError(TInt aError) |
|
185 /** |
|
186 * RunL left. Complete status with the aError and let RunL function to handle it |
|
187 * |
|
188 */ |
|
189 { |
|
190 //if RunL (ProcessL) leaves the current request must not be completed |
|
191 __ASSERT_DEBUG(IsActive(), User::Panic(KSpecAssert_ElemStateMachStM, 1)); |
|
192 iActiveEvent = 0; |
|
193 TRequestStatus* p=&iStatus; |
|
194 User::RequestComplete( p, aError ); |
|
195 return KErrNone; //no error propagation to central error handler |
|
196 } |
|
197 |
|
198 EXPORT_C void CStateMachine::OnCompletion() |
|
199 /** |
|
200 * Called by RunL when the state machine has completed its task. |
|
201 * |
|
202 */ |
|
203 { |
|
204 //!!!notifier cannot delete this |
|
205 TBool bDelete = iStateMachineNotify ? iStateMachineNotify->OnCompletion( this ) : EFalse; |
|
206 if ( iClientStatus ) |
|
207 { |
|
208 User::RequestComplete( iClientStatus, iLastError ); |
|
209 } |
|
210 if ( bDelete ) |
|
211 { |
|
212 delete this; |
|
213 } |
|
214 } |
|
215 |