annotate foosdk/sdk/foobar2000/SDK/service.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #pragma once
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include <utility> // std::forward
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 typedef const void* service_class_ref;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 PFC_DECLARE_EXCEPTION(exception_service_not_found,pfc::exception,"Service not found");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 PFC_DECLARE_EXCEPTION(exception_service_extension_not_found,pfc::exception,"Service extension not found");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 PFC_DECLARE_EXCEPTION(exception_service_duplicated,pfc::exception,"Service duplicated");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 #ifdef _MSC_VER
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 #define FOOGUIDDECL __declspec(selectany)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 #define FOOGUIDDECL
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 #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}};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 #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}};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 //Must be templated instead of taking service_base* because of multiple inheritance issues.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 template<typename T> static void service_release_safe(T * p_ptr) throw() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 if (p_ptr != NULL) PFC_ASSERT_NO_EXCEPTION( p_ptr->service_release() );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 //Must be templated instead of taking service_base* because of multiple inheritance issues.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 template<typename T> static void service_add_ref_safe(T * p_ptr) throw() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 if (p_ptr != NULL) PFC_ASSERT_NO_EXCEPTION( p_ptr->service_add_ref() );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 class service_base;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 template<typename T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 class service_ptr_base_t {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 typedef service_ptr_base_t<T> self_t;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 inline T* get_ptr() const throw() {return m_ptr;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 typedef T obj_t;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 inline bool operator==(const self_t & other) const noexcept {return this->m_ptr == other.m_ptr;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 inline bool operator!=(const self_t & other) const noexcept {return this->m_ptr != other.m_ptr;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 inline bool operator>(const self_t & other) const noexcept {return this->m_ptr > other.m_ptr;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 inline bool operator<(const self_t & other) const noexcept {return this->m_ptr < other.m_ptr;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 inline bool operator==(T * other) const noexcept {return this->m_ptr == other;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 inline bool operator!=(T * other) const noexcept {return this->m_ptr != other;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 inline bool operator>(T * other) const noexcept {return this->m_ptr > other;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 inline bool operator<(T * other) const noexcept {return this->m_ptr < other;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 T * m_ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57 // forward declaration
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 template<typename T> class service_nnptr_t;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60 template<typename T> struct forced_cast_t {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 T* ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 //! Autopointer class to be used with all services. Manages reference counter calls behind-the-scenes.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 template<typename T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 class service_ptr_t : public service_ptr_base_t<T> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 typedef service_ptr_t<T> t_self;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 template<typename t_source> void _init(t_source * in) throw() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 this->m_ptr = in;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 if (this->m_ptr) this->m_ptr->service_add_ref();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 template<typename t_source> void _init(t_source && in) throw() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75 this->m_ptr = in.detach();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 service_ptr_t() throw() {this->m_ptr = NULL;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 service_ptr_t(T * p_ptr) throw() {_init(p_ptr);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 service_ptr_t(const t_self & p_source) throw() {_init(p_source.get_ptr());}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81 service_ptr_t(t_self && p_source) throw() {_init(std::move(p_source));}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 template<typename t_source> service_ptr_t(t_source * p_ptr) throw() {_init(p_ptr);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 template<typename t_source> service_ptr_t(const service_ptr_base_t<t_source> & p_source) throw() {_init(p_source.get_ptr());}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 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(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 template<typename t_source> service_ptr_t(service_ptr_t<t_source> && p_source) throw() { _init(std::move(p_source)); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 ~service_ptr_t() throw() {service_release_safe(this->m_ptr);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 template<typename t_source>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 void copy(t_source * p_ptr) throw() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 service_add_ref_safe(p_ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 service_release_safe(this->m_ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 this->m_ptr = pfc::safe_ptr_cast<T>(p_ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 template<typename t_source>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 void copy(const service_ptr_base_t<t_source> & p_source) throw() {copy(p_source.get_ptr());}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 template<typename t_source>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 void copy(service_ptr_t<t_source> && p_source) throw() {attach(p_source.detach());}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 inline const t_self & operator=(const t_self & p_source) throw() {copy(p_source); return *this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 inline const t_self & operator=(t_self && p_source) throw() {copy(std::move(p_source)); return *this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 inline const t_self & operator=(T * p_ptr) throw() {copy(p_ptr); return *this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107 template<typename t_source> inline t_self & operator=(const service_ptr_base_t<t_source> & p_source) throw() {copy(p_source); return *this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 template<typename t_source> inline t_self & operator=(service_ptr_t<t_source> && p_source) throw() {copy(std::move(p_source)); return *this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 template<typename t_source> inline t_self & operator=(t_source * p_ptr) throw() {copy(p_ptr); return *this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 template<typename t_source> inline t_self & operator=(const service_nnptr_t<t_source> & p_ptr) throw() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 service_release_safe(this->m_ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 t_source * ptr = p_ptr.get_ptr();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 ptr->service_add_ref();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 this->m_ptr = ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 return *this;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 inline void reset() throw() { release(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 inline void release() throw() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 service_release_safe(this->m_ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123 this->m_ptr = NULL;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 inline T* operator->() const throw() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 #if PFC_DEBUG
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 if (this->m_ptr == NULL) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 FB2K_DebugLog() << "service_ptr operator-> on a null pointer, type: " << T::debugServiceName();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 uBugCheck();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 return this->m_ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 inline T* get_ptr() const throw() {return this->m_ptr;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 inline bool is_valid() const throw() {return this->m_ptr != NULL;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 inline bool is_empty() const throw() {return this->m_ptr == NULL;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142 template<typename t_other>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 inline t_self & operator<<(service_ptr_t<t_other> & p_source) throw() {attach(p_source.detach());return *this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144 template<typename t_other>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 inline t_self & operator>>(service_ptr_t<t_other> & p_dest) throw() {p_dest.attach(detach());return *this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 inline T* _duplicate_ptr() const throw() {//should not be used ! temporary !
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 service_add_ref_safe(this->m_ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 return this->m_ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 inline T* detach() throw() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 return pfc::replace_null_t(this->m_ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 template<typename t_source>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158 inline void attach(t_source * p_ptr) throw() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 service_release_safe(this->m_ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160 this->m_ptr = pfc::safe_ptr_cast<T>(p_ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
163 T & operator*() const throw() {return *this->m_ptr;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
164
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
165 service_ptr_t<service_base> & _as_base_ptr() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
166 PFC_ASSERT( _as_base_ptr_check() );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
167 return *reinterpret_cast<service_ptr_t<service_base>*>(this);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
168 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
169 static bool _as_base_ptr_check() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
170 return static_cast<service_base*>((T*)NULL) == reinterpret_cast<service_base*>((T*)NULL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
171 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
172
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
173 //! Forced cast operator - obtains a valid service pointer to the expected class or crashes the app if such pointer cannot be obtained.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
174 template<typename otherPtr_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
175 void operator ^= ( otherPtr_t other ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
176 if (other.is_empty()) release();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
177 else forcedCastFrom(other);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
178 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
179 template<typename otherObj_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
180 void operator ^= ( otherObj_t * other ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
181 if (other == nullptr) release();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
182 else forcedCastFrom( other );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
183 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
184
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
185 bool testForInterface(const GUID & guid) const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
186 if (this->m_ptr == nullptr) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
187 service_ptr_t<service_base> dummy;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
188 return this->m_ptr->service_query(dummy, guid);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
189 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
190 //! Conditional cast operator - attempts to obtain a vaild service pointer to the expected class; returns true on success, false on failure.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
191 template<typename otherPtr_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
192 bool operator &= ( otherPtr_t other ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
193 if (other.is_empty()) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
194 return other->cast(*this);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
195 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
196 template<typename otherObj_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
197 bool operator &= ( otherObj_t * other ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
198 if (other == nullptr) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
199 return other->cast( *this );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
200 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
201
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
202 template<typename otherPtr_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
203 void operator=(forced_cast_t<otherPtr_t> other) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
204 if (other.ptr == NULL) release();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
205 else forcedCastFrom(other.ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
206 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
207
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
208 //! Alternate forcedCast syntax, for contexts where operator^= fails to compile. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
209 //! Usage: target = source.forcedCast();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
210 forced_cast_t<T> forcedCast() const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
211 forced_cast_t<T> r = { this->m_ptr };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
212 return r;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
213 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
214
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
215 template<typename source_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
216 void forcedCastFrom(source_t const & other) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
217 if (!other->cast(*this)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
218 FB2K_BugCheckEx("forced cast failure");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
219 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
220 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
221 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
222
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
223 //! Autopointer class to be used with all services. Manages reference counter calls behind-the-scenes. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
224 //! 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. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
225 //! You want to use service_ptr_t<> rather than service_nnptr_t<> most of the time.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
226 template<typename T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
227 class service_nnptr_t : public service_ptr_base_t<T> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
228 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
229 typedef service_nnptr_t<T> t_self;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
230
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
231 template<typename t_source> void _init(t_source * in) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
232 this->m_ptr = in;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
233 this->m_ptr->service_add_ref();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
234 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
235 service_nnptr_t() throw() {pfc::crash();}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
236 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
237 service_nnptr_t(T * p_ptr) throw() {_init(p_ptr);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
238 service_nnptr_t(const t_self & p_source) throw() {_init(p_source.get_ptr());}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
239 template<typename t_source> service_nnptr_t(t_source * p_ptr) throw() {_init(p_ptr);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
240 template<typename t_source> service_nnptr_t(const service_ptr_base_t<t_source> & p_source) throw() {_init(p_source.get_ptr());}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
241
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
242 template<typename t_source> service_nnptr_t(service_ptr_t<t_source> && p_source) throw() {this->m_ptr = p_source.detach();}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
243
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
244 ~service_nnptr_t() throw() {this->m_ptr->service_release();}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
245
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
246 template<typename t_source>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
247 void copy(t_source * p_ptr) throw() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
248 p_ptr->service_add_ref();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
249 this->m_ptr->service_release();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
250 this->m_ptr = pfc::safe_ptr_cast<T>(p_ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
251 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
252
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
253 template<typename t_source>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
254 void copy(const service_ptr_base_t<t_source> & p_source) throw() {copy(p_source.get_ptr());}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
255
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
256
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
257 inline const t_self & operator=(const t_self & p_source) throw() {copy(p_source); return *this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
258 inline const t_self & operator=(T * p_ptr) throw() {copy(p_ptr); return *this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
259
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
260 template<typename t_source> inline t_self & operator=(const service_ptr_base_t<t_source> & p_source) throw() {copy(p_source); return *this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
261 template<typename t_source> inline t_self & operator=(t_source * p_ptr) throw() {copy(p_ptr); return *this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
262 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();}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
263
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
264
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
265 inline T* operator->() const throw() {PFC_ASSERT(this->m_ptr != NULL);return this->m_ptr;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
266
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
267 inline T* get_ptr() const throw() {return this->m_ptr;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
268
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
269 inline bool is_valid() const throw() {return true;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
270 inline bool is_empty() const throw() {return false;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
271
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
272 inline T* _duplicate_ptr() const throw() {//should not be used ! temporary !
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
273 service_add_ref_safe(this->m_ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
274 return this->m_ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
275 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
276
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
277 T & operator*() const throw() {return *this->m_ptr;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
278
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
279 service_ptr_t<service_base> & _as_base_ptr() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
280 PFC_ASSERT( _as_base_ptr_check() );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
281 return *reinterpret_cast<service_ptr_t<service_base>*>(this);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
282 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
283 static bool _as_base_ptr_check() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
284 return static_cast<service_base*>((T*)NULL) == reinterpret_cast<service_base*>((T*)NULL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
285 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
286
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
287 forced_cast_t<T> forcedCast() const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
288 forced_cast_t<T> r = { this->m_ptr };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
289 return r;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
290 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
291 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
292
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
293 namespace pfc {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
294 class traits_service_ptr : public traits_default {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
295 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
296 enum { realloc_safe = true, constructor_may_fail = false};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
297 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
298
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
299 template<typename T> class traits_t<service_ptr_t<T> > : public traits_service_ptr {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
300 template<typename T> class traits_t<service_nnptr_t<T> > : public traits_service_ptr {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
301 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
302
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
303
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
304 //! For internal use, see FB2K_MAKE_SERVICE_INTERFACE
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
305 #define FB2K_MAKE_SERVICE_INTERFACE_EX(THISCLASS,PARENTCLASS,IS_CORE_API) \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
306 public: \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
307 typedef THISCLASS t_interface; \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
308 typedef PARENTCLASS t_interface_parent; \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
309 \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
310 static const GUID class_guid; \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
311 \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
312 typedef service_ptr_t<t_interface> ptr; \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
313 typedef service_nnptr_t<t_interface> nnptr; \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
314 typedef ptr ref; \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
315 typedef nnptr nnref; \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
316 static const char * debugServiceName() { return #THISCLASS; } \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
317 enum { _is_core_api = IS_CORE_API }; \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
318 protected: \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
319 THISCLASS() {} \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
320 ~THISCLASS() {} \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
321 private: \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
322 const THISCLASS & operator=(const THISCLASS &) = delete; \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
323 THISCLASS(const THISCLASS &) = delete; \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
324 private: \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
325 void _private_service_declaration_selftest() { \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
326 static_assert( pfc::is_same_type<PARENTCLASS,PARENTCLASS::t_interface>::value, "t_interface sanity" ); \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
327 static_assert( ! pfc::is_same_type<PARENTCLASS, THISCLASS>::value, "parent class sanity"); \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
328 static_assert( pfc::is_same_type<PARENTCLASS, service_base>::value || IS_CORE_API == PARENTCLASS::_is_core_api, "is_core_api sanity" ); \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
329 _validate_service_class_helper<THISCLASS>(); /*service_base must be reachable by walking t_interface_parent*/ \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
330 pfc::implicit_cast<service_base*>(this); /*this class must derive from service_base, directly or indirectly, and be implictly castable to it*/ \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
331 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
332
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
333 #define FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT_EX(THISCLASS, IS_CORE_API) \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
334 public: \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
335 typedef THISCLASS t_interface_entrypoint; \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
336 static service_enum_t<THISCLASS> enumerate() { return service_enum_t<THISCLASS>(); } \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
337 FB2K_MAKE_SERVICE_INTERFACE_EX(THISCLASS,service_base, IS_CORE_API)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
338
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
339 //! Helper macro for use when defining a service class. Generates standard features of a service, without ability to register using service_factory / enumerate using service_enum_t. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
340 //! This is used for declaring services that are meant to be instantiated by means other than service_enum_t (or non-entrypoint services), or extensions of services (including extension of entrypoint services). \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
341 //! Sample non-entrypoint declaration: class myclass : public service_base {...; FB2K_MAKE_SERVICE_INTERFACE(myclass, service_base); }; \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
342 //! Sample extension declaration: class myclass : public myotherclass {...; FB2K_MAKE_SERVICE_INTERFACE(myclass, myotherclass); }; \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
343 //! This macro is intended for use ONLY WITH INTERFACE CLASSES, not with implementation classes.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
344 #define FB2K_MAKE_SERVICE_INTERFACE(THISCLASS, PARENTCLASS) FB2K_MAKE_SERVICE_INTERFACE_EX(THISCLASS, PARENTCLASS, false)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
345
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
346 //! Helper macro for use when defining an entrypoint service class. Generates standard features of a service, including ability to register using service_factory and enumerate using service_enum. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
347 //! Sample declaration: class myclass : public service_base {...; FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(myclass); }; \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
348 //! Note that entrypoint service classes must directly derive from service_base, and not from another service class.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
349 //! This macro is intended for use ONLY WITH INTERFACE CLASSES, not with implementation classes.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
350 #define FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(THISCLASS) FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT_EX(THISCLASS, false)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
351
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
352
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
353 #define FB2K_MAKE_SERVICE_COREAPI(THISCLASS) \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
354 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT_EX( THISCLASS, true ) \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
355 public: \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
356 static ptr get() { return fb2k::std_api_get<THISCLASS>(); } \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
357 static bool tryGet(ptr & out) { return fb2k::std_api_try_get(out); } \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
358 static ptr tryGet() { ptr ret; tryGet(ret); return ret; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
359
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
360 #define FB2K_MAKE_SERVICE_COREAPI_EXTENSION(THISCLASS, BASECLASS) \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
361 FB2K_MAKE_SERVICE_INTERFACE_EX( THISCLASS, BASECLASS, true ) \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
362 public: \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
363 static ptr get() { return fb2k::std_api_get<THISCLASS>(); } \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
364 static bool tryGet(ptr & out) { return fb2k::std_api_try_get(out); } \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
365 static ptr tryGet() { ptr ret; tryGet(ret); return ret; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
366
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
367
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
368
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
369 //! Alternate way of declaring services, begin/end macros wrapping the whole class declaration
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
370 #define FB2K_DECLARE_SERVICE_BEGIN(THISCLASS,BASECLASS) \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
371 class NOVTABLE THISCLASS : public BASECLASS { \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
372 FB2K_MAKE_SERVICE_INTERFACE(THISCLASS,BASECLASS); \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
373 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
374
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
375 //! Alternate way of declaring services, begin/end macros wrapping the whole class declaration
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
376 #define FB2K_DECLARE_SERVICE_END() \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
377 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
378
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
379 //! Alternate way of declaring services, begin/end macros wrapping the whole class declaration
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
380 #define FB2K_DECLARE_SERVICE_ENTRYPOINT_BEGIN(THISCLASS) \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
381 class NOVTABLE THISCLASS : public service_base { \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
382 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(THISCLASS) \
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
383 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
384
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
385 class service_base;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
386 typedef service_ptr_t<service_base> service_ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
387 typedef service_nnptr_t<service_base> service_nnptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
388
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
389 //! Base class for all service classes.\n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
390 //! Provides interfaces for reference counter and querying for different interfaces supported by the object.\n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
391 class NOVTABLE service_base
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
392 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
393 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
394 //! Decrements reference count; deletes the object if reference count reaches zero. This is normally not called directly but managed by service_ptr_t<> template. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
395 //! Implemented by service_impl_* classes.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
396 //! @returns New reference count. For debug purposes only, in certain conditions return values may be unreliable.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
397 virtual int service_release() noexcept = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
398 //! Increments reference count. This is normally not called directly but managed by service_ptr_t<> template. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
399 //! Implemented by service_impl_* classes.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
400 //! @returns New reference count. For debug purposes only, in certain conditions return values may be unreliable.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
401 virtual int service_add_ref() noexcept = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
402 //! Queries whether the object supports specific interface and retrieves a pointer to that interface. This is normally not called directly but managed by service_query_t<> function template. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
403 //! Checks the parameter against GUIDs of interfaces supported by this object, if the GUID is one of supported interfaces, p_out is set to service_base pointer that can be static_cast<>'ed to queried interface and the method returns true; otherwise the method returns false. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
404 //! Implemented by service_impl_* classes. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
405 //! Note that service_query() implementation semantics (but not usage semantics) changed in SDK for foobar2000 1.4; they used to be auto-implemented by each service interface (via FB2K_MAKE_SERVICE_INTERFACE macro); they're now implemented in service_impl_* instead. See SDK readme for more details. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
406 virtual bool service_query(service_ptr & p_out,const GUID & p_guid) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
407
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
408 //! Queries whether the object supports specific interface and retrieves a pointer to that interface.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
409 //! @param p_out Receives pointer to queried interface on success.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
410 //! returns true on success, false on failure (interface not supported by the object).
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
411 template<class T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
412 bool service_query_t(service_ptr_t<T> & p_out)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
413 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
414 pfc::assert_same_type<T,typename T::t_interface>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
415 return service_query( *reinterpret_cast<service_ptr_t<service_base>*>(&p_out),T::class_guid);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
416 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
417 //! New shortened version, same as service_query_t.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
418 template<typename outPtr_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
419 bool cast( outPtr_t & outPtr ) { return service_query_t( outPtr ); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
420
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
421 typedef service_base t_interface;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
422 enum { _is_core_api = false };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
423
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
424 static const char * debugServiceName() {return "service_base"; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
425
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
426 static bool serviceRequiresMainThreadDestructor() { return false; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
427
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
428 service_base * as_service_base() { return this; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
429 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
430 service_base() {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
431 ~service_base() {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
432
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
433 static bool service_query_walk(service_ptr &, const GUID &, service_base *) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
434 return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
435 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
436
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
437 template<typename interface_t> static bool service_query_walk(service_ptr & out, const GUID & guid, interface_t * in) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
438 if (guid == interface_t::class_guid) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
439 out = in; return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
440 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
441 typename interface_t::t_interface_parent * chain = in;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
442 return service_query_walk(out, guid, chain);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
443 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
444 template<typename class_t> static bool handle_service_query(service_ptr & out, const GUID & guid, class_t * in) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
445 typename class_t::t_interface * in2 = in;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
446 return service_query_walk( out, guid, in2 );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
447 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
448 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
449 service_base(const service_base&) = delete;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
450 const service_base & operator=(const service_base&) = delete;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
451 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
452
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
453 template<typename T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
454 inline void _validate_service_class_helper() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
455 _validate_service_class_helper<typename T::t_interface_parent>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
456 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
457
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
458 template<>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
459 inline void _validate_service_class_helper<service_base>() {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
460
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
461
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
462 #include "service_impl.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
463
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
464 class NOVTABLE service_factory_base {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
465 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
466 inline service_factory_base(const GUID & p_guid, service_factory_base * & factoryList = __internal__list) : m_guid(p_guid) { PFC_ASSERT(!core_api::are_services_available()); __internal__next = factoryList; factoryList = this; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
467 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
468 inline const GUID & get_class_guid() const {return m_guid;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
469
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
470 static service_class_ref enum_find_class(const GUID & p_guid);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
471 static bool enum_create(service_ptr_t<service_base> & p_out,service_class_ref p_class,t_size p_index);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
472 static t_size enum_get_count(service_class_ref p_class);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
473
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
474 inline static bool is_service_present(const GUID & g) {return enum_get_count(enum_find_class(g))>0;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
475
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
476 //! Throws std::bad_alloc or another exception on failure.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
477 virtual void instance_create(service_ptr_t<service_base> & p_out) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
478
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
479 //! FOR INTERNAL USE ONLY
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
480 static service_factory_base *__internal__list;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
481 //! FOR INTERNAL USE ONLY
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
482 service_factory_base * __internal__next;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
483 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
484 const GUID & m_guid;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
485 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
486
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
487 template<typename B>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
488 class service_factory_traits {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
489 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
490 static service_factory_base * & factory_list() {return service_factory_base::__internal__list;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
491 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
492
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
493 template<typename B>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
494 class service_factory_base_t : public service_factory_base {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
495 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
496 service_factory_base_t() : service_factory_base(B::class_guid, service_factory_traits<B>::factory_list()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
497 pfc::assert_same_type<B,typename B::t_interface_entrypoint>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
498 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
499 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
500 template<typename in_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
501 static void pass_instance(service_ptr& out, in_t* in) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
502 // in_t could be multi inherited, fix multi inheritance issues here
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
503 // caller will static cast the returned service_base* to B* later on
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
504 // make sure that what we hand over supports such
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
505 service_ptr_t< B > temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
506 temp ^= in->as_service_base();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
507 out.attach(temp.detach());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
508 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
509 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
510
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
511 template<typename T> static void _validate_service_ptr(service_ptr_t<T> const & ptr) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
512 PFC_ASSERT( ptr.is_valid() );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
513 service_ptr_t<T> test;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
514 PFC_ASSERT( ptr->service_query_t(test) );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
515 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
516
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
517 #ifdef _DEBUG
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
518 #define FB2K_ASSERT_VALID_SERVICE_PTR(ptr) _validate_service_ptr(ptr)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
519 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
520 #define FB2K_ASSERT_VALID_SERVICE_PTR(ptr)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
521 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
522
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
523 template<class T> static bool service_enum_create_t(service_ptr_t<T> & p_out,t_size p_index) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
524 pfc::assert_same_type<T,typename T::t_interface_entrypoint>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
525 service_ptr_t<service_base> ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
526 if (service_factory_base::enum_create(ptr,service_factory_base::enum_find_class(T::class_guid),p_index)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
527 p_out = static_cast<T*>(ptr.get_ptr());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
528 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
529 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
530 p_out.release();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
531 return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
532 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
533 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
534
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
535 template<typename T> static service_class_ref _service_find_class() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
536 pfc::assert_same_type<T,typename T::t_interface_entrypoint>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
537 return service_factory_base::enum_find_class(T::class_guid);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
538 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
539
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
540 template<typename what>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
541 static bool _service_instantiate_helper(service_ptr_t<what> & out, service_class_ref servClass, t_size index) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
542 /*if (out._as_base_ptr_check()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
543 const bool state = service_factory_base::enum_create(out._as_base_ptr(), servClass, index);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
544 if (state) { FB2K_ASSERT_VALID_SERVICE_PTR(out); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
545 return state;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
546 } else */{
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
547 service_ptr temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
548 const bool state = service_factory_base::enum_create(temp, servClass, index);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
549 if (state) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
550 out.attach( static_cast<what*>( temp.detach() ) );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
551 FB2K_ASSERT_VALID_SERVICE_PTR( out );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
552 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
553 return state;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
554 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
555 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
556
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
557 template<typename T> class service_class_helper_t {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
558 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
559 service_class_helper_t() : m_class(service_factory_base::enum_find_class(T::class_guid)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
560 pfc::assert_same_type<T,typename T::t_interface_entrypoint>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
561 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
562 t_size get_count() const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
563 return service_factory_base::enum_get_count(m_class);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
564 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
565
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
566 bool create(service_ptr_t<T> & p_out,t_size p_index) const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
567 return _service_instantiate_helper(p_out, m_class, p_index);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
568 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
569
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
570 service_ptr_t<T> create(t_size p_index) const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
571 service_ptr_t<T> temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
572 if (!create(temp,p_index)) uBugCheck();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
573 return temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
574 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
575 service_class_ref get_class() const {return m_class;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
576 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
577 service_class_ref m_class;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
578 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
579
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
580 void _standard_api_create_internal(service_ptr & out, const GUID & classID);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
581 void _standard_api_get_internal(service_ptr & out, const GUID & classID);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
582 bool _standard_api_try_get_internal(service_ptr & out, const GUID & classID);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
583
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
584 template<typename T> inline void standard_api_create_t(service_ptr_t<T> & p_out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
585 if constexpr (pfc::is_same_type<T,typename T::t_interface_entrypoint>::value) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
586 _standard_api_create_internal(p_out._as_base_ptr(), T::class_guid);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
587 FB2K_ASSERT_VALID_SERVICE_PTR(p_out);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
588 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
589 service_ptr_t<typename T::t_interface_entrypoint> temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
590 standard_api_create_t(temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
591 if (!temp->service_query_t(p_out)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
592 #if PFC_DEBUG
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
593 FB2K_DebugLog() << "Service extension not found: " << T::debugServiceName() << " (" << pfc::print_guid(T::class_guid) << ") of base type: " << T::t_interface_entrypoint::debugServiceName() << " (" << pfc::print_guid(T::t_interface_entrypoint::class_guid) << ")";
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
594 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
595 throw exception_service_extension_not_found();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
596 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
597 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
598 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
599
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
600 template<typename T> inline void standard_api_create_t(T* & p_out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
601 p_out = NULL;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
602 standard_api_create_t( *reinterpret_cast< service_ptr_t<T> * >( & p_out ) );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
603 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
604
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
605 template<typename T> inline service_ptr_t<T> standard_api_create_t() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
606 service_ptr_t<T> temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
607 standard_api_create_t(temp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
608 return temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
609 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
610
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
611 template<typename T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
612 inline bool static_api_test_t() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
613 typedef typename T::t_interface_entrypoint EP;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
614 service_class_helper_t<EP> helper;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
615 if (helper.get_count() != 1) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
616 if constexpr (!pfc::is_same_type<T,EP>::value) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
617 service_ptr_t<T> t;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
618 if (!helper.create(0)->service_query_t(t)) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
619 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
620 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
621 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
622
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
623 #define FB2K_API_AVAILABLE(API) static_api_test_t<API>()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
624
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
625 //! Helper template used to easily access core services. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
626 //! Usage: static_api_ptr_t<myclass> api; api->dosomething(); \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
627 //! Can be used at any point of code, WITH EXCEPTION of static objects that are initialized during the DLL loading process before the service system is initialized; such as static static_api_ptr_t objects or having static_api_ptr_t instances as members of statically created objects. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
628 //! Throws exception_service_not_found if service could not be reached (which can be ignored for core APIs that are always present unless there is some kind of bug in the code). \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
629 //! This class is provided for backwards compatibility. The recommended way to do this stuff is now someclass::get() / someclass::tryGet().
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
630 template<typename t_interface>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
631 class static_api_ptr_t {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
632 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
633 typedef static_api_ptr_t<t_interface> t_self;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
634 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
635 static_api_ptr_t() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
636 standard_api_create_t(m_ptr);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
637 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
638 t_interface* operator->() const {return m_ptr;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
639 t_interface * get_ptr() const {return m_ptr;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
640 ~static_api_ptr_t() {m_ptr->service_release();}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
641
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
642 static_api_ptr_t(const t_self & in) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
643 m_ptr = in.m_ptr; m_ptr->service_add_ref();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
644 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
645 const t_self & operator=(const t_self & in) {return *this;} //obsolete, each instance should carry the same pointer
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
646 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
647 t_interface * m_ptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
648 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
649
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
650 template<typename t_interface>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
651 class service_enum_t {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
652 typedef service_enum_t<t_interface> self_t;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
653 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
654 service_enum_t() : m_index(0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
655 pfc::assert_same_type<t_interface,typename t_interface::t_interface_entrypoint>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
656 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
657 void reset() {m_index = 0;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
658
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
659 template<typename t_query>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
660 bool first(service_ptr_t<t_query> & p_out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
661 reset();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
662 return next(p_out);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
663 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
664
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
665 template<typename t_query>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
666 bool next(service_ptr_t<t_query> & p_out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
667 pfc::assert_same_type<typename t_query::t_interface_entrypoint,t_interface>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
668 if constexpr (pfc::is_same_type<t_query,t_interface>::value) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
669 return _next(reinterpret_cast<service_ptr_t<t_interface>&>(p_out));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
670 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
671 service_ptr_t<t_interface> temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
672 while(_next(temp)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
673 if (temp->service_query_t(p_out)) return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
674 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
675 return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
676 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
677 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
678
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
679 service_ptr_t<t_interface> get() const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
680 PFC_ASSERT(!finished());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
681 return m_helper.create(m_index);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
682 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
683
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
684 void operator++() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
685 PFC_ASSERT(!finished());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
686 ++m_index;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
687 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
688 void operator++(int) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
689 PFC_ASSERT(!finished());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
690 ++m_index;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
691 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
692
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
693 bool finished() const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
694 return m_index >= m_helper.get_count();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
695 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
696
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
697 service_ptr_t<t_interface> operator*() const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
698 return get();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
699 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
700
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
701 // ==== modern for loop support ====
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
702 // Instead of using service_enum_t<> / service_ptr_t<>, use:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
703 // for( auto ptr : someclass::enumerate() ) { ... }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
704 self_t begin() const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
705 self_t ret = *this;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
706 ret.m_index = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
707 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
708 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
709 self_t end() const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
710 self_t ret = *this;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
711 ret.m_index = ret.m_helper.get_count();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
712 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
713 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
714 bool operator==(self_t const& other) const {return m_index == other.m_index;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
715 bool operator!=(self_t const& other) const { return m_index != other.m_index; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
716
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
717
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
718 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
719 bool _next(service_ptr_t<t_interface> & p_out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
720 return m_helper.create(p_out,m_index++);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
721 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
722 size_t m_index;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
723 service_class_helper_t<t_interface> m_helper;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
724 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
725
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
726 namespace fb2k {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
727 //! Modern get-std-api helper. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
728 //! Does not throw exceptions, crashes on failure. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
729 //! If failure is possible, use std_api_try_get() instead and handle false return value.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
730 template<typename api_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
731 service_ptr_t<api_t> std_api_get() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
732 typedef typename api_t::t_interface_entrypoint entrypoint_t;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
733 service_ptr_t<api_t> ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
734 if constexpr (pfc::is_same_type<api_t, entrypoint_t>::value) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
735 _standard_api_get_internal(ret._as_base_ptr(), api_t::class_guid);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
736 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
737 ret ^= std_api_get<entrypoint_t>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
738 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
739 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
740 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
741
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
742 //! Modern get-std-api helper. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
743 //! Returns true on success (ret ptr is valid), false on failure (API not found).
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
744 template<typename api_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
745 bool std_api_try_get( service_ptr_t<api_t> & ret ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
746 typedef typename api_t::t_interface_entrypoint entrypoint_t;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
747 if constexpr (pfc::is_same_type<api_t, entrypoint_t>::value) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
748 return _standard_api_try_get_internal(ret._as_base_ptr(), api_t::class_guid);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
749 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
750 service_ptr_t<entrypoint_t> temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
751 if (! std_api_try_get( temp ) ) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
752 return ret &= temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
753 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
754 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
755 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
756
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
757
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
758
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
759 template<typename T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
760 class service_factory_t : public service_factory_base_t<typename T::t_interface_entrypoint> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
761 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
762 void instance_create(service_ptr_t<service_base> & p_out) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
763 this->pass_instance(p_out, new service_impl_t<T>);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
764 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
765 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
766
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
767
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
768 template<typename T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
769 class service_factory_singleton_t : public service_factory_base_t<typename T::t_interface_entrypoint> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
770 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
771 void instance_create(service_ptr_t<service_base> & p_out) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
772 this->pass_instance(p_out, &FB2K_SERVICE_SINGLETON(T) );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
773 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
774
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
775 inline T& get_static_instance() { return &FB2K_SERVICE_SINGLETON(T); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
776 inline const T& get_static_instance() const { return &FB2K_SERVICE_SINGLETON(T); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
777 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
778
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
779 template<typename T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
780 class service_factory_single_t : public service_factory_base_t<typename T::t_interface_entrypoint> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
781 service_impl_single_t<T> g_instance;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
782 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
783 template<typename ... arg_t> service_factory_single_t(arg_t && ... arg) : g_instance(std::forward<arg_t>(arg) ...) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
784
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
785 void instance_create(service_ptr_t<service_base> & p_out) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
786 this->pass_instance(p_out, &g_instance);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
787 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
788
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
789 inline T& get_static_instance() { return g_instance; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
790 inline const T& get_static_instance() const { return g_instance; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
791 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
792
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
793 //! Alternate service_factory_single, shared instance created on first access and never deallocated. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
794 //! Addresses the problem of dangling references to our object getting invoked or plainly de-refcounted during late shutdown.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
795 template<typename T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
796 class service_factory_single_v2_t : public service_factory_base_t<typename T::t_interface_entrypoint> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
797 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
798 T * get() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
799 static T * g_instance = new service_impl_single_t<T>;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
800 return g_instance;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
801 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
802 void instance_create(service_ptr_t<service_base> & p_out) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
803 this->pass_instance(p_out, get());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
804 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
805 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
806
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
807 template<typename T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
808 class service_factory_single_ref_t : public service_factory_base_t<typename T::t_interface_entrypoint>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
809 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
810 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
811 T & instance;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
812 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
813 service_factory_single_ref_t(T& param) : instance(param) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
814
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
815 void instance_create(service_ptr_t<service_base> & p_out) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
816 this->pass_instance(p_out, &instance);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
817 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
818
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
819 inline T& get_static_instance() { return instance; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
820 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
821
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
822 template<typename T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
823 class service_factory_single_transparent_t : public service_factory_base_t<typename T::t_interface_entrypoint>, public service_impl_single_t<T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
824 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
825 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
826 template<typename ... arg_t> service_factory_single_transparent_t(arg_t && ... arg) : service_impl_single_t<T>( std::forward<arg_t>(arg) ...) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
827
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
828 void instance_create(service_ptr_t<service_base> & p_out) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
829 this->pass_instance(p_out, pfc::implicit_cast<T*>(this));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
830 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
831
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
832 inline T& get_static_instance() {return *(T*)this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
833 inline const T& get_static_instance() const {return *(const T*)this;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
834 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
835
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
836
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
837 #ifdef _MSC_VER
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
838 #define FB2K_SERVICE_FACTORY_ATTR
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
839 #else
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
840 #define FB2K_SERVICE_FACTORY_ATTR __attribute__ (( __used__ ))
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
841 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
842
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
843 #define _FB2K_CONCAT(a, b) _FB2K_CONCAT_INNER(a, b)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
844 #define _FB2K_CONCAT_INNER(a, b) a ## b
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
845
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
846 #define _FB2K_UNIQUE_NAME(base) _FB2K_CONCAT(base, __COUNTER__)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
847
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
848 #define FB2K_SERVICE_FACTORY( TYPE ) static ::service_factory_singleton_t< TYPE > _FB2K_UNIQUE_NAME(g_factory_) FB2K_SERVICE_FACTORY_ATTR;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
849 #define FB2K_SERVICE_FACTORY_LATEINIT( TYPE ) static ::service_factory_single_v2_t< TYPE > _FB2K_UNIQUE_NAME(g_factory_) FB2K_SERVICE_FACTORY_ATTR;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
850 #define FB2K_SERVICE_FACTORY_PARAMS( TYPE, ... ) static ::service_factory_single_t< TYPE > _FB2K_UNIQUE_NAME(g_factory_) ( __VA_ARGS__ );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
851 #define FB2K_SERVICE_FACTORY_DYNAMIC( TYPE ) static ::service_factory_t< TYPE > _FB2K_UNIQUE_NAME(g_factory_) FB2K_SERVICE_FACTORY_ATTR;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
852
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
853
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
854 #define FB2K_FOR_EACH_SERVICE(type, call) for( auto obj : type::enumerate() ) { obj->call; }