Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
cut some includes in MC
[simgrid.git] / src / mc / remote / RemotePtr.hpp
1 /* Copyright (c) 2008-2018. The SimGrid Team. All rights reserved.          */
2
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. */
5
6 #ifndef SIMGRID_MC_REMOTE_PTR_HPP
7 #define SIMGRID_MC_REMOTE_PTR_HPP
8
9 #include <cstdint>
10 #include <cstring>
11
12 #include <stdexcept>
13 #include <type_traits>
14
15 namespace simgrid {
16 namespace mc {
17
18 /** HACK, A value from another process
19  *
20  *  This represents a value from another process:
21  *
22  *  * constructor/destructor are disabled;
23  *
24  *  * raw memory copy (std::memcpy) is used to copy Remote<T>;
25  *
26  *  * raw memory comparison is used to compare them;
27  *
28  *  * when T is a trivial type, Remote is convertible to a T.
29  *
30  *  We currently only handle the case where the type has the same layout
31  *  in the current process and in the target process: we don't handle
32  *  cross-architecture (such as 32-bit/64-bit access).
33  */
34 template <class T> union Remote {
35 private:
36   T buffer;
37
38 public:
39   Remote() { /* Nothing to do */}
40   ~Remote() { /* Nothing to do */}
41   Remote(T const& p) { std::memcpy(static_cast<void*>(&buffer), static_cast<const void*>(&p), sizeof(buffer)); }
42   Remote(Remote const& that)
43   {
44     std::memcpy(static_cast<void*>(&buffer), static_cast<const void*>(&that.buffer), sizeof(buffer));
45   }
46   Remote& operator=(Remote const& that)
47   {
48     std::memcpy(static_cast<void*>(&buffer), static_cast<const void*>(&that.buffer), sizeof(buffer));
49     return *this;
50   }
51   T* getBuffer() { return &buffer; }
52   const T* getBuffer() const { return &buffer; }
53   std::size_t getBufferSize() const { return sizeof(T); }
54   operator T() const
55   {
56 //FIXME: assert turned off because smpi:Request is not seen as "trivial".
57 //    static_assert(std::is_trivial<T>::value, "Cannot convert non trivial type");
58     return buffer;
59   }
60   void clear() { std::memset(static_cast<void*>(&buffer), 0, sizeof(T)); }
61 };
62
63 /** Pointer to a remote address-space (process, snapshot)
64  *
65  *  With this we can clearly identify the expected type of an address in the
66  *  remote process while avoiding to use native local pointers.
67  *
68  *  Some operators (+/-) assume use the size of the underlying element. This
69  *  only works if the target applications is using the same target: it won't
70  *  work for example, when inspecting a 32 bit application from a 64 bit
71  *  model-checker.
72  *
73  *  We do not actually store the target address space because we can
74  *  always detect it in context. This way `RemotePtr` is as efficient
75  *  as a `uint64_t`.
76  */
77 template <class T> class RemotePtr {
78   std::uint64_t address_;
79
80 public:
81   RemotePtr() : address_(0) {}
82   explicit RemotePtr(std::nullptr_t) : address_(0) {}
83   explicit RemotePtr(std::uint64_t address) : address_(address) {}
84   explicit RemotePtr(T* address) : address_((std::uintptr_t)address) {}
85   explicit RemotePtr(Remote<T*> p) : address_((std::uintptr_t)*p.getBuffer()) {}
86   std::uint64_t address() const { return address_; }
87
88   /** Turn into a local pointer
89    *
90    (if the remote process is not, in fact, remote) */
91   T* local() const { return (T*)address_; }
92
93   operator bool() const { return address_; }
94   bool operator!() const { return not address_; }
95   operator RemotePtr<void>() const { return RemotePtr<void>(address_); }
96   RemotePtr<T>& operator=(std::nullptr_t)
97   {
98     address_ = 0;
99     return *this;
100   }
101   RemotePtr<T> operator+(std::uint64_t n) const { return RemotePtr<T>(address_ + n * sizeof(T)); }
102   RemotePtr<T> operator-(std::uint64_t n) const { return RemotePtr<T>(address_ - n * sizeof(T)); }
103   RemotePtr<T>& operator+=(std::uint64_t n)
104   {
105     address_ += n * sizeof(T);
106     return *this;
107   }
108   RemotePtr<T>& operator-=(std::uint64_t n)
109   {
110     address_ -= n * sizeof(T);
111     return *this;
112   }
113 };
114
115 template <class X, class Y> bool operator<(RemotePtr<X> const& x, RemotePtr<Y> const& y)
116 {
117   return x.address() < y.address();
118 }
119
120 template <class X, class Y> bool operator>(RemotePtr<X> const& x, RemotePtr<Y> const& y)
121 {
122   return x.address() > y.address();
123 }
124
125 template <class X, class Y> bool operator>=(RemotePtr<X> const& x, RemotePtr<Y> const& y)
126 {
127   return x.address() >= y.address();
128 }
129
130 template <class X, class Y> bool operator<=(RemotePtr<X> const& x, RemotePtr<Y> const& y)
131 {
132   return x.address() <= y.address();
133 }
134
135 template <class X, class Y> bool operator==(RemotePtr<X> const& x, RemotePtr<Y> const& y)
136 {
137   return x.address() == y.address();
138 }
139
140 template <class X, class Y> bool operator!=(RemotePtr<X> const& x, RemotePtr<Y> const& y)
141 {
142   return x.address() != y.address();
143 }
144
145 template <class T> inline RemotePtr<T> remote(T* p)
146 {
147   return RemotePtr<T>(p);
148 }
149
150 template <class T = void> inline RemotePtr<T> remote(uint64_t p)
151 {
152   return RemotePtr<T>(p);
153 }
154 }
155 }
156
157 #endif