00001 /** @file 00002 00003 Generic interface which enables any event or async activity to be cancelled 00004 00005 @section license License 00006 00007 Licensed to the Apache Software Foundation (ASF) under one 00008 or more contributor license agreements. See the NOTICE file 00009 distributed with this work for additional information 00010 regarding copyright ownership. The ASF licenses this file 00011 to you under the Apache License, Version 2.0 (the 00012 "License"); you may not use this file except in compliance 00013 with the License. You may obtain a copy of the License at 00014 00015 http://www.apache.org/licenses/LICENSE-2.0 00016 00017 Unless required by applicable law or agreed to in writing, software 00018 distributed under the License is distributed on an "AS IS" BASIS, 00019 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00020 See the License for the specific language governing permissions and 00021 limitations under the License. 00022 00023 */ 00024 00025 #ifndef _I_Action_h_ 00026 #define _I_Action_h_ 00027 00028 #include "libts.h" 00029 #include "I_Thread.h" 00030 #include "I_Continuation.h" 00031 00032 /** 00033 Represents an operation initiated on a Processor. 00034 00035 The Action class is an abstract representation of an operation 00036 being executed by some Processor. A reference to an Action object 00037 allows you to cancel an ongoing asynchronous operation before it 00038 completes. This means that the Continuation specified for the 00039 operation will not be called back. 00040 00041 Actions or classes derived from Action are the typical return 00042 type of methods exposed by Processors in the Event System and 00043 throughout the IO Core libraries. 00044 00045 The canceller of an action must be the state machine that will 00046 be called back by the task and that state machine's lock must be 00047 held while calling cancel. 00048 00049 Processor implementers: 00050 00051 You must ensure that no events are sent to the state machine after 00052 the operation has been cancelled appropriately. 00053 00054 Returning an Action: 00055 00056 Processor functions that are asynchronous must return actions to 00057 allow the calling state machine to cancel the task before completion. 00058 Because some processor functions are reentrant, they can call 00059 back the state machine before the returning from the call that 00060 creates the actions. To handle this case, special values are 00061 returned in place of an action to indicate to the state machine 00062 that the action is already completed. 00063 00064 - @b ACTION_RESULT_DONE The processor has completed the task 00065 and called the state machine back inline. 00066 - @b ACTION_RESULT_INLINE Not currently used. 00067 - @b ACTION_RESULT_IO_ERROR Not currently used. 00068 00069 To make matters more complicated, it's possible if the result is 00070 ACTION_RESULT_DONE that state machine deallocated itself on the 00071 reentrant callback. Thus, state machine implementers MUST either 00072 use a scheme to never deallocate their machines on reentrant 00073 callbacks OR immediately check the returned action when creating 00074 an asynchronous task and if it is ACTION_RESULT_DONE neither read 00075 nor write any state variables. With either method, it's imperative 00076 that the returned action always be checked for special values and 00077 the value handled accordingly. 00078 00079 Allocation policy: 00080 00081 Actions are allocated by the Processor performing the actions. 00082 It is the processor's responsbility to handle deallocation once 00083 the action is complete or cancelled. A state machine MUST NOT 00084 access an action once the operation that returned the Action has 00085 completed or it has cancelled the Action. 00086 00087 */ 00088 class Action 00089 { 00090 00091 public: 00092 00093 /** 00094 Contination that initiated this action. 00095 00096 The reference to the initiating continuation is only used to 00097 verify that the action is being cancelled by the correct 00098 continuation. This field should not be accesed or modified 00099 directly by the state machine. 00100 00101 */ 00102 Continuation * continuation; 00103 00104 00105 /** 00106 Reference to the Continuation's lock. 00107 00108 Keeps a reference to the Continuation's lock to preserve the 00109 access to the cancelled field valid even when the state machine 00110 has been deallocated. This field should not be accesed or 00111 modified directly by the state machine. 00112 00113 */ 00114 Ptr<ProxyMutex> mutex; 00115 00116 /** 00117 Internal flag used to indicate whether the action has been 00118 cancelled. 00119 00120 This flag is set after a call to cancel or cancel_action and 00121 it should not be accesed or modified directly by the state 00122 machine. 00123 00124 */ 00125 volatile int cancelled; 00126 00127 /** 00128 Cancels the asynchronous operation represented by this action. 00129 00130 This method is called by state machines willing to cancel an 00131 ongoing asynchronous operation. Classes derived from Action may 00132 perform additional steps before flagging this action as cancelled. 00133 There are certain rules that must be followed in order to cancel 00134 an action (see the Remarks section). 00135 00136 @param c Continuation associated with this Action. 00137 00138 */ 00139 virtual void cancel(Continuation * c = NULL) { 00140 ink_assert(!c || c == continuation); 00141 #ifdef DEBUG 00142 ink_assert(!cancelled); 00143 cancelled = true; 00144 #else 00145 if (!cancelled) 00146 cancelled = true; 00147 #endif 00148 } 00149 00150 /** 00151 Cancels the asynchronous operation represented by this action. 00152 00153 This method is called by state machines willing to cancel an 00154 ongoing asynchronous operation. There are certain rules that 00155 must be followed in order to cancel an action (see the Remarks 00156 section). 00157 00158 @param c Continuation associated with this Action. 00159 00160 */ 00161 void cancel_action(Continuation * c = NULL) { 00162 ink_assert(!c || c == continuation); 00163 #ifdef DEBUG 00164 ink_assert(!cancelled); 00165 cancelled = true; 00166 #else 00167 if (!cancelled) 00168 cancelled = true; 00169 #endif 00170 } 00171 00172 Continuation *operator =(Continuation * acont) 00173 { 00174 continuation = acont; 00175 if (acont) 00176 mutex = acont->mutex; 00177 else 00178 mutex = 0; 00179 return acont; 00180 } 00181 00182 /** 00183 Constructor of the Action object. Processor implementers are 00184 responsible for associating this action with the proper 00185 Continuation. 00186 00187 */ 00188 Action():continuation(NULL), cancelled(false) { 00189 } 00190 00191 #if defined(__GNUC__) 00192 virtual ~ Action() { 00193 } 00194 #endif 00195 }; 00196 00197 #define ACTION_RESULT_NONE MAKE_ACTION_RESULT(0) 00198 #define ACTION_RESULT_DONE MAKE_ACTION_RESULT(1) 00199 #define ACTION_IO_ERROR MAKE_ACTION_RESULT(2) 00200 #define ACTION_RESULT_INLINE MAKE_ACTION_RESULT(3) 00201 00202 // Use these classes by 00203 // #define ACTION_RESULT_HOST_DB_OFFLINE 00204 // MAKE_ACTION_RESULT(ACTION_RESULT_HOST_DB_BASE + 0) 00205 00206 #define MAKE_ACTION_RESULT(_x) (Action*)(((uintptr_t)((_x<<1)+1))) 00207 00208 #define ACTION_RESULT(_x) \ 00209 (int)((((uintptr_t)_x)&1)!=0?(((uintptr_t)>>1):(uintptr_t)0)) 00210 00211 #define IS_ACTION_RESULT(_x) ((((uintptr_t)_x)&1) != 0) 00212 00213 #endif /*_Action_h_*/