Created
May 21, 2017 05:58
-
-
Save dpzmick/ed2a1cd578c80669eeeada8b7be86881 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "typestring.hh" | |
#include <memory> | |
#include <thread> | |
#include <type_traits> | |
#include <iostream> | |
// by default nothing is realtime | |
template <typename T> | |
struct RTSaftey | |
{ | |
static constexpr bool is_rt = false; | |
}; | |
// elevate a function to realtime | |
// this uses the name passed in directly, so it will never work on class members | |
// unless you can get __PRETTY_FUNC__ without being inside of the function | |
#define REALTIME(fname) \ | |
template <> \ | |
struct RTSaftey<typestring_is(#fname)> \ | |
{ static constexpr bool is_rt = true; }; \ | |
// mark a function as being not safe for realtime execution. If a function | |
// realtime safe, but also isn't annotated with this function, no checks will be | |
// performed. | |
#define NOT_REALTIME_SAFE(fname, helper_name) \ | |
template <> \ | |
struct RTSaftey<typestring_is(#fname)> \ | |
{ static constexpr bool is_rt = false; }; \ | |
\ | |
struct fname##__STRUCT { \ | |
template<bool caller_is_rt, typename... Args> \ | |
auto call(Args... args) -> decltype(helper_name(args...)) \ | |
{ \ | |
static_assert(!caller_is_rt, "cannot call non-realtime from realtime function"); \ | |
return helper_name(args...); \ | |
} \ | |
}; | |
// generates a macro which will call a function that has been decorated with | |
// NOT_REALTIME_SAFE | |
#define MAKE_FN(name, ...) name##__STRUCT{}.call< \ | |
RTSaftey<typestring_is(__func__)>::is_rt>(__VA_ARGS__) | |
// define two templated functions which check if the input has a default value | |
// these do not have to be forward declared, but a forward declaration will | |
// allow us to be slightly more order agnostic | |
template <typename T> bool not_safe_helper(T test); | |
template <typename T> bool safe(T test); | |
// create a wrapper struct for `not_safe_helper`, then create a macro which will | |
// invoke the `call` method of the wrapper struct | |
// if nothing is ever decorated with NOT_REALTIME_SAFE, no checks are performed | |
// (so this is also pretty broken) | |
NOT_REALTIME_SAFE(not_safe, not_safe_helper); | |
#define not_safe(...) MAKE_FN(not_safe, __VA_ARGS__) | |
// declare `safe` as a realtime function | |
// this can't work on class member functions, but templated functions are okay | |
// (as long as realtime safety doesn't depend on the template parameters) | |
REALTIME(safe) | |
// finally, provide implementations for these functions | |
template <typename T> | |
bool not_safe_helper(T test) | |
{ | |
if (test == T{}) return true; | |
return false; | |
} | |
template<typename T> | |
bool safe(T test) | |
{ | |
return not_safe(0); // this causes a compiler | |
// return false; | |
} | |
int main() | |
{ | |
safe(100); | |
return not_safe(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment