diff --git a/src/utils.h b/src/utils.h index 3e77e0a60..a1ba9246d 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1,8 +1,54 @@ #ifndef RAY_UTILS_H #define RAY_UTILS_H +#include #include +template +struct SynchronizedTarget { + typedef typename Synchronized::element_type type; +}; + +template +struct SynchronizedTarget { + typedef const typename Synchronized::element_type type; +}; + +template +class SynchronizedPtr : public std::unique_lock { + typedef std::unique_lock base_type; + + // Make these private; they don't make much sense externally... + using typename base_type::mutex_type; + using base_type::mutex; +public: + typedef typename SynchronizedTarget::type value_type; + SynchronizedPtr(Synchronized& value) : base_type(value) { } + value_type& operator*() const { return *mutex()->unsafe_get(); } + value_type* operator->() const { return mutex() ? mutex()->unsafe_get() : NULL; } +}; + +template +class Synchronized { + mutable Mutex mutex_; + T value_; +public: + typedef T element_type; + template + Synchronized(U&&... args) : value_(std::forward(args)...) { } + Synchronized(const Synchronized& other) : value_(*other) { } + Synchronized(Synchronized&& other) : value_(std::move(*other)) { } + Synchronized& operator =(const Synchronized& other) { *get() = *other.get(); return *this; } + Synchronized& operator =(Synchronized&& other) { *get() = std::move(*other.get()); return *this; } + void lock() const { return mutex_.lock(); } + void unlock() const { return mutex_.unlock(); } + bool try_lock() const { return mutex_.try_lock(); } + SynchronizedPtr get() { return *this; } + SynchronizedPtr get() const { return *this; } + element_type* unsafe_get() { return &value_; } + const element_type* unsafe_get() const { return &value_; } +}; + std::string::iterator split_ip_address(std::string& ip_address); const char* get_cmd_option(char** begin, char** end, const std::string& option);