Skip to content

Instantly share code, notes, and snippets.

@lambdageek
Last active December 4, 2018 19:41
Show Gist options
  • Save lambdageek/64c75b440a7b22092c373b7dc8775fe8 to your computer and use it in GitHub Desktop.
Save lambdageek/64c75b440a7b22092c373b7dc8775fe8 to your computer and use it in GitHub Desktop.
Mono C++ basis header
#include "mono-basis.hpp"
#include <stdio.h>
class X : public mono::alloc::polymorphic_base {
public:
X () = default;
bool get() const { return b; }
private:
bool b;
};
class Y : public X {
~Y() override;
};
Y::~Y() {
printf ("Y destructor %p\n", static_cast<void*>(this));
}
int main ()
{
X* x = mono::new_<Y> ();
X** p = mono::new_<X*> (x);
printf ("%p\n", static_cast<void*>(x));
mono::delete_ (x);
mono::delete_ (p);
return 0;
}
all: main
.PHONY: all
main: main.o
clang -o main main.o
main.o: main.cpp
clang -c -xc++ -std=c++11 -fno-rtti -fno-exceptions -Wall -Wextra -O main.cpp
#ifndef _MONO_BASIS_HPP
#define _MONO_BASIS_HPP
#include <cstdlib>
#include <utility>
#include <new>
namespace mono {
namespace alloc {
namespace detail {
inline
void *allocate (std::size_t sz) {
return std::malloc (sz); // TODO g_malloc
}
inline
void deallocate (void *ptr) {
std::free (ptr); // TODO g_free
}
} // detail
/**
* Base class for all classes in the Mono runtime.
* This ensures that allocation of new objects uses our preferred allocation functions.
*/
class base {
public:
void* operator new (std::size_t sz) {
using mono::alloc::detail::allocate;
return allocate (sz);
}
void* operator new (std::size_t sz, void* ptr) {
return ::operator new (sz, ptr);
}
void operator delete (void *ptr) {
using mono::alloc::detail::deallocate;
return deallocate (ptr);
}
};
/**
* Base class for all polymorpic type hierarchies in the Mono runtime.
* This provides two things: overloaded opreator new and operator delete that use
* our preferred allocation functions, and a default virtual destructor.
*
* It's important to derive polymorphic base classes from polymorphic_base
* because GCC and Clang compile multiple symbols for a virtual destructor.
* One of them, the D0 "deleting object destructor" causes a dependency on
* the global `::operator delete(void*)` even if it is never used. Since
* Mono does not link with the C++ runtime library, the mere definition of
* a virtual destructor will cause linking errors, unless the class has its
* own operator delete.
*/
class polymorphic_base : public base {
public:
virtual ~polymorphic_base () = default;
};
} // alloc
/**
* Use the new_ function to allocate:
* class Foo : public mono::alloc::polymorphic_base {}
* class Bar : public Foo { public: Bar(int x, double y); }
* Foo *foo = mono::new_<Bar> (1, 2.0);
* mono::delete_<Foo> (foo);
*
* Use mono::delete_ to delete objects allocated with new_.
*
* This template can be used with user-defined classes, as well as with the
* builtin types such as 'bool', 'char', 'int', 'Foo*' etc.
*/
template <typename T, typename... Args>
inline
T* new_ (Args&&... args) {
void *ptr = mono::alloc::detail::allocate (sizeof (T));
return !ptr ? nullptr : new (ptr) T (std::forward<Args>(args)...);
}
/**
* Use the delete_ function to deallocate objects allocated with mono::new_
*
* class Foo : public mono::alloc::polymorphic_base {}
* class Bar : public Foo { public: Bar (int x, double y); }
* Foo *foo = mono::new_<Bar> (1, 2.0);
* mono::delete_ (foo);
*
*/
template <typename T>
inline
void delete_ (T* t) {
if (t == nullptr)
return;
void *ptr = static_cast<void*>(t);
t->~T ();
mono::alloc::detail::deallocate (ptr);
}
} // mono
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment