Tree @HEAD (Download .tar.gz)
- ..
- widecharwidth
- ast.cpp
- ast.h
- ast_node_types.inc
- autoload.cpp
- autoload.h
- builtin.cpp
- builtin.h
- builtin_argparse.cpp
- builtin_argparse.h
- builtin_bg.cpp
- builtin_bg.h
- builtin_bind.cpp
- builtin_bind.h
- builtin_block.cpp
- builtin_block.h
- builtin_builtin.cpp
- builtin_builtin.h
- builtin_cd.cpp
- builtin_cd.h
- builtin_command.cpp
- builtin_command.h
- builtin_commandline.cpp
- builtin_commandline.h
- builtin_complete.cpp
- builtin_complete.h
- builtin_contains.cpp
- builtin_contains.h
- builtin_disown.cpp
- builtin_disown.h
- builtin_echo.cpp
- builtin_echo.h
- builtin_emit.cpp
- builtin_emit.h
- builtin_eval.cpp
- builtin_eval.h
- builtin_exit.cpp
- builtin_exit.h
- builtin_fg.cpp
- builtin_fg.h
- builtin_function.cpp
- builtin_function.h
- builtin_functions.cpp
- builtin_functions.h
- builtin_history.cpp
- builtin_history.h
- builtin_jobs.cpp
- builtin_jobs.h
- builtin_math.cpp
- builtin_math.h
- builtin_printf.cpp
- builtin_printf.h
- builtin_pwd.cpp
- builtin_pwd.h
- builtin_random.cpp
- builtin_random.h
- builtin_read.cpp
- builtin_read.h
- builtin_realpath.cpp
- builtin_realpath.h
- builtin_return.cpp
- builtin_return.h
- builtin_set.cpp
- builtin_set.h
- builtin_set_color.cpp
- builtin_set_color.h
- builtin_source.cpp
- builtin_source.h
- builtin_status.cpp
- builtin_status.h
- builtin_string.cpp
- builtin_string.h
- builtin_test.cpp
- builtin_test.h
- builtin_type.cpp
- builtin_type.h
- builtin_ulimit.cpp
- builtin_ulimit.h
- builtin_wait.cpp
- builtin_wait.h
- color.cpp
- color.h
- common.cpp
- common.h
- complete.cpp
- complete.h
- enum_set.h
- env.cpp
- env.h
- env_dispatch.cpp
- env_dispatch.h
- env_universal_common.cpp
- env_universal_common.h
- event.cpp
- event.h
- exec.cpp
- exec.h
- expand.cpp
- expand.h
- fallback.cpp
- fallback.h
- fd_monitor.cpp
- fd_monitor.h
- fds.cpp
- fds.h
- fish.cpp
- fish_indent.cpp
- fish_key_reader.cpp
- fish_test_helper.cpp
- fish_tests.cpp
- fish_version.cpp
- fish_version.h
- flog.cpp
- flog.h
- function.cpp
- function.h
- future_feature_flags.cpp
- future_feature_flags.h
- global_safety.h
- highlight.cpp
- highlight.h
- history.cpp
- history.h
- history_file.cpp
- history_file.h
- input.cpp
- input.h
- input_common.cpp
- input_common.h
- intern.cpp
- intern.h
- io.cpp
- io.h
- iothread.cpp
- iothread.h
- job_group.cpp
- job_group.h
- kill.cpp
- kill.h
- lru.h
- maybe.h
- null_terminated_array.cpp
- null_terminated_array.h
- operation_context.cpp
- operation_context.h
- output.cpp
- output.h
- pager.cpp
- pager.h
- parse_constants.h
- parse_execution.cpp
- parse_execution.h
- parse_tree.cpp
- parse_tree.h
- parse_util.cpp
- parse_util.h
- parser.cpp
- parser.h
- parser_keywords.cpp
- parser_keywords.h
- path.cpp
- path.h
- postfork.cpp
- postfork.h
- print_help.cpp
- print_help.h
- proc.cpp
- proc.h
- reader.cpp
- reader.h
- redirection.cpp
- redirection.h
- sanity.cpp
- sanity.h
- screen.cpp
- screen.h
- signal.cpp
- signal.h
- termsize.cpp
- termsize.h
- timer.cpp
- timer.h
- tinyexpr.cpp
- tinyexpr.h
- tokenizer.cpp
- tokenizer.h
- topic_monitor.cpp
- topic_monitor.h
- trace.cpp
- trace.h
- utf8.cpp
- utf8.h
- util.cpp
- util.h
- wcstringutil.cpp
- wcstringutil.h
- wgetopt.cpp
- wgetopt.h
- wildcard.cpp
- wildcard.h
- wutil.cpp
- wutil.h
global_safety.h @HEAD — raw · history · blame
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | // Support for enforcing correct access to globals. #ifndef FISH_GLOBAL_SAFETY_H #define FISH_GLOBAL_SAFETY_H #include "config.h" // IWYU pragma: keep #include <atomic> #include <cassert> #include "common.h" // fish is multithreaded. Global (which includes function and file-level statics) when used naively // may therefore lead to data races. Use the following types to characterize and enforce correct // access patterns. namespace detail { // An empty value type that cannot be copied or moved. // Include this as an instance variable to prevent globals from being copied or moved. struct fixed_t { fixed_t(const fixed_t &) = delete; fixed_t(fixed_t &&) = delete; fixed_t &operator=(fixed_t &&) = delete; fixed_t &operator=(const fixed_t &) = delete; fixed_t() = default; }; } // namespace detail /// A mainthread_t variable may only be accessed on the main thread. template <typename T> class mainthread_t : detail::fixed_t { T value_{}; public: mainthread_t(T value) : value_(std::move(value)) {} mainthread_t() = default; T *operator->() { ASSERT_IS_MAIN_THREAD(); return &value_; } operator T &() { ASSERT_IS_MAIN_THREAD(); return value_; } operator const T &() const { ASSERT_IS_MAIN_THREAD(); return value_; } void operator=(T value) { ASSERT_IS_MAIN_THREAD(); value_ = std::move(value); } }; /// A latch variable may only be set once, on the main thread. /// The value is a immortal. template <typename T> class latch_t : detail::fixed_t { T *value_{}; public: operator T *() { return value_; } operator const T *() const { return value_; } T *operator->() { return value_; } const T *operator->() const { return value_; } void operator=(std::unique_ptr<T> value) { ASSERT_IS_MAIN_THREAD(); assert(value_ == nullptr && "Latch variable initialized multiple times"); assert(value != nullptr && "Latch variable initialized with null"); // Note: deliberate leak. value_ = value.release(); } void operator=(T &&value) { *this = make_unique<T>(std::move(value)); } template <typename... Args> void emplace(Args &&...args) { *this = make_unique<T>(std::forward<Args>(args)...); } }; /// An atomic type that always use relaxed reads. template <typename T> class relaxed_atomic_t { std::atomic<T> value_{}; public: relaxed_atomic_t() = default; relaxed_atomic_t(T value) : value_(value) {} operator T() const volatile { return value_.load(std::memory_order_relaxed); } void operator=(T v) { return value_.store(v, std::memory_order_relaxed); } void operator=(T v) volatile { return value_.store(v, std::memory_order_relaxed); } // Perform a CAS operation, returning whether it succeeded. bool compare_exchange(T expected, T desired) { return value_.compare_exchange_strong(expected, desired, std::memory_order_relaxed); } // postincrement T operator++(int) { return value_.fetch_add(1, std::memory_order_relaxed); } // preincrement T operator++() { return 1 + value_.fetch_add(1, std::memory_order_relaxed); } }; using relaxed_atomic_bool_t = relaxed_atomic_t<bool>; #endif |