Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
handle.h
Go to the documentation of this file.00001 00004 /* 00005 * Copyright © 2001,2004 Sofus Mortensen, Michael Geddes 00006 * 00007 * This material is provided "as is", with absolutely no warranty 00008 * expressed or implied. Any use is at your own risk. Permission to 00009 * use or copy this software for any purpose is hereby granted without 00010 * fee, provided the above notices are retained on all copies. 00011 * Permission to modify the code and to distribute modified code is 00012 * granted, provided the above notices are retained, and a notice that 00013 * the code was modified is included with the above copyright notice. 00014 * 00015 * This header is part of comet. 00016 * http://www.lambdasoft.dk/comet 00017 */ 00018 00019 #ifndef COMET_HANDLE_H 00020 #define COMET_HANDLE_H 00021 00022 #include <comet/config.h> 00023 #include <comet/static_assert.h> 00024 #include <comet/error_fwd.h> 00025 #include <comet/common.h> 00026 #include <comet/assert.h> 00027 00028 #include <algorithm> 00029 00030 namespace comet { 00031 00035 00043 template< typename H, long INVALID_HANDLE_ > 00044 class handle_policy_base_t 00045 { 00046 public: 00048 handle_policy_base_t() : handle_(reinterpret_cast<H>(INVALID_HANDLE_)) {} 00049 00050 explicit handle_policy_base_t( H handle) : handle_(handle) {} 00051 00052 typedef H value_type; 00053 00055 operator H() const throw() 00056 { 00057 // This function seemed not to work with returning a namespaced 00058 // type. 00059 return handle_; 00060 } 00061 static inline H invalid_handle() { return reinterpret_cast<H>(INVALID_HANDLE_) ;} 00062 00064 bool valid() const 00065 { 00066 return handle_ != invalid_handle(); 00067 } 00068 00070 H detach_handle() 00071 { 00072 return swap_handle(invalid_handle()); 00073 } 00074 00076 static inline value_type detach( handle_policy_base_t &handle )throw() 00077 { 00078 return handle.detach_handle(); 00079 } 00080 00081 protected: 00083 ~handle_policy_base_t() 00084 { } 00085 00087 void detach_to(handle_policy_base_t &rhs) throw() 00088 { 00089 value_type handle(handle_); 00090 handle_= invalid_handle(); 00091 rhs.handle_ = handle; 00092 } 00093 00094 H get_handle() const { return handle_; } 00095 H *get_handle_ptr() { return &handle_;} 00096 00097 H swap_handle(H new_handle) 00098 { 00099 H old = handle_; 00100 handle_ = new_handle; 00101 return old; 00102 } 00103 00104 private: 00105 H handle_; 00106 }; 00107 00112 struct handle_nothrow_error_policy_t 00113 { 00114 static void on_error() 00115 { } 00116 }; 00117 00122 struct handle_throw_error_policy_t 00123 { 00124 static void on_error() 00125 { 00126 DWORD err = GetLastError(); 00127 raise_exception(HRESULT_FROM_WIN32(err)); 00128 } 00129 }; 00130 00138 template<typename C_, typename H, long INVALID_HANDLE_, typename ERROR_POLICY> 00139 class auto_handle_wrap_t : public handle_policy_base_t<H, INVALID_HANDLE_> 00140 { 00141 protected: 00143 static inline bool destroy_( value_type h) 00144 { 00145 return C_::destroy_handle(h); 00146 } 00147 00149 00151 static bool destroy_handle(value_type h); 00152 00153 typedef handle_policy_base_t<H, INVALID_HANDLE_> policy_base ; 00154 00155 void set_handle( value_type h ) throw() 00156 { 00157 destroy_(swap_handle( h)); 00158 } 00159 00160 static bool expect_nonzero( BOOL value) 00161 { 00162 bool is_ok = (value != FALSE); 00163 if (!is_ok) 00164 ERROR_POLICY::on_error(); 00165 return is_ok; 00166 } 00167 public: 00168 00170 auto_handle_wrap_t() throw() 00171 {} 00172 00174 typedef const C_ &ref; 00175 00178 auto_handle_wrap_t( const impl::auto_attach_t<typename policy_base::value_type> &handle ) throw() 00179 : policy_base(handle.get()) 00180 {} 00181 00185 auto_handle_wrap_t( auto_handle_wrap_t &rhs) throw() 00186 { 00187 rhs.detach_to(*this); 00188 } 00189 00193 auto_handle_wrap_t( policy_base &rhs) throw() 00194 { 00195 rhs.detach_to(*this); 00196 } 00197 00200 ~auto_handle_wrap_t() throw() 00201 { 00202 destroy_(get()); 00203 } 00204 00205 00207 00209 template<typename EP> 00210 auto_handle_wrap_t<C_, H, INVALID_HANDLE_, EP> & operator=(auto_handle_wrap_t<C_, H, INVALID_HANDLE_, EP>& rhs) throw() 00211 { 00212 close_handle(); 00213 rhs.detach_to(*this); 00214 return *this; 00215 } 00216 00218 C_ &operator=(const impl::auto_attach_t<value_type> &handle ) 00219 { 00220 close_handle(); 00221 set_handle(handle.get()); 00222 return *static_cast<C_ *>(this); 00223 } 00224 00226 bool close() throw() 00227 { 00228 return destroy_(policy_base::detach(*this)); 00229 } 00230 00232 00233 00235 00244 typename policy_base::value_type* out() throw() 00245 { 00246 close_handle(); 00247 return get_handle_ptr(); 00248 } 00249 00250 typename policy_base::value_type get() const throw() 00251 { return get_handle(); } 00252 typename policy_base::value_type in() const throw() 00253 { return get_handle(); } 00254 typename policy_base::value_type *inout() throw() 00255 { return get_handle_ptr(); } 00257 00258 static inline const C_ &create_const_reference(const value_type &val) 00259 { return *reinterpret_cast<const C_ *>(&val); } 00260 00261 static inline C_ &create_reference(value_type &val) 00262 { return *reinterpret_cast<C_ *>(&val); } 00263 00265 static bool destroy_reference(value_type H) 00266 { 00267 return true; 00268 } 00269 00270 private: 00271 00273 inline void close_handle() 00274 { 00275 if (!close()) 00276 ERROR_POLICY::on_error(); 00277 } 00278 }; 00279 00280 namespace impl 00281 { 00284 class THIS_IS_NOT_ALLOWED 00285 { 00286 ~THIS_IS_NOT_ALLOWED() {} 00287 }; 00288 } 00289 00291 template< typename H, long INVALID_HANDLE_ > 00292 inline impl::THIS_IS_NOT_ALLOWED CloseHandle(const handle_policy_base_t<H,INVALID_HANDLE_>&); 00293 00295 00297 template< typename H, long INVALID_HANDLE_ > 00298 bool CloseHandle(handle_policy_base_t<H,INVALID_HANDLE_> &rhs) 00299 { 00300 return rhs.close(); 00301 } 00302 00304 template< typename ERROR_POLICY = handle_nothrow_error_policy_t > 00305 struct auto_handle_t : auto_handle_wrap_t< auto_handle_t, HANDLE, 0, ERROR_POLICY > 00306 { 00307 typedef auto_handle_wrap_t< auto_handle_t, HANDLE, 0, ERROR_POLICY > handle_base; 00308 00310 auto_handle_t() {} 00312 auto_handle_t( auto_handle_t &rhs) 00313 : auto_handle_wrap_t< auto_handle_t, HANDLE, 0, ERROR_POLICY >(rhs) 00314 {} 00315 00317 auto_handle_t( const impl::auto_attach_t< HANDLE > &rhs ) 00318 : auto_handle_wrap_t< auto_handle_t, HANDLE, 0, ERROR_POLICY >(rhs) 00319 { } 00321 auto_handle_t &operator=(auto_handle_t &rhs) 00322 { 00323 handle_base::operator=(rhs); 00324 return *this; 00325 } 00326 auto_handle_t &operator=( const impl::auto_attach_t<HANDLE> &rhs) 00327 { 00328 handle_base::operator=(rhs); 00329 return *this; 00330 } 00331 00333 static bool destroy_handle( HANDLE h) 00334 { 00335 return ::CloseHandle(h) != FALSE; 00336 } 00337 00338 }; 00339 00341 typedef auto_handle_t<> auto_handle; 00343 typedef auto_handle_t< handle_throw_error_policy_t > auto_handle_throw; 00344 00346 template <typename T> 00347 struct auto_reference_t : T 00348 { 00349 auto_reference_t( const comet::impl::auto_attach_t<typename T::value_type> &rhs ) : T(rhs) 00350 {} 00351 ~auto_reference_t() 00352 { 00353 destroy_reference(detach_handle()); 00354 } 00355 }; 00357 } 00358 00359 using comet::CloseHandle; 00360 00361 #endif