ACE_FUTURE implements a single-write multi-read mode, which can be used to return the results of asynchronous method to return
Activate the object scheduler, inherited thread base type ACE_TASK_BASE
1) Method Requests SVR () 2) method Request to enter the Work () 3) method request to process Work_i ()
ACE_Method_call the call function function established Prime_Scheduler class method request process correlation function work_i. Particular function Call ACE_Method_call call transpose Prime_Scheduler function work_i (), work_i () returns the value returned to the set function, then the ACE_Future set function then To the SET function of the ACE_FUTURE_REP to generate the desired result value value_ and save the ACE_FUTRUE_REP. Then ACE_FUTRUE's function ready checks if there is a result value, it is also the value pointer generated by the ACE_FUTURE_REP to detect the value pointer to the set function, ACE_FURTURE The function get goes to get the result value.
A Call pure virtual function is included in the ACE_METHOD_REQUEST class
Class ACE_EXPORT ACE_METHOD_REQUEST
{
PUBLIC:
ACE_METHOD_REQUEST (unsigned long priority = 0);
Virtual ~ ACE_METHOD_REQUEST (VOID);
Unsigned long priority (void) const;
Void Priority (UNSIGNED Long Prio);
Virtual Int Call (void) = 0;
protected:
Unsigned long priority_;
}
Class prime_scheduler: public ace_task_base
{
PUBLIC:
// Initialization
Virtual int open (void * args = 0);
//termination
Virtual Int Close (u_long flags = 0);
/ / Activate some method of the proxy interface of the object
ACE_FUTURE
ACE_FUTURE
Void End (Void);
protected:
// Run the event loop
Virtual Int SVC (Void);
// Top two methods Work, Name implementation
U_long Work_i (U_LONG, INT);
Const ace_tchar * name_i (void);
Private:
// Activate the object queue
ACE_ACTIVATION_QUEUE ACTIVATION_QUE_;
// Activate the object pointer
PRIME_SCHEDULER * SCHEDULER_;
}
1) Request the method to start processing the method in the active queue request call int prime_scheduler :: SVC (Void)
{
For (;;)
{
// List the next method call request (we use the smart pointer to ensure exception MO clear)
Auto_PTR
ACE_DEBUG ((lm_debug,
ACE_TEXT ("(% T) Calling Method Request / N")))))))))))
// call it
IF (Mo-> Call () == -1)
Break;
}
}
2) Requesting the need to enter the dispatch, requesting the work entered function Work, mainly to request the method to enter a column_future
Prime_scheduler :: Work (u_long newparam,
INT newcount) {
/ / Judgment the dispatcher pointer of the dispatcher's internal
IF (this-> scheduler_) {
Return this-> Scheduler_-> Work (newparam, newcount);
}
// No, use the activation object queue directly
Else {
ACE_FUTURE
// Method requests to enter.
this-> Activation_queue_.enqueue
(New Method_Request_Work (this,
NewParam,
Newcount,
New_future));
Return new_future;
}
}
3) Request processing // This is where Work happens. This method is called in the Call function in the method_request_work class.
U_long
Prime_scheduler :: Work_i (u_long param,
INT country
{
ACE_UNUSED_ARG (Count);
Return Ace :: IS_PRIME (param, 2, param / 2);
}
Method requests work class method_request_Work implementation, constructor is incorporated into activation object dispattors
Class method_request_work: public ace_method_request
{
Method_Request_Work (prime_scheduler *,
U_long,
Int,
ACE_FUTURE
Virtual Int Call (Void)
{
// Distribute the operation and save the result to FUTRUE, we note that the parameter 1 of the set is
// Scheduling Work_i function
Return this-> Future_Result_.Set (this-> scheduler _-> work_i
(this-> param_,
this-> count_)));
}
Pivate:
PRIME_SCHEDULER * SCHEDULER_;
U_long param_;
INT count_;
ACE_FUTURE
}
INT main () {prime_scheduler * andres, * peter, * Helmut, * matias
Create four activation objects.
For (int i = 0; i { { ACE_FUTURE ACE_FUTURE ACE_FUTURE ACE_FUTURE ACE_FUTURE ACE_FUTURE / / Method Requests to enter, wait for object activation calls, they are in the scheduling thread SVR to perform FRESULTA = Andres-> Work (9013); FResultb = peter-> work (9013); FResultc = Helmut-> Work (9013); FResultd = Matias-> Work (9013); // See if there is a result of IF (Fresulta.Ready ()) IF (i% 3 == 0) { // Cancel Futures ... Fresulta.cancel (10UL); FResultb.cancel (20 ul); Fresultc.cancel (30 ul); Fresultd.cancel (40UL); } // Get the result U_long Resulta = 0, Resultb = 0, Resultc = 0, resultd = 0, ResulTe = 0; Fresulta.get (Resulta); Fresultb.get (resultb); FResultc.get (Resultc); FResultd.get (resultd); Fresulte.get (resulte); } // Close the activation object Andres-> end (); Peter-> end (); Helmut-> end (); Matias-> End (); DELETE ANDRES; Delete peter; DELETE HELMUT; DELETE MATIAS; } // Implement but write multi-read mode, can be used to return the result of asynchronous method to return, and the ACE_FUTURE is overloaded = operator. Template Class ace_future { PUBLIC: // Multiple constructor ACE_FUTURE (VOID); ACE_FUTURE (Const Ace_Future ACE_FUTURE (Const T & R); ~ ACE_FUTURE (VOID); // Operator overload Void Operator = (Const ACE_FUTURE INT Operator == (Const ACE_FUTURE INT Operator! = (Const ACE_FUTURE Operator t (); Int Cancel (Const T & R); Int Cancel (Void); Int set (Const T & R); INT GET (T & Value, ACE_TIME_VALUE * TV = 0) const; INT Ready (Void) Const; Int Attach (ACE_FUTURE_OBSERVER INT DETACH (ACE_FUTURE_OBSERVER Void dump (void) const; ACE_FUTURE_REP ACE_ALLOC_HOOK_DECLARE; Private: /// Do not allow new, delete, & operator Void * Operator new (size_t nbytes); Void Operator delete (void *); Void Operator & (); /// Protect Typedef ace_future_rep FUTURE_REP * FUTURE_REP_; } Template Class ACE_FUTURE_OBSERVER { PUBLIC: Virtual ~ ACE_FUTURE_OBSERVER (VOID); Virtual Void Update (Const Ace_Future ACE_ALLOC_HOOK_DECLARE; protected: ACE_FUTURE_OBSERVER (VOID); } Assign this-> future_rep_, and count template { ACE_FUTURE FUTURE_REP :: Assign (this-> future_rep_, FUTURE_REP :: attach (r.future_rep_); } The attach function is referenced template ACE_FUTURE_REP { ACE_ASSERT (Rep! = 0); // use value_ready_mutex_ for Both Condition and Ref Count Management ACE_MT (ACE_GUARD rep-> Ref_count_; RETURN REP; } Assign ACE_FURTURE member ace_furture_rep template ACE_FUTURE_REP { ACE_ASSERT (Rep! = 0); ACE_ASSERT (new_rep! = 0); // use value_ready_mutex_ for Both Condition and Ref Count Management ACE_MT (ACE_THREAD_MUTEX, R_MON, REP-> Value_Ready_Mutex_); ACE_FUTURE_REP Rep = new_rep; // Detached Old Last for Exception Safety IF (il-> ref_count _-- == 0) { ACE_MT (R_Mon.Release ()); // We do not need the lock when deleding the representation. // there shouth be no side effects from deletring rep and we don // Not Want To Release A deleted Mutex. DELETE OLD; } } ACE_FUTURE Function SET Indirect Call Member's ACE_FUTURE_REP SET Function Template ACE_FUTURE { / / Give the result pointer to the ACE_FUTURE_REP. Return this-> Future_rep_-> set (r, * this); } Template ACE_FUTURE_REP ACE_FUTURE { // If the value has been generated, it is ignored. IF (this-> value_ == 0) { ACE_MT (ACE_GUARD_RETURN (ACE_THREAD_MUTEX, ACE_MON, this-> value_ready_mutex_, -1)); / / Not, then a result value, note that use dual check lock mode to avoid multiple assignments IF (this-> value_ == 0) // has no value, resulting { ACE_NEW_RETURN (this-> Value_, T (r), -1); // Remove and Notify All Subscribed Observers. ACE_TYPENAME OBSERVER_COLLECTION :: Iterator = This-> Observer_collection_.begin (); ACE_TYPENAME OBSERVER_COLLECTION :: Iterator End = this-> Observer_collection_.end (); While (Iterator! = End) { Observer * Observer = * Iterator ; Observer-> Update (Caller); } // For thread broadcast signals waiting for Return this-> value_ready_.broadcast (); } } Return 0; } Check result value Template ACE_FUTURE { // We'RE Ready if the ace_future_rep is ready ... Return this-> FUTURE_REP_-> Ready (); } Simply determined whether the value pointer does not return to Template ACE_FUTURE_REP { Return this-> Value_! = 0; } Get the result value, update So ACE_FUTURE_OBSERVER TEMPLATE ACE_FUTURE_REP ACE_TIME_VALUE * TV) Const { // if the value is already product, return it. IF (this-> value_ == 0) { ACE_MT (ACE_GUARD_RETURN (ACE_THREAD_MUTEX, ACE_MON, ACE_CONST_CAST (ACE_THREAD_MUTEX &, THIS-> Value_ready_mutex_), -1)); // if the value is not yet defined we must block unsteil the // Producer Writes to it. While (this-> value_ == 0) // Perform a Timed Wait. IF ((ACE_CONST_CAST (ACE_CONDITION_THREAD_MUTEX &, THIS-> Value_Ready_)). Wait (TV) == -1) Return -1; // deStructor Releases The Lock. } Value = * this-> value_; Return 0; }