1 /* Copyright (c) 2008-2015. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
7 #ifndef SIMGRID_MC_REMOTE_PTR_HPP
8 #define SIMGRID_MC_REMOTE_PTR_HPP
15 #include <type_traits>
20 /** HACK, A value from another process
22 * This represents a value from another process:
24 * * constructor/destructor are disabled;
26 * * raw memory copy (std::memcpy) is used to copy Remote<T>;
28 * * raw memory comparison is used to compare them;
30 * * when T is a trivial type, Remote is convertible to a T.
32 * We currently only handle the case where the type has the same layout
33 * in the current process and in the target process: we don't handle
34 * cross-architecture (such as 32-bit/64-bit access).
45 std::memcpy(&buffer, &p, sizeof(buffer));
47 Remote(Remote const& that)
49 std::memcpy(&buffer, &that.buffer, sizeof(buffer));
51 Remote& operator=(Remote const& that)
53 std::memcpy(&buffer, &that.buffer, sizeof(buffer));
56 T* getBuffer() { return &buffer; }
57 const T* getBuffer() const { return &buffer; }
58 std::size_t getBufferSize() const { return sizeof(T); }
60 static_assert(std::is_trivial<T>::value, "Cannot convert non trivial type");
65 std::memset(static_cast<void*>(&buffer), 0, sizeof(T));
70 /** Pointer to a remote address-space (process, snapshot)
72 * With this we can clearly identify the expected type of an address in the
73 * remote process while avoiding to use native local pointers.
75 * Some operators (+/-) assume use the size of the underlying element. This
76 * only works if the target applications is using the same target: it won't
77 * work for example, when inspecting a 32 bit application from a 64 bit
80 * We do not actually store the target address space because we can
81 * always detect it in context. This way `RemotePtr` is as efficient
84 template<class T> class RemotePtr {
85 std::uint64_t address_;
87 RemotePtr() : address_(0) {}
88 RemotePtr(std::uint64_t address) : address_(address) {}
89 RemotePtr(T* address) : address_((std::uintptr_t)address) {}
90 RemotePtr(Remote<T*> p) : RemotePtr(*p.getBuffer()) {}
91 std::uint64_t address() const { return address_; }
93 /** Turn into a local pointer
95 (if the remote process is not, in fact, remote) */
96 T* local() const { return (T*) address_; }
102 bool operator!() const
106 operator RemotePtr<void>() const
108 return RemotePtr<void>(address_);
110 RemotePtr<T> operator+(std::uint64_t n) const
112 return RemotePtr<T>(address_ + n * sizeof(T));
114 RemotePtr<T> operator-(std::uint64_t n) const
116 return RemotePtr<T>(address_ - n * sizeof(T));
118 RemotePtr<T>& operator+=(std::uint64_t n)
120 address_ += n * sizeof(T);
123 RemotePtr<T>& operator-=(std::uint64_t n)
125 address_ -= n * sizeof(T);
130 template<class X, class Y>
131 bool operator<(RemotePtr<X> const& x, RemotePtr<Y> const& y)
133 return x.address() < y.address();
136 template<class X, class Y>
137 bool operator>(RemotePtr<X> const& x, RemotePtr<Y> const& y)
139 return x.address() > y.address();
142 template<class X, class Y>
143 bool operator>=(RemotePtr<X> const& x, RemotePtr<Y> const& y)
145 return x.address() >= y.address();
148 template<class X, class Y>
149 bool operator<=(RemotePtr<X> const& x, RemotePtr<Y> const& y)
151 return x.address() <= y.address();
154 template<class X, class Y>
155 bool operator==(RemotePtr<X> const& x, RemotePtr<Y> const& y)
157 return x.address() == y.address();
160 template<class X, class Y>
161 bool operator!=(RemotePtr<X> const& x, RemotePtr<Y> const& y)
163 return x.address() != y.address();
166 template<class T> inline
167 RemotePtr<T> remote(T *p)
169 return RemotePtr<T>(p);
172 template<class T=void> inline
173 RemotePtr<T> remote(uint64_t p)
175 return RemotePtr<T>(p);