Logo AND Algorithmique Numérique Distribuée

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