Skip to content

Instantly share code, notes, and snippets.

Massimo Tristano keebus

Block or report user

Report or block keebus

Hide content and notifications from this user.

Learn more about blocking users

Contact Support about this user’s behavior.

Learn more about reporting abuse

Report abuse
View GitHub Profile
@keebus
keebus / local_opaque_object.c
Last active Jul 18, 2018
Local opaque object in C
View local_opaque_object.c
// library.h -------------------------------------------------------------------
#define opaque(Type) Type; int $sizeof_##Type(void);
#define opaque_impl(Type) int $sizeof_##Type(void) { return sizeof(Type); }
#define local(Type) ((Type *)alloca($sizeof_##Type()))
// foo.h -----------------------------------------------------------------------
@keebus
keebus / cexceptions.md
Last active Aug 16, 2017
Exception-like code in C (gcc/clang)
View cexceptions.md

Lightweight exceptions in C (with gcc/clang)

For fun I implemented a lightweight exception mechanism for C that allows writing transactional code. This is what it looks like:

int device_create(device_t **odevice)
{
	throwbase(-1); // makes this function "throwing" with a default return value of -1.

	device_t *device = malloc(sizeof *device);
	check(device); 
View opaque_class.md

Opaque Class

I believe C++ classes implement encapsulation extremely poorly as they require private variables and functions to be declared together with the public interface, clashing with C-style code modularization based on header files inclusion. To implement real incapsulation, we would like to only present the class public interface in its header, hiding all the other information. Unfortunately the canonical ways to achieve this in C++ are both flawed as they introduce unnecessary overhead.

  1. One is Pimpls for Private Implementations. They rely on forward declaring a private class that actually implements the public class functionalities and then only holding a pointer to this private class within the public class. This adds one level of indirection, as now a pointer to the public class does not point to the data iself but to a pointer to the data.
  2. Virtual interfaces are the other way, which is even worse than Pimpls as they add overhead to each member function call.

Although C does not

@keebus
keebus / dynamic_traits.md
Last active Nov 22, 2017
Dynamic traits
View dynamic_traits.md

Dynamic Traits

During ordinary C++ development we ofter encounter the situation where we want to operate with similar objects through a common interface. C++ natively supports only one idiomatic way of implementing dynamic function dispatch, the _virtual_ keyword. The idiomatic, traditional OOP way to solve this problem in C++ is to declare pure-abstract classes, also called interfaces and implement them in other abstract or concrete classes in their declaration explicitly.

This solution has at least a couple of serious drawbacks:

  1. It introduces strong type coupling between the class that implements the interface and the interface itself. Specifically, the class needs to know in advance what interfaces it wants to implement. Although this is sometimes the case, it is not always the case, and more often this coupling is undesirable. Finally, C++ classes once declared cannot later on be opened, adding more implementations to interfaces. This means that you cannot, through standard C++, declare an
View finally.md

Finally

One of C++'s strengths is automatic code invocation at scope-exit (aka RAII). The traditional idea behind RAII of having specialized types for every resource type with a custom destructor that frees it is good in theory but in practice comes with a lot of friction and thus boiler-plate and frustration for the developer, that now has to create a new type for every little rollback operation he wants to perform. The problem is exacerbated with C++11 move operators: making a small "smart" class that does some form of cleanup now requires even more boilerplate.

Fortunately there's a way to neatly work around this, and the idea comes from D's scope keyword or Go's defer. We want a mechanism that tells the compiler to invoke a snippet of inlined code at scope exit. Something like

// Acquire a resource
Resource* resource = AcquireResource();

// Then whatever happens, release the resource when it goes out of scope.
You can’t perform that action at this time.