GNU Radio Manual and C++ API Reference  3.8.5.0
The Free & Open Software Radio Ecosystem
rpc_shared_ptr_selection.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2019 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef RPC_SHARED_PTR_SELECTION_H
24 #define RPC_SHARED_PTR_SELECTION_H
25 
26 #include <memory>
27 
28 #include "gnuradio/config.h"
29 #ifdef GR_RPCSERVER_THRIFT
30 #ifdef THRIFT_HAS_VERSION_H
31 #include <thrift/version.h>
32 #endif
33 // to get boost includes, if and only if they're still in Thrift:
34 #include <thrift/concurrency/Thread.h>
35 #endif
36 
37 // select a "shared_ptr" type to use: std:: or boost::
38 //
39 // Dear Thrift maintainers, should you read this, here's a haiku:
40 //
41 // Version numbers carved in strings
42 // C Preprocessor can't
43 // Templates can't
44 // Sadness
45 
46 
47 namespace gr {
48 
49 //! \brief constexpr check for whether a character is a digit
50 constexpr bool digit(char d) { return !(d < '0' || d > '9'); }
51 
52 /* \brief Convert C string to a Version magic, constexpr.
53  *
54  * Converts "5.10.3" to 5·10⁶ + 10·10³+ 3 = 5 010 003
55  */
56 constexpr uint64_t cstr_to_version_magic(const char* cstr, uint64_t magicsofar)
57 {
58  // OK, we go: check for the current character being a zero byte, in that case,
59  // return magicsofar
60  return *cstr ?
61  // next, check whether a digit, in that case, multiply magicsofar with
62  // 10, and parse on into the sunset
63  (digit(*cstr)
64  ? cstr_to_version_magic(cstr + 1, magicsofar * 10 + (*cstr - '0'))
65  :
66  // if it's not a digit, maybe it's a dot? throw
67  ((*cstr) == '.' ?
68  // it's a dot -> multiply by one hundred, move on
69  cstr_to_version_magic(cstr + 1, magicsofar * 100)
70  :
71  // not a dot, not a digit, not an end byte
72  (throw "String is not a x.y.z version string")))
73  : magicsofar;
74 }
75 
76 /* \brief Convert three-element version numbers to a single unsigned integer. constexpr.
77  *
78  * Converts 5, 10, 3 to 5·10⁶ + 10·10³+ 3 = 5 010 003
79  */
80 constexpr uint64_t
81 version_to_version_magic(unsigned int x, unsigned int y, unsigned int z)
82 {
83  return (uint64_t)x * 1000 * 1000 + y * 1000 + z;
84 }
85 
86 /* \brief Thrift-specific version check
87  *
88  * Evaluates THRIFT_VERSION as string by converting it to a version magic.
89  *
90  * Then, compares that to 0.11.0, which is the first release where Thrift might use
91  * std::shared_ptrs.
92  *
93  * Then, compares to 0.13.0, which is the release where Thrift only uses
94  * std::shared_ptr.
95  *
96  * If inbetween, do the same check that Thrift does in their 0.11-0.12
97  * stdcxx.h headers, minus the redundant MSVC check, which is guaranteed by our MSVC
98  * minimum requirement, anyway
99  */
101 {
102 #ifndef THRIFT_VERSION
103  // if there's no thrift, then that doesn't use boost
104  return false;
105 #else // THRIFT_VERSION
106  return (cstr_to_version_magic(THRIFT_VERSION, 0) <
107  version_to_version_magic(0, 11, 0)) ||
108  (cstr_to_version_magic(THRIFT_VERSION, 0) <
109  version_to_version_magic(0, 13, 0) &&
110  /* This is the internal check that thrift does in 0.11 and 0.12 to decide whether to
111  use std:: or boost::shared_ptr. As soon as we require Thrift >= 0.13.0 this
112  #define-based check is to be removed. */
113 #if defined(BOOST_NO_CXX11_SMART_PTR) || defined(FORCE_BOOST_SMART_PTR)
114  true
115 #else
116  false
117 #endif
118  );
119 #endif // THRIFT_VERSION
120 }
121 
122 /* \brief template base class; unspecialized; specializations hold a `t` member that's
123  * actually a Thrift-compatible `shared_ptr`.
124  */
125 template <bool use_std, class T>
126 struct rpc_sptr_impl;
127 
128 //! \brief template specialization holding a `std::shared_ptr`
129 template <class T>
130 struct rpc_sptr_impl<true, T> {
131  using t = std::shared_ptr<T>;
132 };
133 
134 #ifdef BOOST_SHARED_PTR_HPP_INCLUDED
135 //! \brief template specialization holding a `boost::shared_ptr`
136 template <class T>
137 struct rpc_sptr_impl<false, T> {
138  using t = boost::shared_ptr<T>;
139 };
140 #endif
141 
142 /* \brief template class with ::t member type that is std:: or boost::shared_ptr,
143  * depending on `thrift_version_uses_boost()`.
144  */
145 template <class T>
146 struct rpc_sptr {
147  using t = typename rpc_sptr_impl<!thrift_version_uses_boost(), T>::t;
148 };
149 } // namespace gr
150 #endif
constexpr uint64_t version_to_version_magic(unsigned int x, unsigned int y, unsigned int z)
Definition: rpc_shared_ptr_selection.h:81
GNU Radio logging wrapper for log4cpp library (C++ port of log4j)
Definition: basic_block.h:46
constexpr uint64_t cstr_to_version_magic(const char *cstr, uint64_t magicsofar)
Definition: rpc_shared_ptr_selection.h:56
constexpr bool thrift_version_uses_boost()
Definition: rpc_shared_ptr_selection.h:100
constexpr bool digit(char d)
constexpr check for whether a character is a digit
Definition: rpc_shared_ptr_selection.h:50