From 9469d09c57345ed4872725a2b519511f2f0cace7 Mon Sep 17 00:00:00 2001
From: Kruno Tomola Fabro <krunotf@memgraph.io>
Date: Fri, 26 Aug 2016 12:21:42 +0100
Subject: [PATCH] Poc example works.

---
 include/barrier/barrier.hpp |   0
 include/barrier/common.hpp  |   0
 poc/CMakeLists.txt          |   5 ++
 poc/isolation.cpp           |  24 +++++++
 poc/isolation/db.hpp        |  28 ++++++++
 poc/isolation/header.cpp    |  59 +++++++++++++++++
 poc/isolation/header.hpp    | 123 ++++++++++++++++++++++++++++++++++++
 poc/isolation/isolated.hpp  |  17 +++++
 src/barrier/barrier.cpp     |   0
 9 files changed, 256 insertions(+)
 create mode 100644 include/barrier/barrier.hpp
 create mode 100644 include/barrier/common.hpp
 create mode 100644 poc/isolation.cpp
 create mode 100644 poc/isolation/db.hpp
 create mode 100644 poc/isolation/header.cpp
 create mode 100644 poc/isolation/header.hpp
 create mode 100644 poc/isolation/isolated.hpp
 create mode 100644 src/barrier/barrier.cpp

diff --git a/include/barrier/barrier.hpp b/include/barrier/barrier.hpp
new file mode 100644
index 000000000..e69de29bb
diff --git a/include/barrier/common.hpp b/include/barrier/common.hpp
new file mode 100644
index 000000000..e69de29bb
diff --git a/poc/CMakeLists.txt b/poc/CMakeLists.txt
index 89856093b..cb6a5cd8b 100644
--- a/poc/CMakeLists.txt
+++ b/poc/CMakeLists.txt
@@ -11,3 +11,8 @@ add_executable(profile profile.cpp)
 target_link_libraries(profile memgraph)
 target_link_libraries(profile Threads::Threads)
 target_link_libraries(profile ${fmt_static_lib})
+
+include_directories(${CMAKE_SOURCE_DIR}/poc)
+
+add_executable(isolation isolation.cpp isolation/header.cpp)
+target_link_libraries(isolation ${fmt_static_lib})
diff --git a/poc/isolation.cpp b/poc/isolation.cpp
new file mode 100644
index 000000000..493b83949
--- /dev/null
+++ b/poc/isolation.cpp
@@ -0,0 +1,24 @@
+// Making it as first import will prevent accidentaly importing to isolated
+// other code.
+#include "isolation/isolated.hpp"
+
+#include <iostream>
+
+#include "isolation/db.hpp"
+#include "isolation/header.hpp"
+
+using namespace base;
+
+int main()
+{
+    std::cout << sizeof(Accessor) << " : " << alignof(Accessor) << "\n";
+
+    Db db;
+    db.data = 207;
+
+    auto ret = sha::do_something(reinterpret_cast<sha::Db &>(db));
+
+    std::cout << ret << std::endl;
+
+    return 0;
+}
diff --git a/poc/isolation/db.hpp b/poc/isolation/db.hpp
new file mode 100644
index 000000000..87e8eb3ff
--- /dev/null
+++ b/poc/isolation/db.hpp
@@ -0,0 +1,28 @@
+#include <string>
+
+namespace base
+{
+class Accessor
+{
+public:
+    char before = ~((char)-1);
+    int data = 0;
+    size_t after = ~((size_t)-1);
+};
+
+class Name
+{
+public:
+    Name(const char *str) : name(std::string(str)) {}
+
+    std::string name;
+};
+
+class Db
+{
+public:
+    int accessed = 0;
+    int data = 0;
+    Name name = {"name"};
+};
+}
diff --git a/poc/isolation/header.cpp b/poc/isolation/header.cpp
new file mode 100644
index 000000000..fffc646fa
--- /dev/null
+++ b/poc/isolation/header.cpp
@@ -0,0 +1,59 @@
+#include "isolation/header.hpp"
+
+#include "isolation/db.hpp"
+
+template <class TO, class FROM>
+TO &ref_as(FROM &ref)
+{
+    return (*reinterpret_cast<TO *>(&ref));
+}
+
+template <class TO, class FROM>
+TO value_as(FROM &&ref)
+{
+    return std::move((*reinterpret_cast<TO *>(&ref)));
+}
+
+sha::Accessor::Accessor(const sha::Accessor::Accessor &other)
+    : Sized(sizeof(base::Accessor), alignof(base::Accessor))
+{
+    as<base::Accessor>() = other.as<base::Accessor>();
+}
+
+sha::Accessor::Accessor(sha::Accessor::Accessor &&other)
+    : Sized(sizeof(base::Accessor), alignof(base::Accessor))
+{
+    as<base::Accessor>() = value_as<base::Accessor>(other);
+}
+
+sha::Accessor &sha::Accessor::operator=(const sha::Accessor::Accessor &other)
+{
+    // TODO
+    return *this;
+}
+sha::Accessor &sha::Accessor::operator=(sha::Accessor::Accessor &&other)
+{
+    // TODO
+    return *this;
+}
+
+int sha::Accessor::get_prop(sha::Name &name)
+{
+    return as<base::Accessor>().data;
+}
+
+sha::Accessor sha::Db::access()
+{
+    auto &db = as<base::Db>();
+    db.accessed++;
+    base::Accessor acc;
+    acc.data = db.data;
+    return sha::Accessor(value_as<sha::Accessor>(acc));
+}
+
+sha::Name &sha::Db::get_name(const char *str)
+{
+    auto &db = as<base::Db>();
+    db.accessed++;
+    return ref_as<sha::Name>(db.name);
+}
diff --git a/poc/isolation/header.hpp b/poc/isolation/header.hpp
new file mode 100644
index 000000000..56e8319dd
--- /dev/null
+++ b/poc/isolation/header.hpp
@@ -0,0 +1,123 @@
+#pragma once
+
+// All fake types should be defined here as a interface.
+
+#include <cassert>
+#include <type_traits>
+
+namespace sha
+{
+
+// Sized
+class Name;
+class Db;
+
+// Unsized
+class Accessor;
+
+// Marks types which will be passed only be ref/pointer.
+class Unsized
+{
+public:
+    // This will assure that this class/derived classes can't be instantiated,
+    // copyed or moved.
+    // This way the other side can't "accidentaly" create/copy/move or destroy
+    // this type because that would be errornus.
+    Unsized() = delete;
+    Unsized(const Unsized &other) = delete;
+    Unsized(Unsized &&other) = delete;
+    ~Unsized() = delete;
+    Unsized &operator=(const Unsized &other) = delete;
+    Unsized &operator=(Unsized &&other) = delete;
+
+protected:
+    template <class T>
+    T &as()
+    {
+        return (*reinterpret_cast<T *>(this));
+    }
+
+    template <class T>
+    const T &as() const
+    {
+        return (*reinterpret_cast<const T *>(this));
+    }
+};
+
+// Every type which will be passed by value must extends this class.
+template <std::size_t size_B, std::size_t alignment_B>
+class Sized
+{
+public:
+    // This will assure that this/derived class can't be instantiated.
+    // This way if other side can't "accidentaly" create this/derived type
+    // because that would be errornus.
+    Sized() = delete;
+
+    // This constructr also serves as a check for correctness of size and
+    // aligment.
+    Sized(std::size_t _size_B, std::size_t _alignment_B)
+    {
+        assert(size_B == _size_B);
+        assert(alignment_B == _alignment_B);
+    }
+
+protected:
+    template <class T>
+    T &as()
+    {
+        return (*reinterpret_cast<T *>(&data));
+    }
+
+    template <class T>
+    const T &as() const
+    {
+        return (*reinterpret_cast<const T *>(&data));
+    }
+
+private:
+    // Here the first argument for template is size of struct in bytes. While
+    // the second one is aligment of struct in bytes. Every class which will be
+    // passed by value must have this kind of aligned storage with correct size
+    // and aligment for that type. Unit tests to check this must be present.
+    // Example would be:
+    // std::aligned_storage<sizeof(std::set<int>), alignof(std::set<int>)>
+    // While the resoults of sizeof and alignof would be passed as template
+    // argumetns.
+    // This values would be checked in tests like the following for example
+    // above:
+    // assert(sizeof(Accessor)==sizeof(std::set<int>));
+    // assert(alignof(Accessor)==alignof(std::set<int>));
+    std::aligned_storage<size_B, alignment_B> data;
+};
+
+// Type which will be passed by value so it's real size matters.
+class Accessor : private Sized<16, 8>
+{
+public:
+    // If the underlying type can't be copyed or moved this two constructors
+    // would be deleted.
+    Accessor(const Accessor &other);
+    Accessor(Accessor &&other);
+
+    // If the underlying type can't be copyed or moved this two operators
+    // would be deleted.
+    Accessor &operator=(const Accessor &other);
+    Accessor &operator=(Accessor &&other);
+
+    int get_prop(Name &name);
+};
+
+// Type which will be passed by ref/pointer only so it's size doesnt matter.
+class Name : private Unsized
+{
+};
+
+// Type which will be passed by ref/pointer only so it's size doesnt matter.
+class Db : public Unsized
+{
+public:
+    Accessor access();
+    Name &get_name(const char *str);
+};
+}
diff --git a/poc/isolation/isolated.hpp b/poc/isolation/isolated.hpp
new file mode 100644
index 000000000..e11ccb17a
--- /dev/null
+++ b/poc/isolation/isolated.hpp
@@ -0,0 +1,17 @@
+// This is the file of isolated code. It has access only to header.hpp
+
+#include "isolation/header.hpp"
+
+namespace sha
+{
+int do_something(Db &db)
+{
+    auto &name = db.get_name("name");
+
+    auto acc = db.access();
+
+    auto ret = acc.get_prop(name);
+
+    return ret;
+}
+}
diff --git a/src/barrier/barrier.cpp b/src/barrier/barrier.cpp
new file mode 100644
index 000000000..e69de29bb