GNU Radio Manual and C++ API Reference 3.10.5.1
The Free & Open Software Radio Ecosystem
thrift_application_base.h
Go to the documentation of this file.
1/* -*- c++ -*- */
2/*
3 * Copyright 2015 Free Software Foundation, Inc.
4 *
5 * This file is part of GNU Radio
6 *
7 * SPDX-License-Identifier: GPL-3.0-or-later
8 *
9 */
10
11#ifndef THRIFT_APPLICATION_BASE_H
12#define THRIFT_APPLICATION_BASE_H
13
14#include <gnuradio/api.h>
15#include <gnuradio/logger.h>
16#include <gnuradio/prefs.h>
18#include <chrono>
19#include <memory>
20#include <thread>
21
22namespace {
23// Time, in milliseconds, to wait between checks to the Thrift runtime to see if
24// it has fully initialized.
25static constexpr unsigned int THRIFTAPPLICATION_ACTIVATION_TIMEOUT_MS(200);
26}; // namespace
27
28namespace apache {
29namespace thrift {
30namespace server {
31class TServer;
32}
33} // namespace thrift
34} // namespace apache
35
36/*!
37 * \brief Class to be statically initialized by thrift_application_base. Used
38 * to store state for thrift_application_base's singleton functions.
39 */
40
42{
43public:
46 {
47 ;
48 }
49
50 // Used to ensure the Thrift runtime is initialized on the first call to ::i().
52 // Stores the generated endpoint string after the Thrift runtime has initialized.
53 std::string d_endpointStr;
54 // Thread to execute the Thrift runtime's blocking serve() function.
55 std::shared_ptr<gr::thread::thread> d_start_thrift_thread;
56};
57
58/*!
59 * \brief Base class for a Thrift application with a singleton with
60 * instance function thrift_application_base::i(). Lazy initialization
61 * is used to start the Thrift runtime, therefore the Thrift runtime
62 * is not started unless thrift_application_base::i() is called at
63 * least once. This typically means that at least one rpc variable
64 * must be registered by a block before the runtime will start.
65 *
66 * \param TserverBase Template parameter naming the type of the server
67 * base, which is typically rpcserverbase.
68 * \param TserverClass Template parameter naming the eventual type of
69 * the fully derived application.
70 * \param _app Reference to the fully derived application instance to
71 * be returned by thrift_application_base::i().
72 */
73
74template <typename TserverBase, typename TserverClass>
76{
77public:
78 thrift_application_base(TserverClass* _app);
79
80 /*!
81 * Destructor for the application. Since shutdown and cleanup of the
82 * runtime is typically custom to a particular booter
83 * implementation, this must be implemented as a specialized function
84 * for a particular booter. Thus a template implementation is not
85 * provided here.
86 */
88
89 /*!
90 * The application singleton instance function.
91 */
92 static TserverBase* i();
93
94 /*!
95 * Returns the endpoint string of this application.
96 */
97 static const std::vector<std::string> endpoints();
98
99protected:
100 /*!
101 * Allows this application's booter to set the endpoint string after
102 * the Thrift runtime has initialized.
103 *
104 * \param[in] endpoint The endpoint string reported by this class.
105 */
106 void set_endpoint(const std::string& endpoint);
107
108 virtual TserverBase* i_impl() = 0;
109
110 /*!
111 * Reference to the fully derived application instance.
112 */
113 static TserverClass* d_application;
114
115 /*!
116 * Reference to the Thrift runtime.
117 */
118 std::unique_ptr<apache::thrift::server::TServer> d_thriftserver;
119
120 /*!
121 * Max number of attempts when checking the Thrift runtime for
122 * Initialization before giving up. Set in the Thrift config file
123 * (see \ref ctrlport_thrift_prefs).
124 */
125 static const unsigned int d_default_max_init_attempts;
126
127 /*!
128 * Default port for the runtime to listen on, if a static port is
129 * not specified. Set in the Thrift config file (see \ref
130 * ctrlport_thrift_prefs).
131 */
132 static const unsigned int d_default_thrift_port;
133
134 /*!
135 * Maximum number of threads to create when serving multiple rpc
136 * clients. Set in the Thrift config file (see \ref
137 * ctrlport_thrift_prefs).
138 */
139 static const unsigned int d_default_num_thrift_threads;
140
141 /*!
142 * Default packet size for the IP payload of thrift packets. Set in
143 * the Thrift config file (see \ref ctrlport_thrift_prefs).
144 */
145 static const unsigned int d_default_thrift_buffer_size;
146
147 /*!
148 * <a href="https://wiki.gnuradio.org/index.php/Logging" target="_blank">Logging</a>
149 * instances.
150 */
152
153private:
154 // Function to be called in a separate thread to invoke the blocking
155 // ThriftServer::serve() function. Must be specialized for a particular
156 // booter implementation, therefore a template implementation is
157 // not provided here.
158 void start_thrift();
159
160 // Non-blocking function that returns true when the Thrift
161 // runtime has finished initialization. Must be implemented
162 // as a specialized template function for a particular booter
163 // implementation, therefore template implementation is not
164 // provided here.
165 bool application_started();
166
167 // Internal function to start the initialization of the runtime.
168 // Since this singleton uses lazy instantiation, this function
169 // will be called on the first call to the instance function ::i(),
170 // and since ::i() is static, this function must be static as well.
171 static void start_application();
172
173 // Pointer to the structure containing statically allocated
174 // state information for the applicaiton_base singleton.
175 static std::unique_ptr<thrift_application_base_impl> p_impl;
176
177 // Mutex to protect the endpoint string.
178 gr::thread::mutex d_lock;
179
180 // Will be set to true by a the application_started() function,
181 // specialized for a particular booter implementation, once the
182 // thrift runtime has successfully initialized.
183 bool d_thirft_is_running;
184};
185
186template <typename TserverBase, typename TserverClass>
188
189template <typename TserverBase, typename TserverClass>
191 TserverClass* _app)
192 : d_lock(), d_thirft_is_running(false)
193{
195 d_application = _app;
196}
197
198template <typename TserverBase, typename TserverClass>
200{
201 unsigned int max_init_attempts =
202 static_cast<unsigned int>(gr::prefs::singleton()->get_long(
203 "thrift", "init_attempts", d_default_max_init_attempts));
204
205 if (!p_impl->d_application_initialized) {
206 p_impl->d_start_thrift_thread = std::make_shared<gr::thread::thread>(
207 [app = d_application] { app->start_thrift(); });
208
209 bool app_started(false);
210 for (unsigned int attempts(0); (!app_started && attempts < max_init_attempts);
211 ++attempts) {
212 std::this_thread::sleep_for(
213 std::chrono::milliseconds(THRIFTAPPLICATION_ACTIVATION_TIMEOUT_MS));
214 app_started = d_application->application_started();
215 }
216
217 if (!app_started) {
218 gr::logger log("thrift_application_base");
219 log.warn("start_application(): timeout waiting");
220 }
221
222 p_impl->d_application_initialized = true;
223 }
224}
225
226template <typename TserverBase, typename TserverClass>
227const std::vector<std::string>
229{
230 std::vector<std::string> ep;
231 ep.push_back(p_impl->d_endpointStr);
232 return ep;
233}
234
235template <typename TserverBase, typename TserverClass>
237 const std::string& endpoint)
238{
239 gr::thread::scoped_lock guard(d_lock);
240 p_impl->d_endpointStr = endpoint;
241}
242
243template <typename TserverBase, typename TserverClass>
245{
246 if (!p_impl->d_application_initialized) {
247 start_application();
248 }
249 return d_application->i_impl();
250}
251
252#endif
GR_LOG macros.
Definition: logger.h:119
long get_long(const std::string &section, const std::string &option, long default_val)
If option exists and value can be converted to long, return it; else default_val.
static prefs * singleton()
Class to be statically initialized by thrift_application_base. Used to store state for thrift_applica...
Definition: thrift_application_base.h:42
std::string d_endpointStr
Definition: thrift_application_base.h:53
bool d_application_initialized
Definition: thrift_application_base.h:51
std::shared_ptr< gr::thread::thread > d_start_thrift_thread
Definition: thrift_application_base.h:55
thrift_application_base_impl()
Definition: thrift_application_base.h:44
Base class for a Thrift application with a singleton with instance function thrift_application_base::...
Definition: thrift_application_base.h:76
static const unsigned int d_default_thrift_buffer_size
Definition: thrift_application_base.h:145
gr::logger_ptr d_logger
Definition: thrift_application_base.h:151
thrift_application_base(TserverClass *_app)
Definition: thrift_application_base.h:190
std::unique_ptr< apache::thrift::server::TServer > d_thriftserver
Definition: thrift_application_base.h:118
void set_endpoint(const std::string &endpoint)
Definition: thrift_application_base.h:236
static const unsigned int d_default_num_thrift_threads
Definition: thrift_application_base.h:139
static const std::vector< std::string > endpoints()
Definition: thrift_application_base.h:228
static TserverClass * d_application
Definition: thrift_application_base.h:113
static const unsigned int d_default_thrift_port
Definition: thrift_application_base.h:132
virtual TserverBase * i_impl()=0
static const unsigned int d_default_max_init_attempts
Definition: thrift_application_base.h:125
static TserverBase * i()
Definition: thrift_application_base.h:244
gr::logger_ptr d_debug_logger
Definition: thrift_application_base.h:151
Definition: thrift_application_base.h:28
boost::mutex mutex
Definition: thread.h:37
boost::unique_lock< boost::mutex > scoped_lock
Definition: thread.h:38
std::shared_ptr< logger > logger_ptr
Definition: logger.h:225
GR_RUNTIME_API bool configure_default_loggers(gr::logger_ptr &l, gr::logger_ptr &d, const std::string &name)