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 aunique_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 aunique_ptr<MNumber>&
and adapt the stack and map variables to work withunique_ptr<MObject>&
- Use
shared_ptr
. I don't thinkshared_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.
-
What's the VM currently written in?raptortech97– raptortech972014年11月29日 21:56:44 +00:00Commented 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– scripts2014年11月29日 22:13:58 +00:00Commented 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 slowratchet freak– ratchet freak2014年11月29日 22:21:01 +00:00Commented 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– scripts2014年11月29日 22:29:30 +00:00Commented Nov 29, 2014 at 22:29
-
it's on the VM specification, i just ported it over. I don't like it eitherscripts– scripts2014年11月30日 14:42:45 +00:00Commented Nov 30, 2014 at 14:42
1 Answer 1
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.
-
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– scripts2014年11月30日 00:28:43 +00:00Commented Nov 30, 2014 at 0:28
-
Good luck with the C++ interop - you'll need it.DeadMG– DeadMG2014年11月30日 09:44:10 +00:00Commented Nov 30, 2014 at 9:44