00001 #ifndef _SERVICE_H_
00002 #define _SERVICE_H_
00003
00004 typedef const void* service_class_ref;
00005
00006 PFC_DECLARE_EXCEPTION(exception_service_not_found,pfc::exception,"Service not found");
00007 PFC_DECLARE_EXCEPTION(exception_service_extension_not_found,pfc::exception,"Service extension not found");
00008 PFC_DECLARE_EXCEPTION(exception_service_duplicated,pfc::exception,"Service duplicated");
00009
00010 #ifdef _MSC_VER
00011 #define FOOGUIDDECL __declspec(selectany)
00012 #else
00013 #define FOOGUIDDECL
00014 #endif
00015
00016
00017 #define DECLARE_GUID(NAME,A,S,D,F,G,H,J,K,L,Z,X) FOOGUIDDECL const GUID NAME = {A,S,D,{F,G,H,J,K,L,Z,X}};
00018 #define DECLARE_CLASS_GUID(NAME,A,S,D,F,G,H,J,K,L,Z,X) FOOGUIDDECL const GUID NAME::class_guid = {A,S,D,{F,G,H,J,K,L,Z,X}};
00019
00021 template<typename T> class service_obscure_refcounting : public T {
00022 private:
00023 int service_add_ref() throw();
00024 int service_release() throw();
00025 };
00026
00028 template<typename T> static inline service_obscure_refcounting<T>* service_obscure_refcounting_cast(T * p_source) throw() {return static_cast<service_obscure_refcounting<T>*>(p_source);}
00029
00031 template<typename T> static void service_release_safe(T * p_ptr) throw() {
00032 if (p_ptr != NULL) p_ptr->service_release();
00033 }
00034
00036 template<typename T> static void service_add_ref_safe(T * p_ptr) throw() {
00037 if (p_ptr != NULL) p_ptr->service_add_ref();
00038 }
00039
00041 template<typename T>
00042 class service_ptr_t {
00043 private:
00044 typedef service_ptr_t<T> t_self;
00045 public:
00046 inline service_ptr_t() throw() : m_ptr(NULL) {}
00047 inline service_ptr_t(T* p_ptr) throw() : m_ptr(NULL) {copy(p_ptr);}
00048 inline service_ptr_t(const t_self & p_source) throw() : m_ptr(NULL) {copy(p_source);}
00049
00050 template<typename t_source>
00051 inline service_ptr_t(t_source * p_ptr) throw() : m_ptr(NULL) {copy(p_ptr);}
00052
00053 template<typename t_source>
00054 inline service_ptr_t(const service_ptr_t<t_source> & p_source) throw() : m_ptr(NULL) {copy(p_source);}
00055
00056 inline ~service_ptr_t() throw() {service_release_safe(m_ptr);}
00057
00058 template<typename t_source>
00059 void copy(t_source * p_ptr) throw() {
00060 service_release_safe(m_ptr);
00061 m_ptr = pfc::safe_ptr_cast<T>(p_ptr);
00062 service_add_ref_safe(m_ptr);
00063 }
00064
00065 template<typename t_source>
00066 inline void copy(const service_ptr_t<t_source> & p_source) throw() {copy(p_source.get_ptr());}
00067
00068
00069 inline const t_self & operator=(const t_self & p_source) throw() {copy(p_source); return *this;}
00070 inline const t_self & operator=(T * p_ptr) throw() {copy(p_ptr); return *this;}
00071
00072 template<typename t_source> inline t_self & operator=(const service_ptr_t<t_source> & p_source) throw() {copy(p_source); return *this;}
00073 template<typename t_source> inline t_self & operator=(t_source * p_ptr) throw() {copy(p_ptr); return *this;}
00074
00075 inline void release() throw() {
00076 service_release_safe(m_ptr);
00077 m_ptr = NULL;
00078 }
00079
00080
00081 inline service_obscure_refcounting<T>* operator->() const throw() {PFC_ASSERT(m_ptr != NULL);return service_obscure_refcounting_cast(m_ptr);}
00082
00083 inline T* get_ptr() const throw() {return m_ptr;}
00084
00085 inline bool is_valid() const throw() {return m_ptr != NULL;}
00086 inline bool is_empty() const throw() {return m_ptr == NULL;}
00087
00088 inline bool operator==(const t_self & p_item) const throw() {return m_ptr == p_item.get_ptr();}
00089 inline bool operator!=(const t_self & p_item) const throw() {return m_ptr != p_item.get_ptr();}
00090 inline bool operator>(const t_self & p_item) const throw() {return m_ptr > p_item.get_ptr();}
00091 inline bool operator<(const t_self & p_item) const throw() {return m_ptr < p_item.get_ptr();}
00092
00093 template<typename t_other>
00094 inline t_self & operator<<(service_ptr_t<t_other> & p_source) throw() {__unsafe_set(p_source.__unsafe_detach());return *this;}
00095 template<typename t_other>
00096 inline t_self & operator>>(service_ptr_t<t_other> & p_dest) throw() {p_dest.__unsafe_set(__unsafe_detach());return *this;}
00097
00098
00099 inline T* __unsafe_duplicate() const throw() {
00100 service_add_ref_safe(m_ptr);
00101 return m_ptr;
00102 }
00103
00104 inline T* __unsafe_detach() throw() {
00105 return pfc::replace_null_t(m_ptr);
00106 }
00107
00108 template<typename t_source>
00109 inline void __unsafe_set(t_source * p_ptr) throw() {
00110 service_release_safe(m_ptr);
00111 m_ptr = pfc::safe_ptr_cast<T>(p_ptr);
00112 }
00113 private:
00114 T* m_ptr;
00115 };
00116
00117 namespace pfc {
00118 template<typename T>
00119 class traits_t<service_ptr_t<T> > : public traits_default {
00120 public:
00121 enum { realloc_safe = true, constructor_may_fail = false};
00122 };
00123 }
00124
00125
00126 template<typename T, template<typename> class t_alloc = pfc::alloc_fast>
00127 class service_list_t : public pfc::list_t<service_ptr_t<T>, t_alloc >
00128 {
00129 };
00130
00136 #define FB2K_MAKE_SERVICE_INTERFACE(THISCLASS,PARENTCLASS) \
00137 public: \
00138 typedef THISCLASS t_interface; \
00139 typedef PARENTCLASS t_interface_parent; \
00140 \
00141 static const GUID class_guid; \
00142 \
00143 virtual bool service_query(service_ptr_t<service_base> & p_out,const GUID & p_guid) { \
00144 if (p_guid == class_guid) {p_out = this; return true;} \
00145 else return PARENTCLASS::service_query(p_out,p_guid); \
00146 } \
00147 protected: \
00148 THISCLASS() {} \
00149 ~THISCLASS() {} \
00150 private: \
00151 const THISCLASS & operator=(const THISCLASS &) {throw pfc::exception_not_implemented();} \
00152 THISCLASS(const THISCLASS &) {throw pfc::exception_not_implemented();} \
00153 private: \
00154 void __private__service_declaration_selftest() { \
00155 pfc::assert_same_type<PARENTCLASS,PARENTCLASS::t_interface>(); \
00156 __validate_service_class_helper<THISCLASS>(); \
00157 pfc::safe_cast<service_base*>(this); \
00158 }
00159
00164 #define FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(THISCLASS) \
00165 public: \
00166 typedef THISCLASS t_interface_entrypoint; \
00167 FB2K_MAKE_SERVICE_INTERFACE(THISCLASS,service_base)
00168
00169
00170 #define FB2K_DECLARE_SERVICE_BEGIN(THISCLASS,BASECLASS) \
00171 class NOVTABLE THISCLASS : public BASECLASS { \
00172 FB2K_MAKE_SERVICE_INTERFACE(THISCLASS,BASECLASS); \
00173 public:
00174
00175 #define FB2K_DECLARE_SERVICE_END() \
00176 };
00177
00178 #define FB2K_DECLARE_SERVICE_ENTRYPOINT_BEGIN(THISCLASS) \
00179 class NOVTABLE THISCLASS : public service_base { \
00180 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(THISCLASS) \
00181 public:
00182
00183
00186 class NOVTABLE service_base
00187 {
00188 public:
00191 virtual int service_release() throw() = 0;
00194 virtual int service_add_ref() throw() = 0;
00197 virtual bool service_query(service_ptr_t<service_base> & p_out,const GUID & p_guid) {return false;}
00198
00202 template<class T>
00203 bool service_query_t(service_ptr_t<T> & p_out)
00204 {
00205 pfc::assert_same_type<T,T::t_interface>();
00206 service_ptr_t<service_base> temp;
00207 if (!service_query(temp,T::class_guid)) return false;
00208 p_out.__unsafe_set(static_cast<T*>(temp.__unsafe_detach()));
00209 return true;
00210 }
00211
00212 typedef service_base t_interface;
00213
00214 protected:
00215 service_base() {}
00216 ~service_base() {}
00217 private:
00218 service_base(const service_base&) {throw pfc::exception_not_implemented();}
00219 const service_base & operator=(const service_base&) {throw pfc::exception_not_implemented();}
00220 };
00221
00222 template<typename T>
00223 static void __validate_service_class_helper() {
00224 __validate_service_class_helper<T::t_interface_parent>();
00225 }
00226
00227 template<>
00228 static void __validate_service_class_helper<service_base>() {}
00229
00230
00231 #include "service_impl.h"
00232
00233 class NOVTABLE service_factory_base {
00234 protected:
00235 inline service_factory_base(const GUID & p_guid) : m_guid(p_guid) {PFC_ASSERT(!core_api::are_services_available());__internal__next=__internal__list;__internal__list=this;}
00236 inline ~service_factory_base() {PFC_ASSERT(!core_api::are_services_available());}
00237 public:
00238 inline const GUID & get_class_guid() const {return m_guid;}
00239
00240 static service_class_ref enum_find_class(const GUID & p_guid);
00241 static bool enum_create(service_ptr_t<service_base> & p_out,service_class_ref p_class,t_size p_index);
00242 static t_size enum_get_count(service_class_ref p_class);
00243
00244 inline static bool is_service_present(const GUID & g) {return enum_get_count(enum_find_class(g))>0;}
00245
00247 virtual void instance_create(service_ptr_t<service_base> & p_out) = 0;
00248
00250 static service_factory_base *__internal__list;
00252 service_factory_base * __internal__next;
00253 private:
00254 const GUID & m_guid;
00255 };
00256
00257
00258 template<typename B>
00259 class service_factory_base_t : public service_factory_base {
00260 public:
00261 service_factory_base_t() : service_factory_base(B::class_guid) {
00262 pfc::assert_same_type<B,B::t_interface_entrypoint>();
00263 }
00264
00265 };
00266
00267
00268
00269
00270 template<class T> static bool service_enum_create_t(service_ptr_t<T> & p_out,t_size p_index) {
00271 pfc::assert_same_type<T,T::t_interface_entrypoint>();
00272 service_ptr_t<service_base> ptr;
00273 if (service_factory_base::enum_create(ptr,service_factory_base::enum_find_class(T::class_guid),p_index)) {
00274 p_out = static_cast<T*>(ptr.get_ptr());
00275 return true;
00276 } else {
00277 p_out.release();
00278 return false;
00279 }
00280 }
00281
00282 template<typename T> class service_class_helper_t {
00283 public:
00284 service_class_helper_t() : m_class(service_factory_base::enum_find_class(T::class_guid)) {
00285 pfc::assert_same_type<T,T::t_interface_entrypoint>();
00286 }
00287 t_size get_count() const {
00288 return service_factory_base::enum_get_count(m_class);
00289 }
00290
00291 bool create(service_ptr_t<T> & p_out,t_size p_index) const {
00292 service_ptr_t<service_base> temp;
00293 if (!service_factory_base::enum_create(temp,m_class,p_index)) return false;
00294 p_out.__unsafe_set(static_cast<T*>(temp.__unsafe_detach()));
00295 return true;
00296 }
00297
00298 service_ptr_t<T> create(t_size p_index) const {
00299 service_ptr_t<T> temp;
00300 if (!create(temp,p_index)) throw pfc::exception_bug_check();
00301 return temp;
00302 }
00303 private:
00304 service_class_ref m_class;
00305 };
00306
00307 template<typename T> static void standard_api_create_t(service_ptr_t<T> & p_out) {
00308 if (pfc::is_same_type<T,T::t_interface_entrypoint>::value) {
00309 service_class_helper_t<T::t_interface_entrypoint> helper;
00310 switch(helper.get_count()) {
00311 case 0:
00312 throw exception_service_not_found();
00313 case 1:
00314 if (!helper.create(reinterpret_cast<service_ptr_t<T::t_interface_entrypoint>&>(p_out),0)) throw pfc::exception_bug_check();
00315 break;
00316 default:
00317 throw exception_service_duplicated();
00318 }
00319 } else {
00320 service_ptr_t<T::t_interface_entrypoint> temp;
00321 standard_api_create_t(temp);
00322 if (!temp->service_query_t(p_out)) throw exception_service_extension_not_found();
00323 }
00324 }
00325
00326 template<typename T> static service_ptr_t<T> standard_api_create_t() {
00327 service_ptr_t<T> temp;
00328 standard_api_create_t(temp);
00329 return temp;
00330 }
00331
00336 template<typename t_interface>
00337 class static_api_ptr_t {
00338 public:
00339 static_api_ptr_t() {
00340 standard_api_create_t(m_ptr);
00341 }
00342 service_obscure_refcounting<t_interface>* operator->() const {return service_obscure_refcounting_cast(m_ptr.get_ptr());}
00343 t_interface* get_ptr() const {return m_ptr.get_ptr();}
00344 private:
00345 service_ptr_t<t_interface> m_ptr;
00346 };
00347
00349 template<typename T> class service_instance_array_t {
00350 public:
00351 typedef service_ptr_t<T> t_ptr;
00352 service_instance_array_t() {
00353 service_class_helper_t<T> helper;
00354 const t_size count = helper.get_count();
00355 m_data.set_size(count);
00356 for(t_size n=0;n<count;n++) m_data[n] = helper.create(n);
00357 }
00358
00359 t_size get_size() const {return m_data.get_size();}
00360 const t_ptr & operator[](t_size p_index) const {return m_data[p_index];}
00361
00362
00363 t_ptr & operator[](t_size p_index) {return m_data[p_index];}
00364 private:
00365 pfc::array_t<t_ptr> m_data;
00366 };
00367
00368 template<typename t_interface>
00369 class service_enum_t {
00370 public:
00371 service_enum_t() : m_index(0) {
00372 pfc::assert_same_type<t_interface,typename t_interface::t_interface_entrypoint>();
00373 }
00374 void reset() {m_index = 0;}
00375
00376 template<typename t_query>
00377 bool first(service_ptr_t<t_query> & p_out) {
00378 reset();
00379 return next(p_out);
00380 }
00381
00382 template<typename t_query>
00383 bool next(service_ptr_t<t_query> & p_out) {
00384 pfc::assert_same_type<typename t_query::t_interface_entrypoint,t_interface>();
00385 if (pfc::is_same_type<t_query,t_interface>::value) {
00386 return __next(reinterpret_cast<service_ptr_t<t_interface>&>(p_out));
00387 } else {
00388 service_ptr_t<t_interface> temp;
00389 while(__next(temp)) {
00390 if (temp->service_query_t(p_out)) return true;
00391 }
00392 return false;
00393 }
00394 }
00395
00396 private:
00397 bool __next(service_ptr_t<t_interface> & p_out) {
00398 return m_helper.create(p_out,m_index++);
00399 }
00400 unsigned m_index;
00401 service_class_helper_t<t_interface> m_helper;
00402 };
00403
00404 template<typename T>
00405 class service_factory_t : public service_factory_base_t<typename T::t_interface_entrypoint> {
00406 public:
00407 void instance_create(service_ptr_t<service_base> & p_out) {
00408 p_out = pfc::safe_cast<service_base*>(pfc::safe_cast<typename T::t_interface_entrypoint*>(pfc::safe_cast<T*>( new service_impl_t<T> )));
00409 }
00410 };
00411
00412 template<typename T>
00413 class service_factory_single_t : public service_factory_base_t<typename T::t_interface_entrypoint> {
00414 service_impl_single_t<T> g_instance;
00415 public:
00416 TEMPLATE_CONSTRUCTOR_FORWARD_FLOOD(service_factory_single_t,g_instance)
00417
00418 void instance_create(service_ptr_t<service_base> & p_out) {
00419 p_out = pfc::safe_cast<service_base*>(pfc::safe_cast<typename T::t_interface_entrypoint*>(pfc::safe_cast<T*>(&g_instance)));
00420 }
00421
00422 inline T& get_static_instance() {return g_instance;}
00423 };
00424
00425 template<typename T>
00426 class service_factory_single_ref_t : public service_factory_base_t<typename T::t_interface_entrypoint>
00427 {
00428 private:
00429 T & instance;
00430 public:
00431 service_factory_single_ref_t(T& param) : instance(param) {}
00432
00433 void instance_create(service_ptr_t<service_base> & p_out) {
00434 p_out = pfc::safe_cast<service_base*>(pfc::safe_cast<typename T::t_interface_entrypoint*>(pfc::safe_cast<T*>(&instance)));
00435 }
00436
00437 inline T& get_static_instance() {return instance;}
00438 };
00439
00440
00441 template<typename T>
00442 class service_factory_single_transparent_t : public service_factory_base_t<typename T::t_interface_entrypoint>, public service_impl_single_t<T>
00443 {
00444 public:
00445 TEMPLATE_CONSTRUCTOR_FORWARD_FLOOD(service_factory_single_transparent_t,service_impl_single_t<T>)
00446
00447 void instance_create(service_ptr_t<service_base> & p_out) {
00448 p_out = pfc::safe_cast<service_base*>(pfc::safe_cast<typename T::t_interface_entrypoint*>(pfc::safe_cast<T*>(this)));
00449 }
00450
00451 inline T& get_static_instance() {return *(T*)this;}
00452 };
00453
00454 #endif