Hi everyone, I am new to this online forum. I am a software engineer residing in Singapore doing software development for a living for past 9 years. Only recently am I introduced to the wonders of ACE. It is such a pity the ACE framework is not part of the C++ standard else any decent C++ compiler would have those classes built in as compared to now I got to download separately and add on. My ACE newbie questions are as below. Would appreciate some ACE experts to help me here.
Qn 1. Can we use C++ STL and ACE classes interchangeably? Since STL is part of the C++ standard can I say I use a vector<ACE_Event_Handler *> or list<ACE_Reactor *> for e.g ?
Qn 2. Can I have a portable graceful shutdown technique for the server program? Most tutorials I found online use the signal handling technique. That is, a client admin program is executed by sending a SIGINT or some other signal to the server program to indicate a graceful shutdown procedure is to be executed. The signal concept will not work in Windows environment I presume?
My approach to get my server program graceful shutdown feature to be portable is to dedicate one extra port meant only for admin client. Once connect request is received on this extra port, it indicates to my server program it is time to perform graceful shutdown. This approach should work on both Unix and Windows environment.
class Server_Daemon {
public:
int open(...) { //called by main program Step 1
reactor_.open(10); //max. 10 handles
workerPool_.open();
workerPool_.activate(THR_LWP, 10); //pre-spawn 10 threads
}
int close(...) { //called by main program Step 3
workerPool_.close();
reactor_.close();
}
int run(...) { //called by main program Step 2
ACE_NEW_RETURN(admin_acceptor_, AdminAccept_Handler(this), -1); //only ONE instance of AdminAccept_Handler will be instantiated
reactor_.register_handler(admin_acceptor_,ACE_Event_Handler::ACCEPT_MASK);
reactor_.run_reactor_event_loop();
}
AdminAccept_Handler *admin_acceptor_;
ACE_Reactor reactor_;
ACE_Task<ACE_MT_SYNCH> workerPool_;
}
class AdminAccept_Handler : public ACE_Event_Handler {
public:
int AdminAccept_Handler(Server_Daemon *s) { //ctor
src_ = s;
reactor(src_->reactor_); // called parent class set the reactor
}
int handle_input(...) {
//first accept call received presume Graceful Shutdown command
src_->workerPool_.msg_queue()->deactivate(); //freeze ACE_Task msg queue, wake up all threads within to finish up and exit thread
src_->workerPool_.msg_queue()->close(); //release ACE_Task msg queue resources
src_->workerPool_.msg_queue()->wait(); //wait for all the threads within ACE_Task to exit
src_->reactor_.purge_pending_notifications(0); //purge all handlers notification and handlers
src_->reactor_.end_reactor_event_loop();
return -1; // Will reactor_ called handle_close of this instance????
}
int handle_close(...) {
delete this;
}
private:
Server_Daemon *src_;
}
Please note the handle_input method of AdminAccept_Handler class. For reactor_.purge_pending_notifications(0) I wanna remove all notifications for ALL handlers registered with reactor_ and also remove ALL handlers thereafter. If those reactor_ registered handlers are allocated dynamically previously, will I be leaking memory by just calling this purge_pending_notifications method?
What about the current handler that is executing the handle_input? Will it be purged also? Will I have some erratic behavior since I called purge_pending_notifications(0) within the handle_input method of a registered handler? I also called reactor_.end_reactor_event_loop within the handle_input method of the current handler. Will this behave erratically also?
Would appreciate other alternative suggestions if my proposed graceful shutdown approach above is flawed. Thanks.