2

I work for a company that use a custom DSL and my job is to port the VM to C++.

I'm trying to do this in compliance with the C++11 standard so i use auto when appropriate, the new for syntax, etc. But I'm having problem trying to "port" a part of the code that uses raw pointers to the new smart pointers.

On this DSL every object is derived from a base class called MObject, for example Numbers are handled by this class:

class MNumber : public MObject {
...
}

The class responsible for handling the VM memory looks like this:

class Mallocator {
...
std::vector<MObject*> memory; //where all objects go...

And to, for example, place a new MNumber in memory this is the function you call:

MNumber* Mallocator::newMNumber(double a) {
      MNumber* number = new MNumber {a};
      memory.push_back(number);
      INCRMEM(number); //updates memory usage and some other stuff 
      return number;

}

User defined variables are stored on a map like this: std::map<std::string, MObject*> And steps executed by the VM to create a new user defined variable are more or less like this:

//storing a value on the VM stack
MNumber* number = allocator->newMNumber(...); //allocate the object
stack.push_back(number); //put a reference to the allocated value on the stack

//retrieving object from the stack and creating the variable
string var_name = codeobj->getVarName(instr.arg); //get the name of the variable from user code
value = stack.back(); // get the pointer to the allocated object from the stack
curr_frame->env->setVar(var_name, value); //associate the name to the object in the current scope

It makes sense to me that the Mallocator object should hold ownership of every allocated MObject and the stack and the variables map should hold a "reference" to the allocated memory, since they only read the values. After searching the web for a few days and watching the Herb Sutter talk "Back to the Basics! Essentials of Modern C++ Style" i collected a few ideas:

  • On the newMNumber create a unique_ptr and use the .get() method to return a raw pointer. Wouldn't this defeat the purpose of using smart pointers?
  • On the newMNumber return a unique_ptr<MNumber>& and adapt the stack and map variables to work with unique_ptr<MObject>&
  • Use shared_ptr. I don't think shared_ptr is the solution because the ownership is not shared
  • Leave it the way it is and manage the pointers life-cycle myself (i'm already doing this anyway)

So my questions are: what is the right way to tackle this problem? Is my design correct? What other options i have?

PS1: Mallocator is a singleton and it is the sole responsible for allocating the objects and deleting objects from memory the rest of the VM only works with the pointers returned by Mallocator.

PS2: The language has more Objects than just numbers but since i can't share the whole code i've used MNumber as an example.

PS3: Some objects, like strings and integers, are cached so, for example, the function (not shown here) newMNumber(int a) only allow one object per integer to exist.

Thanks.

5
  • What's the VM currently written in? Nov 29, 2014 at 21:56
  • Right now python. Another dev tried porting it to Java but he left the company. The main problem with the current one is speed.
    – scripts
    Nov 29, 2014 at 22:13
  • Passing a raw pointer when the receiving end doesn't own the object is fine. Though put a profiler on the case to find where it is slow Nov 29, 2014 at 22:21
  • The current one is the python one haha. I'm not a native english speaker, i think i expressed myself badly. There are 3 VMs: 1)the first one written in python. its working and is in production but it's slow 2)a partial port from the first one to java, made by another dev who left the company 3)my port of the first one written in c++ and the subject o this question. About passing a raw pointer: you're saying is ok to return a raw pointer using the .get method from the unique_ptr? Even if this raw pointer is going to be stored in another data structure, like the stack or maybe the variable map?
    – scripts
    Nov 29, 2014 at 22:29
  • it's on the VM specification, i just ported it over. I don't like it either
    – scripts
    Nov 30, 2014 at 14:42

1 Answer 1

3

On the newMNumber create a unique_ptr and use the .get() method to return a raw pointer. Wouldn't this defeat the purpose of using smart pointers?

No, no it would not.

The point of using smart pointers is about controlling who deletes the object, not who observes the object. It's perfectly fine under the smart pointer paradigm to observe the object owned by a smart pointer through a non-smart pointer or reference. In fact, this is a fairly common pattern that a class returns a non-owning pointer or reference to memory that it owns.

2
  • Thanks! Funny thing i was reading your website about the wide programming language and there's a lot of similarities between the DSL I'm working and the Wide programming language!
    – scripts
    Nov 30, 2014 at 0:28
  • Good luck with the C++ interop - you'll need it.
    – DeadMG
    Nov 30, 2014 at 9:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.