Poc example works.
This commit is contained in:
parent
16a42298c5
commit
9469d09c57
0
include/barrier/barrier.hpp
Normal file
0
include/barrier/barrier.hpp
Normal file
0
include/barrier/common.hpp
Normal file
0
include/barrier/common.hpp
Normal file
@ -11,3 +11,8 @@ add_executable(profile profile.cpp)
|
|||||||
target_link_libraries(profile memgraph)
|
target_link_libraries(profile memgraph)
|
||||||
target_link_libraries(profile Threads::Threads)
|
target_link_libraries(profile Threads::Threads)
|
||||||
target_link_libraries(profile ${fmt_static_lib})
|
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})
|
||||||
|
24
poc/isolation.cpp
Normal file
24
poc/isolation.cpp
Normal file
@ -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;
|
||||||
|
}
|
28
poc/isolation/db.hpp
Normal file
28
poc/isolation/db.hpp
Normal file
@ -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"};
|
||||||
|
};
|
||||||
|
}
|
59
poc/isolation/header.cpp
Normal file
59
poc/isolation/header.cpp
Normal file
@ -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);
|
||||||
|
}
|
123
poc/isolation/header.hpp
Normal file
123
poc/isolation/header.hpp
Normal file
@ -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);
|
||||||
|
};
|
||||||
|
}
|
17
poc/isolation/isolated.hpp
Normal file
17
poc/isolation/isolated.hpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
0
src/barrier/barrier.cpp
Normal file
0
src/barrier/barrier.cpp
Normal file
Loading…
Reference in New Issue
Block a user