I am attempting to construct a bunch of objects that can share data, but aren't coupled to each other. What I want is for the fields of each object to be a shared_ptr to whatever data they need. Once all the objects are created, this will fulfill all my needs, but my issue is how to distribute the information needed to create the shared_ptr's, since the types can be anything.
I will be creating all objects that share a set of data at once inside a factory object. Also, each shared field will have an enum entry to signify the attribute type (not data type). For instance the enum will have an entry that is Position, and every object that needs position information will use enum to key into a map to find the information it needs to create the shared_ptr.
What I want from my system is this:
Pass an SetEnum to the factory, which defines which "set" of objects to create, along with an optional map<AttributeEnum, ??> that defines the initial data of set of objects
Create the necessary objects, using a map<AttributeEnum, ??> to create shared_ptr's as fields in each of the objects. If the object needs a field corresponding to a specific value of AttributeEnum, it will pull its value from the map. If that value is not a key in the map, it will create it with a default value, and add it to the map for future objects to use. This step can be done during or after construction if a method with a template type would be helpful to solve the issue.
The issue is that I want errors at compile time, not run time. How can I map AttributeEnum to a type? For example, every field corresponding to an AttributeEnum value of Position will have type shared_ptr<double>, but I want a compile error if I attempt to associate Position with, for instance, shared_ptr<int>. My question is how to go about this?
A couple different systems I have thought of (albeit none of them ensure the errors at compile time):
Pass around a std::map<Enum, shared_ptr<void> > and static cast the shared_ptr's to the appropriate types.
Construct the objects, then iterate through the Enum, checking each object for which attributes it needs, then passing the proper pointers to it.
Having one object "own" each attribute, and force the other to get the information via a message-passing system.
I am considering storing two parallel sets of data, the AttributeEnum having entry Position, and compiler constants that would define the types such as #define POSITION double, then I would simply use POSITION for the type where ever I must, but this would make the code much harder to read.
Related
Actually, I want to pass an object to function by taking input from User. There are many objects and I want user to tell which object to pass. One way that I can think of is by using if/else-if statements (e.g if user says 1(int) then it means object-1). But is there any direct method by which I can directly take object as input. So I can pass it to function without using if/else-if statements.
You cannot have a user input an object directly out-of-the-box, but you can certainly write code to obtain that result (for example by implementing deserialization and receiving a JSON representation of the object).
However, if I understood your question correctly, you have a predefined set of objects with known integer keys. In that case, the most straightforward way is to store these objects in a container, such as std::map<int, YourObject> (or an std::vector<YourObject> if your keys are easily mappable to [0;N)). Once you've had the user input the key, you can then lookup into the container to retrieve the corresponding object via the container's at() member function.
When is it advantageous to use Record type vs a Class in Chapel? On IRC someone mentioned that Records distribute over locales better or something.
Records and classes are similar in Chapel in that they both support the creation of objects with fields and methods. That said, there are some major differences as well . Here's a quick review of some of those differences (tl;dr: records are roughly like C structs while classes support class hierarchies, dynamic dispatch, etc.), followed by a summary that gives some indications as to when you might choose to use one or the other:
Nature of Variables
record variables represent a record object directly
class variables represent a reference (pointer) to a class object
Put another way, a record variable is the record object, such that there is no distinguishing between the two. In contrast, a class variable points to a class object which may be stored on a different locale from the variable itself (i.e., class variables can refer to objects stored across distributed memories).
An implication of this is that when one record is assigned to another, the value of the RHS record is copied to the LHS record's value (e.g., typically the fields of the RHS record are copied to the fields of the LHS record). Another implication is that records have to define (or use the compiler-provided) copy initializers, and often provide 0-argument initializers to establish new record objects.
In contrast, when one class is assigned to another it makes the LHS class variable refer (point) to the same object as the RHS class variable. In addition, because class variables are pointers, they have the option of storing the nil value as a sentinel (though Chapel also supports non-nilable class variables that avoid the need for runtime checks or the risk of nil-pointer dereferences).
Allocation/Deallocation
class objects are allocated on the heap and can be governed by various memory management policies
record objects are allocated "in place" (e.g., on the current stack frame) and are automatically de-allocated (e.g., when they go out of scope)
This means that the lifetime of a class object can be independent of the program's structure, where it relies on one of several policies to manage its memory (owned, shared, borrowed, unmanaged). In contrast, record objects can be thought of as always being automatically memory managed, yet constrained by lexical scoping.
As a specific example, if you have an array of classes, you've typically created a contiguous sequence of pointers that may refer to objects living anywhere on the system (the local heap or some other locale's heap). Whereas if you have an array of records, its storage will typically be a contiguous sequence of record objects.
An implication of this is that if you want to create a "pointer-based" data structure in Chapel—like a linked list, tree, or graph—you will typically use class objects to store the nodes of that data structure with fields of class type to refer to their neighbors (whereas it would be challenging to represent these nodes using records since Chapel has no pointers and they're allocated in-place; put another way, a Chapel record cannot contain fields of its own type because it would effectively result in an infinitely recursive data structure).
Inheritance / Method Dispatch
a class can be declared as a subclass of another class, supporting virtual methods / dynamic dispatch
records do not support object hierarchies nor virtual/dynamic dispatch
This means that if you want to create an object hierarchy as in Java or C++, you'll want to use classes, and that initializers for such class hierarchies are themselves hierarchical.
Summary
Given these distinctions, you'll typically want to use a class if:
you want to create a "pointer-based" data structure (e.g., a linked list or binary tree) because class types can refer to themselves / one another using class variable fields
you want to create object hierarchies supporting dynamic method dispatch
you want to work with objects that are not constrained by their lexical scope
you want to work with objects whose identity matters
You'll typically want to use a record if:
value matters more than identity and it's OK to copy that value around
you want object memory to be managed by the variable's scope (though owned classes can have this effect as well)
you want more control over how objects are laid out in memory
In practice, combining the two can be quite powerful. For example, a record with a class field can be used to create a reference-counted object by having the class implement the object's identity and the record implement the reference counting semantics via assignment overloads and copy initializers to deal with the cases when copies of the record enter and leave scope, are assigned, etc. (however, note that shared classes in Chapel provide this capability directly, so this is just an illustration not a common practice).
My question is probably just a simple question about using the c++ language, but the background/motivation involves networking code, so I'll include it
Background:
I have an application with a bunch of balls moving around according to various rules. There is a server and a client that should be as synchronized as possible about the state of each ball.
I'm using Google's Protocol Buffers to create message objects that allow the client to set up or update each ball. Balls have different states, and each ball might need to be transmitted to the client using a different message class generated by GPB. For example, one type of ball updates its position using a fixed acceleration vector, so the message corresponding to that type of ball would have position,velocity, and acceleration.
I want to store these message objects in a data structure that organizes them by position, so that clients can access only message objects that are nearby. But each message has a different class type, so I don't know how to correctly put them all in a structure.
If I were hand-writing the message classes, I would make them all be subclasses of an abstract Message base object, with an enum type member. Then I would store the messages as unique_ptrs to the abstract class and then do a static cast by the type enum whenever I needed to work with each object individually. Ideally, since I need to serialize the message objects (they each have a serializeToOutputStream(..)) function, I would make this function an abstract member of the base class and have each of the particular message classes override it, so that I could avoid a cast in some situations.
The problem is that I am not hand-writing these classes. They are generated by google's compiler. I'm sure such a situation has arisen before, so I wonder how I should deal with it in an elegant way, if there is one.
Language-Only Version of Question:
I have a fixed set of generated classes A,B,C,D... that all have a few common functions like serializeToStream(). It would be very tedious to alter these classes since their sources are generated by a compiler. I would like to store unique pointers or raw pointers to these objects in a data structure of some kind, like an std::map or std::vector, but I don't know how to do this. If possible it would be great to call some of the functions that they all have without knowing which particular class I was dealing with (such as if I call the serialize function on all of them in a vector).
There is not good way to solve your problem. Only nasty haks. For example you can store pointer to object and pointer to method of some fake type in your map. But then you must cast your classes and pointers of its methods by reinterpret to this fake type. You must remember that all who will read that your code will scold you and may be better to find the approach to create common base.
First, my actual question
I have a shared pointer in a map, I want to remove that shared pointer from the map when there are no other references besides the shared pointer in the map itself, so the target gets released. How can I do this? Alternatively, what's a better design to solve my problem?
Background below:
Out of nostalgia I've been writing a MUD engine in C++ using a MySQL backend. I'm at the point now of persisting entities (things like accounts, characters and so forth in this context). I'm having a bit of trouble figuring out the best way to implement this and decided to seek some advice.
My current persistence architecture looks like this, taking character for an example
Character entity -> Character storage -> Character persistence -> MySQL
Character entity refers to the character itself and is analogous to a model in MVC. It doesn't have anything but data and only knows about other entities.
Character storage is a container currently responsible for holding instances of the character entity in memory. When a request is made to find a character either by ID or name, it checks it's memory, implemented as a map of std::string containing UUIDs to a std::shared_ptr. If we have an instance already in memory, we pass back a shared pointer, if not, we ask the persistence layer for it, store it in the map and then pass a shared pointer back to it.
The persistence layer is abstract, there's a character_persistence interface which has a concrete implementation of mysql_character_persistence, so I could easily switch to different forms of persistence.
I used reference counting and a templated entity_ptr type.
I created a entity_ptr_provider interface which defined the methods obtain(uuid) and release(uuid). An entity_ptr takes a templated argument of entity type (account, character etc), an entity of that type and an entity_ptr_provider.
On construction or copy of the entity_ptr type, it calls obtain on the entity_ptr_provider with the UUID of the entity so it can increment the references to it, when it's deconstructed, it calls release which allows the entity_ptr_provider to decrement the reference. When references reach 0, it's released from the table.
I have a bunch of structs in C++. I'd like to save it to file and load them up again. Problem is a few of my structs are pointers to base classes(/structs). So i'd need a way to figure out the type and create it. They really are just POD, they all have public members and no constructors.
What is the easiest way to save and load them from file? I have a LOT of structs and the only types i use are ints, pointers or c strings. I am thinking i could do some macro hacks. But really i have no idea what i should do.
Have you tried the Boost serialization library?
Don't roll your own here - use something well-developed and tested. One idea is Protocol Buffers
The pointers pose a specific issue: I suppose that multiple struct may actually refer to the same pointer and that you'd like a single pointer to be recreated when deserializing...
The first idea, to avoid boiler-plate code, is to create a compile-time reflexion tool:
BOOST_FUSION_ADAPT_STRUCT
BOOST_FUSION_ADAPT_STRUCT_NAMED
Those 2 macros will generate some wicked information on your struct so that you can then use them with Fusion algorithms, which cross the gap between compile-time and run-time.
Now, you need something that will be able to serialize and deserialize your data. Deserialization is usually a bit more difficult, though here you have the advantage of no polymorphism (which always makes things difficult).
Normally, on a first pass you identify the graph of objects to serialize, assign them all an ID, and use this ID in lieu of the pointer when serializing. For deserializing, you use a 3-columns map:
the map is ID -> (pointer to allocated object, list of pointers that could not be set)
allocate all objects, filling the ID map with a pointer to the allocated object each time
when you need to deserialize an ID, look it up in the map, if absent put a pointer to your pointer in the corresponding list
when you put the pointer to the allocated object in the map, take the time to fill all 'not set' pointers (and remove the list at the same time)
Of course, it's better to have frameworks handling it for you. You may try out s11n, if I remember correctly it handles cycles of references.