foobar2000 SDK  2015-01-14
service.h
Go to the documentation of this file.
1 #ifndef _foobar2000_sdk_service_h_included_
2 #define _foobar2000_sdk_service_h_included_
3 
4 typedef const void* service_class_ref;
5 
6 PFC_DECLARE_EXCEPTION(exception_service_not_found,pfc::exception,"Service not found");
7 PFC_DECLARE_EXCEPTION(exception_service_extension_not_found,pfc::exception,"Service extension not found");
8 PFC_DECLARE_EXCEPTION(exception_service_duplicated,pfc::exception,"Service duplicated");
9 
10 #ifdef _MSC_VER
11 #define FOOGUIDDECL __declspec(selectany)
12 #else
13 #define FOOGUIDDECL
14 #endif
15 
16 
17 #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}};
18 #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}};
19 
21 template<typename T> class service_obscure_refcounting : public T {
22 private:
23  int service_add_ref() throw();
24  int service_release() throw();
25 };
26 
28 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);}
29 
30 //Must be templated instead of taking service_base* because of multiple inheritance issues.
31 template<typename T> static void service_release_safe(T * p_ptr) throw() {
32  if (p_ptr != NULL) PFC_ASSERT_NO_EXCEPTION( p_ptr->service_release() );
33 }
34 
35 //Must be templated instead of taking service_base* because of multiple inheritance issues.
36 template<typename T> static void service_add_ref_safe(T * p_ptr) throw() {
37  if (p_ptr != NULL) PFC_ASSERT_NO_EXCEPTION( p_ptr->service_add_ref() );
38 }
39 
40 class service_base;
41 
42 template<typename T>
44 public:
45  inline T* get_ptr() const throw() {return m_ptr;}
46 protected:
47  T * m_ptr;
48 };
49 
50 // forward declaration
51 template<typename T> class service_nnptr_t;
52 
54 template<typename T>
55 class service_ptr_t : public service_ptr_base_t<T> {
56 private:
58 
59  template<typename t_source> void _init(t_source * in) throw() {
60  this->m_ptr = in;
61  if (this->m_ptr) this->m_ptr->service_add_ref();
62  }
63  template<typename t_source> void _init(t_source && in) throw() {
64  this->m_ptr = in.detach();
65  }
66 public:
67  service_ptr_t() throw() {this->m_ptr = NULL;}
68  service_ptr_t(T * p_ptr) throw() {_init(p_ptr);}
69  service_ptr_t(const t_self & p_source) throw() {_init(p_source.get_ptr());}
70  service_ptr_t(t_self && p_source) throw() {_init(std::move(p_source));}
71  template<typename t_source> service_ptr_t(t_source * p_ptr) throw() {_init(p_ptr);}
72  template<typename t_source> service_ptr_t(const service_ptr_base_t<t_source> & p_source) throw() {_init(p_source.get_ptr());}
73  template<typename t_source> service_ptr_t(const service_nnptr_t<t_source> & p_source) throw() { this->m_ptr = p_source.get_ptr(); this->m_ptr->service_add_ref(); }
74  template<typename t_source> service_ptr_t(service_ptr_t<t_source> && p_source) throw() { _init(std::move(p_source)); }
75 
77 
78  template<typename t_source>
79  void copy(t_source * p_ptr) throw() {
80  service_add_ref_safe(p_ptr);
82  this->m_ptr = pfc::safe_ptr_cast<T>(p_ptr);
83  }
84 
85  template<typename t_source>
86  void copy(const service_ptr_base_t<t_source> & p_source) throw() {copy(p_source.get_ptr());}
87 
88  template<typename t_source>
89  void copy(service_ptr_t<t_source> && p_source) throw() {attach(p_source.detach());}
90 
91 
92  inline const t_self & operator=(const t_self & p_source) throw() {copy(p_source); return *this;}
93  inline const t_self & operator=(t_self && p_source) throw() {copy(std::move(p_source)); return *this;}
94  inline const t_self & operator=(T * p_ptr) throw() {copy(p_ptr); return *this;}
95 
96  template<typename t_source> inline t_self & operator=(const service_ptr_base_t<t_source> & p_source) throw() {copy(p_source); return *this;}
97  template<typename t_source> inline t_self & operator=(service_ptr_t<t_source> && p_source) throw() {copy(std::move(p_source)); return *this;}
98  template<typename t_source> inline t_self & operator=(t_source * p_ptr) throw() {copy(p_ptr); return *this;}
99 
100  template<typename t_source> inline t_self & operator=(const service_nnptr_t<t_source> & p_ptr) throw() {
102  t_source * ptr = p_ptr.get_ptr();
103  ptr->service_add_ref();
104  this->m_ptr = ptr;
105  return *this;
106  }
107 
108 
109  inline void release() throw() {
111  this->m_ptr = NULL;
112  }
113 
114 
115  inline service_obscure_refcounting<T>* operator->() const throw() {PFC_ASSERT(this->m_ptr != NULL);return service_obscure_refcounting_cast(this->m_ptr);}
116 
117  inline T* get_ptr() const throw() {return this->m_ptr;}
118 
119  inline bool is_valid() const throw() {return this->m_ptr != NULL;}
120  inline bool is_empty() const throw() {return this->m_ptr == NULL;}
121 
122  inline bool operator==(const service_ptr_base_t<T> & p_item) const throw() {return this->m_ptr == p_item.get_ptr();}
123  inline bool operator!=(const service_ptr_base_t<T> & p_item) const throw() {return this->m_ptr != p_item.get_ptr();}
124 
125  inline bool operator>(const service_ptr_base_t<T> & p_item) const throw() {return this->m_ptr > p_item.get_ptr();}
126  inline bool operator<(const service_ptr_base_t<T> & p_item) const throw() {return this->m_ptr < p_item.get_ptr();}
127 
128  inline bool operator==(T * p_item) const throw() {return this->m_ptr == p_item;}
129  inline bool operator!=(T * p_item) const throw() {return this->m_ptr != p_item;}
130 
131  inline bool operator>(T * p_item) const throw() {return this->m_ptr > p_item;}
132  inline bool operator<(T * p_item) const throw() {return this->m_ptr < p_item;}
133 
134  template<typename t_other>
135  inline t_self & operator<<(service_ptr_t<t_other> & p_source) throw() {attach(p_source.detach());return *this;}
136  template<typename t_other>
137  inline t_self & operator>>(service_ptr_t<t_other> & p_dest) throw() {p_dest.attach(detach());return *this;}
138 
139 
140  inline T* _duplicate_ptr() const throw() {//should not be used ! temporary !
142  return this->m_ptr;
143  }
144 
145  inline T* detach() throw() {
146  return pfc::replace_null_t(this->m_ptr);
147  }
148 
149  template<typename t_source>
150  inline void attach(t_source * p_ptr) throw() {
152  this->m_ptr = pfc::safe_ptr_cast<T>(p_ptr);
153  }
154 
155  T & operator*() const throw() {return *this->m_ptr;}
156 
158  PFC_ASSERT( _as_base_ptr_check() );
159  return *reinterpret_cast<service_ptr_t<service_base>*>(this);
160  }
161  static bool _as_base_ptr_check() {
162  return static_cast<service_base*>((T*)NULL) == reinterpret_cast<service_base*>((T*)NULL);
163  }
164 
166  template<typename otherPtr_t>
167  void operator ^= ( otherPtr_t other ) {
168  PFC_ASSERT( other.is_valid() );
169  if (!other->cast(*this)) uBugCheck();
170  }
171 
173  template<typename otherPtr_t>
174  bool operator &= ( otherPtr_t other ) {
175  PFC_ASSERT( other.is_valid() );
176  return other->cast(*this);
177  }
178 
179 };
180 
184 template<typename T>
185 class service_nnptr_t : public service_ptr_base_t<T> {
186 private:
188 
189  template<typename t_source> void _init(t_source * in) {
190  this->m_ptr = in;
191  this->m_ptr->service_add_ref();
192  }
194 public:
195  service_nnptr_t(T * p_ptr) throw() {_init(p_ptr);}
196  service_nnptr_t(const t_self & p_source) throw() {_init(p_source.get_ptr());}
197  template<typename t_source> service_nnptr_t(t_source * p_ptr) throw() {_init(p_ptr);}
198  template<typename t_source> service_nnptr_t(const service_ptr_base_t<t_source> & p_source) throw() {_init(p_source.get_ptr());}
199 
200  template<typename t_source> service_nnptr_t(service_ptr_t<t_source> && p_source) throw() {this->m_ptr = p_source.detach();}
201 
202  ~service_nnptr_t() throw() {this->m_ptr->service_release();}
203 
204  template<typename t_source>
205  void copy(t_source * p_ptr) throw() {
206  p_ptr->service_add_ref();
207  this->m_ptr->service_release();
208  this->m_ptr = pfc::safe_ptr_cast<T>(p_ptr);
209  }
210 
211  template<typename t_source>
212  void copy(const service_ptr_base_t<t_source> & p_source) throw() {copy(p_source.get_ptr());}
213 
214 
215  inline const t_self & operator=(const t_self & p_source) throw() {copy(p_source); return *this;}
216  inline const t_self & operator=(T * p_ptr) throw() {copy(p_ptr); return *this;}
217 
218  template<typename t_source> inline t_self & operator=(const service_ptr_base_t<t_source> & p_source) throw() {copy(p_source); return *this;}
219  template<typename t_source> inline t_self & operator=(t_source * p_ptr) throw() {copy(p_ptr); return *this;}
220  template<typename t_source> inline t_self & operator=(service_ptr_t<t_source> && p_source) throw() {this->m_ptr->service_release(); this->m_ptr = p_source.detach();}
221 
222 
223  inline service_obscure_refcounting<T>* operator->() const throw() {PFC_ASSERT(this->m_ptr != NULL);return service_obscure_refcounting_cast(this->m_ptr);}
224 
225  inline T* get_ptr() const throw() {return this->m_ptr;}
226 
227  inline bool is_valid() const throw() {return true;}
228  inline bool is_empty() const throw() {return false;}
229 
230  inline bool operator==(const service_ptr_base_t<T> & p_item) const throw() {return this->m_ptr == p_item.get_ptr();}
231  inline bool operator!=(const service_ptr_base_t<T> & p_item) const throw() {return this->m_ptr != p_item.get_ptr();}
232 
233  inline bool operator>(const service_ptr_base_t<T> & p_item) const throw() {return this->m_ptr > p_item.get_ptr();}
234  inline bool operator<(const service_ptr_base_t<T> & p_item) const throw() {return this->m_ptr < p_item.get_ptr();}
235 
236  inline bool operator==(T * p_item) const throw() {return this->m_ptr == p_item;}
237  inline bool operator!=(T * p_item) const throw() {return this->m_ptr != p_item;}
238 
239  inline bool operator>(T * p_item) const throw() {return this->m_ptr > p_item;}
240  inline bool operator<(T * p_item) const throw() {return this->m_ptr < p_item;}
241 
242  inline T* _duplicate_ptr() const throw() {//should not be used ! temporary !
244  return this->m_ptr;
245  }
246 
247  T & operator*() const throw() {return *this->m_ptr;}
248 
250  PFC_ASSERT( _as_base_ptr_check() );
251  return *reinterpret_cast<service_ptr_t<service_base>*>(this);
252  }
253  static bool _as_base_ptr_check() {
254  return static_cast<service_base*>((T*)NULL) == reinterpret_cast<service_base*>((T*)NULL);
255  }
256 };
257 
258 namespace pfc {
260  public:
261  enum { realloc_safe = true, constructor_may_fail = false};
262  };
263 
264  template<typename T> class traits_t<service_ptr_t<T> > : public traits_service_ptr {};
265  template<typename T> class traits_t<service_nnptr_t<T> > : public traits_service_ptr {};
266 }
267 
268 
269 template<typename T, template<typename> class t_alloc = pfc::alloc_fast>
270 class service_list_t : public pfc::list_t<service_ptr_t<T>, t_alloc >
271 {
272 };
273 
279 #define FB2K_MAKE_SERVICE_INTERFACE(THISCLASS,PARENTCLASS) \
280  public: \
281  typedef THISCLASS t_interface; \
282  typedef PARENTCLASS t_interface_parent; \
283  \
284  static const GUID class_guid; \
285  \
286  virtual bool service_query(service_ptr_t<service_base> & p_out,const GUID & p_guid) { \
287  if (p_guid == class_guid) {p_out = this; return true;} \
288  else return PARENTCLASS::service_query(p_out,p_guid); \
289  } \
290  typedef service_ptr_t<t_interface> ptr; \
291  typedef service_nnptr_t<t_interface> nnptr; \
292  typedef ptr ref; \
293  typedef nnptr nnref; \
294  protected: \
295  THISCLASS() {} \
296  ~THISCLASS() {} \
297  private: \
298  const THISCLASS & operator=(const THISCLASS &) {throw pfc::exception_not_implemented();} \
299  THISCLASS(const THISCLASS &) {throw pfc::exception_not_implemented();} \
300  private: \
301  void __private__service_declaration_selftest() { \
302  pfc::assert_same_type<PARENTCLASS,PARENTCLASS::t_interface>(); /*parentclass must be an interface*/ \
303  __validate_service_class_helper<THISCLASS>(); /*service_base must be reachable by walking t_interface_parent*/ \
304  pfc::implicit_cast<service_base*>(this); /*this class must derive from service_base, directly or indirectly, and be implictly castable to it*/ \
305  }
306 
311 #define FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(THISCLASS) \
312  public: \
313  typedef THISCLASS t_interface_entrypoint; \
314  FB2K_MAKE_SERVICE_INTERFACE(THISCLASS,service_base)
315 
316 
317 #define FB2K_DECLARE_SERVICE_BEGIN(THISCLASS,BASECLASS) \
318  class NOVTABLE THISCLASS : public BASECLASS { \
319  FB2K_MAKE_SERVICE_INTERFACE(THISCLASS,BASECLASS); \
320  public:
321 
322 #define FB2K_DECLARE_SERVICE_END() \
323  };
324 
325 #define FB2K_DECLARE_SERVICE_ENTRYPOINT_BEGIN(THISCLASS) \
326  class NOVTABLE THISCLASS : public service_base { \
327  FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(THISCLASS) \
328  public:
329 
330 
333 class NOVTABLE service_base
334 {
335 public:
338  virtual int service_release() throw() = 0;
341  virtual int service_add_ref() throw() = 0;
344  virtual bool service_query(service_ptr_t<service_base> & p_out,const GUID & p_guid) {return false;}
345 
349  template<class T>
351  {
353  return service_query( *reinterpret_cast<service_ptr_t<service_base>*>(&p_out),T::class_guid);
354  }
356  template<typename outPtr_t>
357  bool cast( outPtr_t & outPtr ) { return service_query_t( outPtr ); }
358 
360 
361 protected:
364 private:
365  service_base(const service_base&) {throw pfc::exception_not_implemented();}
366  const service_base & operator=(const service_base&) {throw pfc::exception_not_implemented();}
367 };
368 
371 
372 template<typename T>
374  __validate_service_class_helper<typename T::t_interface_parent>();
375 }
376 
377 template<>
379 
380 
381 #include "service_impl.h"
382 
383 class NOVTABLE service_factory_base {
384 protected:
385  inline service_factory_base(const GUID & p_guid, service_factory_base * & factoryList) : m_guid(p_guid) {PFC_ASSERT(!core_api::are_services_available());__internal__next=factoryList;factoryList=this;}
387 public:
388  inline const GUID & get_class_guid() const {return m_guid;}
389 
390  static service_class_ref enum_find_class(const GUID & p_guid);
391  static bool enum_create(service_ptr_t<service_base> & p_out,service_class_ref p_class,t_size p_index);
392  static t_size enum_get_count(service_class_ref p_class);
393 
394  inline static bool is_service_present(const GUID & g) {return enum_get_count(enum_find_class(g))>0;}
395 
397  virtual void instance_create(service_ptr_t<service_base> & p_out) = 0;
398 
403 private:
404  const GUID & m_guid;
405 };
406 
407 template<typename B>
409 public:
411 };
412 
413 template<typename B>
415 public:
418  }
419 };
420 
421 template<typename T> static void _validate_service_ptr(service_ptr_t<T> const & ptr) {
422  PFC_ASSERT( ptr.is_valid() );
424  PFC_ASSERT( ptr->service_query_t(test) );
425 }
426 
427 #ifdef _DEBUG
428 #define FB2K_ASSERT_VALID_SERVICE_PTR(ptr) _validate_service_ptr(ptr)
429 #else
430 #define FB2K_ASSERT_VALID_SERVICE_PTR(ptr)
431 #endif
432 
433 template<class T> static bool service_enum_create_t(service_ptr_t<T> & p_out,t_size p_index) {
437  p_out = static_cast<T*>(ptr.get_ptr());
438  return true;
439  } else {
440  p_out.release();
441  return false;
442  }
443 }
444 
445 template<typename T> static service_class_ref _service_find_class() {
447  return service_factory_base::enum_find_class(T::class_guid);
448 }
449 
450 template<typename what>
452  /*if (out._as_base_ptr_check()) {
453  const bool state = service_factory_base::enum_create(out._as_base_ptr(), servClass, index);
454  if (state) { FB2K_ASSERT_VALID_SERVICE_PTR(out); }
455  return state;
456  } else */{
457  service_ptr temp;
458  const bool state = service_factory_base::enum_create(temp, servClass, index);
459  if (state) {
460  out.attach( static_cast<what*>( temp.detach() ) );
461  FB2K_ASSERT_VALID_SERVICE_PTR( out );
462  }
463  return state;
464  }
465 }
466 
467 template<typename T> class service_class_helper_t {
468 public:
469  service_class_helper_t() : m_class(service_factory_base::enum_find_class(T::class_guid)) {
471  }
472  t_size get_count() const {
474  }
475 
476  bool create(service_ptr_t<T> & p_out,t_size p_index) const {
477  return _service_instantiate_helper(p_out, m_class, p_index);
478  }
479 
480  service_ptr_t<T> create(t_size p_index) const {
481  service_ptr_t<T> temp;
482  if (!create(temp,p_index)) uBugCheck();
483  return temp;
484  }
486 private:
488 };
489 
490 void _standard_api_create_internal(service_ptr & out, const GUID & classID);
491 
492 template<typename T> inline void standard_api_create_t(service_ptr_t<T> & p_out) {
494  _standard_api_create_internal(p_out._as_base_ptr(), T::class_guid);
495  FB2K_ASSERT_VALID_SERVICE_PTR(p_out);
496  } else {
498  standard_api_create_t(temp);
499  if (!temp->service_query_t(p_out)) throw exception_service_extension_not_found();
500  }
501 }
502 
503 template<typename T> inline void standard_api_create_t(T* & p_out) {
504  p_out = NULL;
505  standard_api_create_t( *reinterpret_cast< service_ptr_t<T> * >( & p_out ) );
506 }
507 
508 template<typename T> inline service_ptr_t<T> standard_api_create_t() {
509  service_ptr_t<T> temp;
510  standard_api_create_t(temp);
511  return temp;
512 }
513 
514 template<typename T>
515 inline bool static_api_test_t() {
516  typedef typename T::t_interface_entrypoint EP;
518  if (helper.get_count() != 1) return false;
521  if (!helper.create(0)->service_query_t(t)) return false;
522  }
523  return true;
524 }
525 
526 #define FB2K_API_AVAILABLE(API) static_api_test_t<API>()
527 
532 template<typename t_interface>
534 private:
536 public:
539  }
541  t_interface * get_ptr() const {return m_ptr;}
542  ~static_api_ptr_t() {m_ptr->service_release();}
543 
544  static_api_ptr_t(const t_self & in) {
545  m_ptr = in.m_ptr; m_ptr->service_add_ref();
546  }
547  const t_self & operator=(const t_self & in) {return *this;} //obsolete, each instance should carry the same pointer
548 private:
549  t_interface * m_ptr;
550 };
551 
553 template<typename T> class service_instance_array_t {
554 public:
558  const t_size count = helper.get_count();
559  m_data.set_size(count);
560  for(t_size n=0;n<count;n++) m_data[n] = helper.create(n);
561  }
562 
563  t_size get_size() const {return m_data.get_size();}
564  const t_ptr & operator[](t_size p_index) const {return m_data[p_index];}
565 
566  //nonconst version to allow sorting/bsearching; do not abuse
567  t_ptr & operator[](t_size p_index) {return m_data[p_index];}
568 private:
570 };
571 
572 template<typename t_interface>
574 public:
577  }
578  void reset() {m_index = 0;}
579 
580  template<typename t_query>
582  reset();
583  return next(p_out);
584  }
585 
586  template<typename t_query>
587  bool next(service_ptr_t<t_query> & p_out) {
590  return __next(reinterpret_cast<service_ptr_t<t_interface>&>(p_out));
591  } else {
593  while(__next(temp)) {
594  if (temp->service_query_t(p_out)) return true;
595  }
596  return false;
597  }
598  }
599 
600 private:
602  return m_helper.create(p_out,m_index++);
603  }
604  unsigned m_index;
606 };
607 
608 
609 
610 template<typename T>
611 class service_factory_t : public service_factory_base_t<typename T::t_interface_entrypoint> {
612 public:
614  p_out = pfc::implicit_cast<service_base*>(pfc::implicit_cast<typename T::t_interface_entrypoint*>(pfc::implicit_cast<T*>( new service_impl_t<T> )));
615  }
616 };
617 
618 
619 template<typename T>
620 class service_factory_single_t : public service_factory_base_t<typename T::t_interface_entrypoint> {
622 public:
624 
626  p_out = pfc::implicit_cast<service_base*>(pfc::implicit_cast<typename T::t_interface_entrypoint*>(pfc::implicit_cast<T*>(&g_instance)));
627  }
628 
629  inline T& get_static_instance() {return g_instance;}
630  inline const T& get_static_instance() const {return g_instance;}
631 };
632 
633 template<typename T>
634 class service_factory_single_ref_t : public service_factory_base_t<typename T::t_interface_entrypoint>
635 {
636 private:
638 public:
639  service_factory_single_ref_t(T& param) : instance(param) {}
640 
642  p_out = pfc::implicit_cast<service_base*>(pfc::implicit_cast<typename T::t_interface_entrypoint*>(pfc::implicit_cast<T*>(&instance)));
643  }
644 
645  inline T& get_static_instance() {return instance;}
646 };
647 
648 
649 template<typename T>
650 class service_factory_single_transparent_t : public service_factory_base_t<typename T::t_interface_entrypoint>, public service_impl_single_t<T>
651 {
652 public:
654 
656  p_out = pfc::implicit_cast<service_base*>(pfc::implicit_cast<typename T::t_interface_entrypoint*>(pfc::implicit_cast<T*>(this)));
657  }
658 
659  inline T& get_static_instance() {return *(T*)this;}
660 };
661 
662 
663 
664 
665 
666 
667 
668 
669 
670 
671 
672 
673 
674 
675 
676 template<typename what>
677 static bool service_by_guid_fallback(service_ptr_t<what> & out, const GUID & id) {
680  while(e.next(ptr)) {
681  if (ptr->get_guid() == id) {out = ptr; return true;}
682  }
683  return false;
684 }
685 
686 template<typename what>
688 public:
690 
691  bool ready() const {return m_inited;}
692 
693  // Caller must ensure initialize call before create() as well as thread safety of initialize() calls. The rest of this class is thread safe (only reads member data).
694  void initialize() {
695  if (m_inited) return;
698  const t_size servCount = service_factory_base::enum_get_count(m_servClass);
699  for(t_size walk = 0; walk < servCount; ++walk) {
700  service_ptr_t<what> temp;
701  if (_service_instantiate_helper(temp, m_servClass, walk)) {
702  m_order.set(temp->get_guid(), walk);
703  }
704  }
705  m_inited = true;
706  }
707 
708  bool create(service_ptr_t<what> & out, const GUID & theID) const {
709  PFC_ASSERT(m_inited);
710  t_size index;
711  if (!m_order.query(theID,index)) return false;
712  return _service_instantiate_helper(out, m_servClass, index);
713  }
714  service_ptr_t<what> create(const GUID & theID) const {
715  service_ptr_t<what> temp; if (!crete(temp,theID)) throw exception_service_not_found(); return temp;
716  }
717 
718 private:
719  volatile bool m_inited;
722 };
723 
724 template<typename what>
726 public:
728 };
730 
731 
732 template<typename what>
733 static void service_by_guid_init() {
734  service_by_guid_data<what> & data = _service_by_guid_data_container<what>::data;
735  data.initialize();
736 }
737 template<typename what>
738 static bool service_by_guid(service_ptr_t<what> & out, const GUID & theID) {
740  service_by_guid_data<what> & data = _service_by_guid_data_container<what>::data;
741  if (data.ready()) {
742  //fall-thru
743  } else if (core_api::is_main_thread()) {
744  data.initialize();
745  } else {
746 #ifdef _DEBUG
747  FB2K_DebugLog() << "Warning: service_by_guid() used in non-main thread without initialization, using fallback";
748 #endif
749  return service_by_guid_fallback(out,theID);
750  }
751  return data.create(out,theID);
752 }
753 template<typename what>
754 static service_ptr_t<what> service_by_guid(const GUID & theID) {
755  service_ptr_t<what> temp;
756  if (!service_by_guid(temp,theID)) throw exception_service_not_found();
757  return temp;
758 }
759 
760 #define FB2K_FOR_EACH_SERVICE(type, call) {service_enum_t<typename type::t_interface_entrypoint> e; service_ptr_t<type> ptr; while(e.next(ptr)) {ptr->call;} }
761 
762 
763 
765 public:
766  template<typename what> static int compare(const what & v1, const what & v2) { return pfc::compare_t(v1->get_guid(), v2->get_guid()); }
767 };
768 
769 
770 #endif //_foobar2000_sdk_service_h_included_
bool operator>(const service_ptr_base_t< T > &p_item) const
Definition: service.h:125
service_ptr_t()
Definition: service.h:67
t_self & operator=(const service_ptr_base_t< t_source > &p_source)
Definition: service.h:96
bool operator!=(const service_ptr_base_t< T > &p_item) const
Definition: service.h:123
service_ptr_t(const service_nnptr_t< t_source > &p_source)
Definition: service.h:73
service_factory_base(const GUID &p_guid, service_factory_base *&factoryList)
Definition: service.h:385
bool create(service_ptr_t< what > &out, const GUID &theID) const
Definition: service.h:708
t_interface * get_ptr() const
Definition: service.h:541
Template implementing reference-counting features of service_base. Intended for dynamic instantiation...
Definition: service_impl.h:4
static bool service_by_guid(service_ptr_t< what > &out, const GUID &theID)
Definition: service.h:738
const t_self & operator=(const t_self &in)
Definition: service.h:547
const t_self & operator=(T *p_ptr)
Definition: service.h:216
void reset()
Definition: service.h:578
service_ptr_t(const service_ptr_base_t< t_source > &p_source)
Definition: service.h:72
static bool service_enum_create_t(service_ptr_t< T > &p_out, t_size p_index)
Definition: service.h:433
void copy(const service_ptr_base_t< t_source > &p_source)
Definition: service.h:86
Definition: pfc.h:53
service_ptr_t< T > create(t_size p_index) const
Definition: service.h:480
static_api_ptr_t(const t_self &in)
Definition: service.h:544
const T & get_static_instance() const
Definition: service.h:630
bool is_empty() const
Definition: service.h:120
T * get_ptr() const
Definition: service.h:117
bool operator==(T *p_item) const
Definition: service.h:128
service_nnptr_t(const service_ptr_base_t< t_source > &p_source)
Definition: service.h:198
const t_self & operator=(T *p_ptr)
Definition: service.h:94
t_size get_size() const
Definition: service.h:563
t_type replace_null_t(t_type &p_var)
Definition: primitives.h:688
virtual bool service_query(service_ptr_t< service_base > &p_out, const GUID &p_guid)
Queries whether the object supports specific interface and retrieves a pointer to that interface...
Definition: service.h:344
service_class_helper_t< t_interface > m_helper
Definition: service.h:605
TEMPLATE_CONSTRUCTOR_FORWARD_FLOOD(service_factory_single_transparent_t, service_impl_single_t< T >) void instance_create(service_ptr_t< service_base > &p_out)
Definition: service.h:653
void __validate_service_class_helper< service_base >()
Definition: service.h:378
bool first(service_ptr_t< t_query > &p_out)
Definition: service.h:581
service_impl_single_t< T > g_instance
Definition: service.h:621
~service_base()
Definition: service.h:363
service_ptr_t(const t_self &p_source)
Definition: service.h:69
service_factory_single_ref_t(T &param)
Definition: service.h:639
void copy(t_source *p_ptr)
Definition: service.h:205
bool operator>(T *p_item) const
Definition: service.h:131
Special hack to ensure errors when someone tries to ->service_add_ref()/->service_release() on a serv...
Definition: service.h:21
TEMPLATE_CONSTRUCTOR_FORWARD_FLOOD(service_factory_single_t, g_instance) void instance_create(service_ptr_t< service_base > &p_out)
Definition: service.h:623
service_obscure_refcounting< t_interface > * operator->() const
Definition: service.h:540
void standard_api_create_t(service_ptr_t< T > &p_out)
Definition: service.h:492
t_ret * safe_ptr_cast(t_param *p_param)
Definition: primitives.h:185
static_api_ptr_t< t_interface > t_self
Definition: service.h:535
static service_obscure_refcounting< T > * service_obscure_refcounting_cast(T *p_source)
Converts a service interface pointer to a pointer that obscures service counter functionality.
Definition: service.h:28
bool __next(service_ptr_t< t_interface > &p_out)
Definition: service.h:601
t_self & operator=(const service_ptr_base_t< t_source > &p_source)
Definition: service.h:218
service_class_ref m_servClass
Definition: service.h:721
Helper; simulates array with instance of each available implementation of given service class...
Definition: service.h:553
Template implementing dummy version of reference-counting features of service_base. Intended for static/local/member instantiation: "static service_impl_single_t myvar(params);". Because reference counting features are disabled (dummy reference counter), code instantiating it is responsible for deleting it as well as ensuring that no references are active when the object gets deleted. Note that some constructor parameters such as NULL will need explicit typecasts to ensure correctly guessed types for constructor function template (null string needs to be (const char*)NULL rather than just NULL, etc).
Definition: service_impl.h:44
pfc::map_t< GUID, t_size > m_order
Definition: service.h:720
const t_self & operator=(t_self &&p_source)
Definition: service.h:93
void operator^=(otherPtr_t other)
Forced cast operator - obtains a valid service pointer to the expected class or crashes the app if su...
Definition: service.h:167
service_ptr_t< T > t_self
Definition: service.h:57
t_self & operator>>(service_ptr_t< t_other > &p_dest)
Definition: service.h:137
bool operator>(const service_ptr_base_t< T > &p_item) const
Definition: service.h:233
static service_factory_base * __internal__list
FOR INTERNAL USE ONLY.
Definition: service.h:400
service_nnptr_t(const t_self &p_source)
Definition: service.h:196
T * detach()
Definition: service.h:145
const GUID & m_guid
Definition: service.h:404
t_size get_count() const
Definition: service.h:472
service_ptr_t< what > create(const GUID &theID) const
Definition: service.h:714
service_nnptr_t(service_ptr_t< t_source > &&p_source)
Definition: service.h:200
service_nnptr_t(t_source *p_ptr)
Definition: service.h:197
unsigned m_index
Definition: service.h:604
const void * service_class_ref
Definition: service.h:4
bool is_valid() const
Definition: service.h:119
t_self & operator=(service_ptr_t< t_source > &&p_source)
Definition: service.h:220
bool operator==(const service_ptr_base_t< T > &p_item) const
Definition: service.h:122
const t_self & operator=(const t_self &p_source)
Definition: service.h:92
bool static_api_test_t()
Definition: service.h:515
static bool _as_base_ptr_check()
Definition: service.h:253
T * _duplicate_ptr() const
Definition: service.h:140
PFC_DECLARE_EXCEPTION(exception_service_not_found, pfc::exception,"Service not found")
t_self & operator=(service_ptr_t< t_source > &&p_source)
Definition: service.h:97
bool operator==(const service_ptr_base_t< T > &p_item) const
Definition: service.h:230
const t_self & operator=(const t_self &p_source)
Definition: service.h:215
static t_size enum_get_count(service_class_ref p_class)
Definition: service.cpp:18
bool test(const char *str, const char *pattern, bool b_separate_by_semicolon=false)
Definition: wildcard.cpp:26
service_base t_interface
Definition: service.h:359
bool create(service_ptr_t< T > &p_out, t_size p_index) const
Definition: service.h:476
service_ptr_t(t_self &&p_source)
Definition: service.h:70
~service_ptr_t()
Definition: service.h:76
service_class_ref m_class
Definition: service.h:487
Autopointer class to be used with all services. Manages reference counter calls behind-the-scenes. This assumes that the pointers are valid all the time (can't point to null). Mainly intended to be used for scenarios where null pointers are not valid and relevant code should crash ASAP if somebody passes invalid pointers around. You want to use service_ptr_t<> rather than service_nnptr_t<> most of the time.
Definition: service.h:51
service_nnptr_t< service_base > service_nnptr
Definition: service.h:370
const GUID & get_class_guid() const
Definition: service.h:388
T * get_ptr() const
Definition: service.h:225
size_t t_size
Definition: int_types.h:48
service_ptr_t(t_source *p_ptr)
Definition: service.h:71
void copy(service_ptr_t< t_source > &&p_source)
Definition: service.h:89
void crash()
Definition: other.cpp:105
static service_class_ref _service_find_class()
Definition: service.h:445
void release()
Definition: service.h:109
static void service_add_ref_safe(T *p_ptr)
Definition: service.h:36
t_self & operator=(const service_nnptr_t< t_source > &p_ptr)
Definition: service.h:100
Base class for all service classes. Provides interfaces for reference counter and querying for differ...
Definition: service.h:333
int compare_t(const hasher_md5_result &p_item1, const hasher_md5_result &p_item2)
Definition: hasher_md5.h:20
void _init(t_source *in)
Definition: service.h:189
static void service_by_guid_init()
Definition: service.h:733
t_interface * m_ptr
Definition: service.h:549
service_nnptr_t(T *p_ptr)
Definition: service.h:195
void instance_create(service_ptr_t< service_base > &p_out)
Throws std::bad_alloc or another exception on failure.
Definition: service.h:641
pfc::array_t< t_ptr > m_data
Definition: service.h:569
bool is_empty() const
Definition: service.h:228
t_self & operator=(t_source *p_ptr)
Definition: service.h:98
void _standard_api_create_internal(service_ptr &out, const GUID &classID)
Definition: service.cpp:48
void _init(t_source &&in)
Definition: service.h:63
service_ptr_t< service_base > & _as_base_ptr()
Definition: service.h:249
const t_ptr & operator[](t_size p_index) const
Definition: service.h:564
static void service_release_safe(T *p_ptr)
Definition: service.h:31
static service_class_ref enum_find_class(const GUID &p_guid)
Definition: service.cpp:6
static service_factory_base *& factory_list()
Definition: service.h:410
service_ptr_t< service_base > service_ptr
Definition: service.h:369
void set(const _t_key &p_key, const _t_value &p_value)
Definition: map.h:22
bool operator==(T *p_item) const
Definition: service.h:236
T * _duplicate_ptr() const
Definition: service.h:242
bool is_valid() const
Definition: service.h:227
service_obscure_refcounting< T > * operator->() const
Definition: service.h:115
std::exception exception
Definition: primitives.h:193
static void _validate_service_ptr(service_ptr_t< T > const &ptr)
Definition: service.h:421
bool service_query_t(service_ptr_t< T > &p_out)
Queries whether the object supports specific interface and retrieves a pointer to that interface...
Definition: service.h:350
service_nnptr_t< T > t_self
Definition: service.h:187
service_base()
Definition: service.h:362
void instance_create(service_ptr_t< service_base > &p_out)
Throws std::bad_alloc or another exception on failure.
Definition: service.h:613
t_ret implicit_cast(t_ret val)
Definition: primitives.h:182
T & operator*() const
Definition: service.h:155
void attach(t_source *p_ptr)
Definition: service.h:150
static bool enum_create(service_ptr_t< service_base > &p_out, service_class_ref p_class, t_size p_index)
Definition: service.cpp:12
bool operator!=(const service_ptr_base_t< T > &p_item) const
Definition: service.h:231
void __validate_service_class_helper()
Definition: service.h:373
Autopointer class to be used with all services. Manages reference counter calls behind-the-scenes.
Definition: service.h:55
service_factory_base * __internal__next
FOR INTERNAL USE ONLY.
Definition: service.h:402
service_ptr_t(T *p_ptr)
Definition: service.h:68
t_self & operator=(t_source *p_ptr)
Definition: service.h:219
static int compare(const what &v1, const what &v2)
Definition: service.h:766
bool operator<(T *p_item) const
Definition: service.h:240
bool operator!=(T *p_item) const
Definition: service.h:129
bool is_main_thread()
Returns true if calling thread is main app thread, false otherwise.
bool operator&=(otherPtr_t other)
Conditional cast operator - attempts to obtain a vaild service pointer to the expected class; returns...
Definition: service.h:174
bool cast(outPtr_t &outPtr)
New shortened version, same as service_query_t.
Definition: service.h:357
volatile bool m_inited
Definition: service.h:719
service_obscure_refcounting< T > * operator->() const
Definition: service.h:223
const service_base & operator=(const service_base &)
Definition: service.h:366
T & operator*() const
Definition: service.h:247
Helper template used to easily access core services. Usage: static_api_ptr_t api; api->doso...
Definition: service.h:533
static bool is_service_present(const GUID &g)
Definition: service.h:394
PFC_NORETURN void SHARED_EXPORT uBugCheck()
static bool service_by_guid_fallback(service_ptr_t< what > &out, const GUID &id)
Definition: service.h:677
bool ready() const
Definition: service.h:691
virtual void instance_create(service_ptr_t< service_base > &p_out)=0
Throws std::bad_alloc or another exception on failure.
service_ptr_t< service_base > & _as_base_ptr()
Definition: service.h:157
bool operator>(T *p_item) const
Definition: service.h:239
service_ptr_t(service_ptr_t< t_source > &&p_source)
Definition: service.h:74
bool next(service_ptr_t< t_query > &p_out)
Definition: service.h:587
void copy(const service_ptr_base_t< t_source > &p_source)
Definition: service.h:212
static bool _service_instantiate_helper(service_ptr_t< what > &out, service_class_ref servClass, t_size index)
Definition: service.h:451
bool are_services_available()
Tests whether services are available at this time. They are not available only during DLL startup or ...
T * get_ptr() const
Definition: service.h:45
service_base(const service_base &)
Definition: service.h:365
service_ptr_t< T > t_ptr
Definition: service.h:555
static service_by_guid_data< what > data
Definition: service.h:727
bool operator!=(T *p_item) const
Definition: service.h:237
bool operator<(T *p_item) const
Definition: service.h:132
t_ptr & operator[](t_size p_index)
Definition: service.h:567
static bool _as_base_ptr_check()
Definition: service.h:161
void copy(t_source *p_ptr)
Definition: service.h:79
service_class_ref get_class() const
Definition: service.h:485
void _init(t_source *in)
Definition: service.h:59
bool query(const _t_key &p_key, _t_value &p_value) const
Definition: map.h:44