1 /* Copyright (c) 2008-2019. The SimGrid Team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
6 #ifndef SIMGRID_MC_REMOTE_PTR_HPP
7 #define SIMGRID_MC_REMOTE_PTR_HPP
9 #include "src/simix/smx_private.hpp"
14 /** HACK, A value from another process
16 * This represents a value from another process:
18 * * constructor/destructor are disabled;
20 * * raw memory copy (std::memcpy) is used to copy Remote<T>;
22 * * raw memory comparison is used to compare them;
24 * * when T is a trivial type, Remote is convertible to a T.
26 * We currently only handle the case where the type has the same layout
27 * in the current process and in the target process: we don't handle
28 * cross-architecture (such as 32-bit/64-bit access).
30 template <class T> union Remote {
35 Remote() { /* Nothing to do */}
36 ~Remote() { /* Nothing to do */}
37 Remote(T const& p) { std::memcpy(static_cast<void*>(&buffer), static_cast<const void*>(&p), sizeof(buffer)); }
38 Remote(Remote const& that)
40 std::memcpy(static_cast<void*>(&buffer), static_cast<const void*>(&that.buffer), sizeof(buffer));
42 Remote& operator=(Remote const& that)
44 std::memcpy(static_cast<void*>(&buffer), static_cast<const void*>(&that.buffer), sizeof(buffer));
47 T* getBuffer() { return &buffer; }
48 const T* getBuffer() const { return &buffer; }
49 std::size_t getBufferSize() const { return sizeof(T); }
52 //FIXME: assert turned off because smpi:Request is not seen as "trivial".
53 // static_assert(std::is_trivial<T>::value, "Cannot convert non trivial type");
56 void clear() { std::memset(static_cast<void*>(&buffer), 0, sizeof(T)); }
59 /** Pointer to a remote address-space (process, snapshot)
61 * With this we can clearly identify the expected type of an address in the
62 * remote process while avoiding to use native local pointers.
64 * Some operators (+/-) assume use the size of the underlying element. This
65 * only works if the target applications is using the same target: it won't
66 * work for example, when inspecting a 32 bit application from a 64 bit
69 * We do not actually store the target address space because we can
70 * always detect it in context. This way `RemotePtr` is as efficient
73 template <class T> class RemotePtr {
74 std::uint64_t address_;
77 RemotePtr() : address_(0) {}
78 explicit RemotePtr(std::nullptr_t) : address_(0) {}
79 explicit RemotePtr(std::uint64_t address) : address_(address) {}
80 explicit RemotePtr(T* address) : address_((std::uintptr_t)address) {}
81 explicit RemotePtr(Remote<T*> p) : address_((std::uintptr_t)*p.getBuffer()) {}
82 std::uint64_t address() const { return address_; }
84 /** Turn into a local pointer
86 (if the remote process is not, in fact, remote) */
87 T* local() const { return (T*)address_; }
89 operator bool() const { return address_; }
90 bool operator!() const { return not address_; }
91 operator RemotePtr<void>() const { return RemotePtr<void>(address_); }
92 RemotePtr<T>& operator=(std::nullptr_t)
97 RemotePtr<T> operator+(std::uint64_t n) const { return RemotePtr<T>(address_ + n * sizeof(T)); }
98 RemotePtr<T> operator-(std::uint64_t n) const { return RemotePtr<T>(address_ - n * sizeof(T)); }
99 RemotePtr<T>& operator+=(std::uint64_t n)
101 address_ += n * sizeof(T);
104 RemotePtr<T>& operator-=(std::uint64_t n)
106 address_ -= n * sizeof(T);
111 template <class X, class Y> bool operator<(RemotePtr<X> const& x, RemotePtr<Y> const& y)
113 return x.address() < y.address();
116 template <class X, class Y> bool operator>(RemotePtr<X> const& x, RemotePtr<Y> const& y)
118 return x.address() > y.address();
121 template <class X, class Y> bool operator>=(RemotePtr<X> const& x, RemotePtr<Y> const& y)
123 return x.address() >= y.address();
126 template <class X, class Y> bool operator<=(RemotePtr<X> const& x, RemotePtr<Y> const& y)
128 return x.address() <= y.address();
131 template <class X, class Y> bool operator==(RemotePtr<X> const& x, RemotePtr<Y> const& y)
133 return x.address() == y.address();
136 template <class X, class Y> bool operator!=(RemotePtr<X> const& x, RemotePtr<Y> const& y)
138 return x.address() != y.address();
141 template <class T> inline RemotePtr<T> remote(T* p)
143 return RemotePtr<T>(p);
146 template <class T = void> inline RemotePtr<T> remote(uint64_t p)
148 return RemotePtr<T>(p);