Write a daemon on Windows (3) handle management
Programming in Windows, dealing with handle is a common occurrence. In order to prevent forgetting CloseHandle, I use the do-while-false technique:
void f () { = NULL; Do { while (false); if (h) { CloseHandle (h); = NULL;} }
Handle more, you have to write several lengths of the same cleanup code, more trouble. To think about it, it's very easy to write a shut-off device--close automatically when the scope is out:
class Public boost::noncopyable{public: Closer (HANDLE h) : H_ (h) { } ~ Closer () { if (h_) { CloseHandle (h_); = NULL; } } Private : HANDLE H_;};
After you create or open a handle, delegate its close action to closer.
This is what I thought when I wrote this article, when I wrote the code, I used another method: Scoped_handle. This is from the boost inside those who use RAII techniques to learn, such as Scoped_ptr,scoped_array, the name is also learned:
TemplateclassScoped_handle: Publicboost::noncopyable{ Public: Scoped_handle (): H_ (invalid_value) {} scoped_handle (ConstHANDLE &h): H_ (h) {}~Scoped_handle () {destory (); } //You should ensure not self-assignment voidResetConstHANDLE &h) {destory (); H_=h; } voiddestory () {if(H_! =invalid_value) { //CloseHandle would set last error code//So we should recover it//Someone may use Reset (CreateFile (...))Last_error_recover R; CloseHandle (H_); H_=Invalid_value; } } BOOLValid ()Const { returnH_! =Invalid_value; } HANDLE&Get_ref () {returnH_; } HANDLE*get_ptr () {return&H_; }Private: HANDLE H_;};
There is a template parameter Invalid_value, which is the invalid value of the handle, I now see two kinds: null,invalid_handle_value.
Examples of usage:
Scoped_handle<> hprocess (openprocess (process_query_information | Process_vm_read, FALSE, PID)); if (! Hprocess.valid ()) { Errorloglasterr ("Openprocess[%lu] fail", PID);} Else { = query (hprocess.get_ref (), native_name);}
Scoped_handle<> Htoken; if (! OpenProcessToken (GetCurrentProcess (), Token_adjust_privileges, Htoken.get_ptr ())) { //...}
Scoped_handle<> m_exit_event;m_exit_event.reset (CreateEvent (null, TRUE, FALSE, null)); if (! M_exit_event.valid ()) { //...}
I now find myself a reason not to use closer: I don't like to let others help me do what I can. Closer is like someone new to the object, and then give the pointer to another person, let him "wipe the bottom", but his "wipe the bottom" is just a little help. However, this reason is not strong, the convenience of closer far more than the "wipe the butt" disgust.
Here's a TODO: I want to be able to customize the close action, which is the close action as a template parameter, so that I can put handle also refer to the location of the template parameters, this thing is more widely used, but I do not know how to put the close action on the location of the template parameters.
Presumably sharp-eyed classmate saw the above code there is a last_error_recover, this is a very simple class, comments have explained its purpose, the following is the implementation:
class Public boost::noncopyable{public: last_error_recover () : Code_ (GetLastError ()) { } Last_error_recover (const DWORD Code) : Code_ (code) { } ~last_ Error_recover () { setlasterror (code_); } Private : Const DWORD Code_;};
Source: Https://git.oschina.net/mkdym/DaemonSvc.git (Master) && Https://github.com/mkdym/DaemonSvc.git (for lifting).
Saturday, October 31, 2015
Write a daemon on Windows (3) handle management