Is CRuntimmeClass the equivalent concept to malloc or new method in C++ - mfc

I am confused with the concept of dynamic memory allocation, so here is what I understand:
1 In CPP we have malloc or new, to be able to use memory on heap and we can "dynamically" change the size of the memory as we the program runs.
2 In MFC there is a CRuntimeClass (https://learn.microsoft.com/en-us/cpp/mfc/reference/cruntimeclass-structure?view=msvc-160#createobject), after using IMPLEMENT_DYNAMIC ,which I am not very familiar and I guess this is something similar to the the new/malloc functions

CRuntimeClass is MFC's way to encode metadata for types to allow it to create objects when the type is available as a string only. This is required when constructing document instances from a CDocTemplate, associating views with documents, or when serializing and deserializing structured data.
To make this happen, MFC maintains an application-global in-memory registry where respective types are registered. This registry can be queried for CRuntimeClass implementations given a type name.
CreateObject isn't the equivalent of new. It uses new to construct an instance of a type available as a string representation. It can be thought of as a factory method.

Related

What are opaque identifiers with regards to handles?

I have read this article and I encountered the following
A resource handle can be an opaque identifier, in which case it is
often an integer number (often an array index in an array or "table"
that is used to manage that type of resource), or it can be a pointer
that allows access to further information.
So a handle is either an opaque identifier or a pointer that allows access to further information. But from what I understand, these specific pointers are opaque pointers, so what exactly is the difference between these pointers ,which are opaque pointer, and opaque identifiers?
One of the literal meanings of "opaque" is "not transparent".
In computer science, an opaque identifier or a handle is one that doesn't expose its inner details. This means we can only access information from it by using some defined interface, and can't otherwise access information about its value (if any) or internal structure.
As an example, a FILE in the C standard library (and available in C++ through <cstdio>) is an opaque type. We don't know if it is a data structure, an integer, or anything else. All we know is that a set of functions, like fopen() return a pointer to one (i.e. a FILE *) and other functions (fclose(), fprintf(), ....) accept a FILE * as an argument. If we have a FILE *, we can't reliably do anything with it (e.g. actually write to a file) unless we use those functions.
The advantage of that is it allows different implementations to use different ways of representing a file. As long as our code uses the supplied functions, we don't have to worry about the internal workings of a FILE, or of I/O functions. Compiler vendors (or implementers of the standard library) worry about getting the internal details right. We simply use the opaque type FILE, and pointers to it, and stick to using standard functions, and our code works with all implementations (compilers, standard library versions, host systems)
An opaque identifier can be of any type. It can be an integer, a pointer, even a pointer to a pointer, or a data structure. Integers and pointers are common choices, but not the only ones. The key is only using a defined set of operations (i.e. a specific interface) to interact with those identifiers, without getting our hands dirty by playing with internal details.
A handle is said to be "opaque" when client code doesn't know how to see what it references. It's simply some identifier that can be used to identify something. Often it will be a pointer to an incomplete type that's only defined within a library and who's definition isn't visible to client code. Or it could just be an integer that references some element in some data structure. The important thing is that the client doesn't know or care what the handle is. The client only cares that it uniquely identifies some resource.
Consider the following interface:
widget_handle create_widget();
void do_a_thing(widget_handle);
void destroy_widget(widget_handle);
Here, it doesn't actually matter to the calling code what a widget_handle is, how the library actually stores widgets, or how the library actually uses a widget_handle to find a particular widget. It could be a pointer to a widget, or it could be an index into some global array of widgets. The caller doesn't care. All that matters is that it somehow identifies a widget.
One possible difference is that an integer handle can have "special" values, while pointer handle cannot.
For example, the file descriptors 0,1,2 are stdin, stdout, stderr. This would be harder to pull off if you have a pointer for a handle.
You really you shouldn't care. They could be everything.
Suppose you buy a ticket from person A for an event. You must give this ticket to person B to access the event.
The nature of the ticket is irrelevant to you, it could be:
a paper ticket,
an alphanumerical code,
a barcode,
a QR-Code,
a photo,
a badge,
whatever.
You don't care. Only A and B use the ticket for its nature, you are just carrying it around. Only B knows how to verify the validity and only A know how to issue a correct ticket.
An opaque pointer could be a memory location directly, while an integer could be an offset of a base memory address in a table but how is that relevant to you, client of the opaque handle?
In classic Mac OS memory management, handles were doubly indirected pointers. The handle pointed to a "master pointer" which was the address of the actual data. This allowed moving the actual storage of the object in memory. When a block was moved, its master pointer would be updated by the memory manager.
In order to use the data the handle ultimately referenced, the handle had to be locked, which would prevent it being moved. (There was little concurrency in the system so unless one was calling the operating system or libraries which might, one could also rely on memory not getting moved. Doing so was somewhat perilous however as code often evolved to call something that could move memory inside a place where that was not expected.)
In this design, the handle is a pointer but it is not an opaque type. A generic handle is a void ** in C, but often one had a typed handle. If you look here you'll find lots of handle types that are more concrete. E.g. StringHandle.

What is the purpose and usage of `memory_resource`?

The standard C++17 include a new namespace pmr including a set of classes grouped under the name of memory_resource.
After a search on internet, I found very few vulgarized information about it, the direct consequence is this question:
What are the main ideas behind pmr and especially pmr::memory_resource?
Detailing a bit more the question, some of the question marks in my head are:
What does it bring new, or what were the limitations it solve?
What is the difference with allocator?
Does polymorphic mean it is possible to select runtime the allocator provided to a container constructor? (e.g. for testing purpose)
Does it helps for implementing memory pool, or other memory management schemes?
Context:
In the intend of creating a memory pool allocator, I found information about this namespace. Reading names like pool_options or polymorphic_allocator raised my attention.
Related questions:
polymorphic_allocator: when and why should I use it?
A polymorphic_allocator is intended to let you have an allocator whose behavior is dynamically determined at runtime.
The only way to create a polymorphic_allocator is:
Default constructed, in which case it uses std::pmr::get_default_resource() return value, which is a memory_resource*.
Pass it a memory_resource*.
copy from another polymorphic_allocator.
So the point of customization for a polymorphic_allocator is creating a class that inherits from memory_resource and implementing its methods, or using one of the pre-declared memory_resources that are defined in std::pmr: (un)synchronized_pool_resource and monotonic_buffer_resource as types, or std::pmr::new_delete_resource() / std::pmr::null_memory_resource().
Suppose you want a your memory to be allocated using a strategy different than the 5 provided in std::pmr. Then you make a class that inherits from std::pmr::memory_resource, and pass it to a container which uses a polymorphic_allocator.

How to add a managed value type member to an unmanaged class?

I am trying to create a native C++ class called MyNativeClass that can be used by non-managed code. The member functions of MyNativeClass are implemented using managed code. In addition, the managed code needs a System::Numerics::BigInteger object, but when I attempt to add a System::Numerics::BigInteger bi_ field to MyNativeClass, I get
error C3265: cannot declare a managed 'bi_' in an unmanaged 'MyNativeClass'
Here is a simplified code listing which demonstrates what I am trying to achieve:
mynativeclass.h
class MyNativeClass
{
//...
public:
MyNativeClass();
//...
private:
System::Numerics::BigInteger bi_;
//...
};
mynativeclass.cc
MyNativeClass::MyNativeClass()
: bi_(BigInteger::Zero)
{
//...
}
I am not sure why this is not allowed.
Is there a way to do this?
You can't have managed data inside native types. The reason is that objects of native types are outside the purview of the garbage collector, and wouldn't keep managed objects from dying.
"I know that", you say. "But value types aren't kept on the managed heap and don't need to have their lifetime tracked by the garbage collector!" Quite true. But managed value types may contain handles to reference types. If the garbage collector can't see them, it can't keep their referents alive (or adjust them when the generational garbage collector compacts the heap / promotes objects to a higher generation).
It would be possible for blittable data (that doesn't contain handles) to be stored directly inside native memory. And in fact this is allowed for primitive types, which have dual identify (native int == System.Int32, for example). But it's not allowed for any composite types, presumably to keep the language rules simple. And BitInteger wouldn't be allowed anyway, because it does need to keep a handle to a variable-sized content area (using dotPeek or the reference source, it is revealed to be a array<unsigned>^) in order to support arbitrary precision.
The workaround is to use the GCHandle feature of the garbage collector, to keep objects alive from outside the garbage collector's realm. But replacing all handles inside a value class with GCHandles would result in an incompatible in-memory layout, so it wouldn't actually be the same type anymore. Simplest solution is to use gcroot<> (which is a nice C++/CLI interface to GCHandle) to a reference class type, and stick your managed value types inside that.
The C++/CLI team originally tried to allow hybrid types, but things got complicated and ended up with the separation rules you see now. There was a rather nice blog article about that but I can't find it now.

Object creation in boost::singleton_pool

I am trying to use boost::singleton_pool to create a large number of objects of a type 'Order' in a highly performance critical multithreaded application. Looking at the documentation, this is what I should be doing,
struct OrderTag{};
typedef boost::singleton_pool<OrderTag, sizeof(Order)> OrderPool;
boost::singleton_pool has a static member function malloc which returns pointer of the void*, but I need to create objects of the type Order in OrderPool by making calls to its constructor. Shall I be using boost::pool_allocator along with singleton_pool to do so?
Thanks.
In short: no. boost::pool_allocator implementation itself uses boost::singleton_pool and provides interface like std::allocator so you can use it with STL containers (but not only STL and not only containers) like vector, list etc. The UserAllocator concept is not something like boost::pool_allocator but it's a thing that controls memory management at the lowest level. For example I wrote UserAllocator that allocates memory via mmap() function and not uses heap at all.
So to create objects of a type 'Order' you should use boost::pool_allocator or boost::fast_pool_allocator. In your case it is not necessary to use boost::singleton_pool directly.
You can use singleton_pool with placement new like this:
Order* p = new (OrderPool.malloc()) Order(/* add ctor parameters if any*/);
or use boost::object_pool<Order>

Dynamic array of COM objects

I have an ATL COM object which needs to expose a collection of other COM objects, so clients can find out how many objects are in the collection (via a simple Count property which I can provide) and access the objects using its index. This collection of objects is dynamic - the count is not fixed - and I don't know how many there will be when my main (parent) object is constructed (so I can't create these objects in my FinalConstruct for example). The objects I want to expose only have read-only properties.
What I want to do is somehow create a std::vector of these objects the first time they are required. I want to use ATL smart COM pointers where possible so I don't need to manually manage reference counts, etc. but I'm not sure whether I should be using CComPtr, 'CComQIPtr', etc.
Assuming the objects I want to return are called IChild, I was hoping I could do something like this:
std::vector<CComPtr<IChild> > children;
...
CComPtr<IChild> child;
// Somehow instantiate an IChild?
...
children.push_back(child);
STDMETHODIMP Parent::GetAt(LONG index, IChild** pRet)
{
*pRet = children[index];
}
If anyone has any pointers on how I can achieve this, I would be very welcome. There is an excellent article on exposing a static object, but I can't find anything on the particular problem in hand.
Yes, std::vector< CComPtr<IChild> > is the way to do it - you will get a dynamic array of IChild* that manages the lifetime of IChild-derived objects. Once you want to convert the IChild* to a derived interface you'll have to use QueryInterface() the same way as you would use dynamic_cast with C++ objects.
There's no point to use CComQIPtr for the array. The primary use of CComQIPtr is to have a convenient way to call QueryInterface() on a pointer to an object that maybe implements the interface of interest. Instead of calling QueryInterface() and checking the result you invoke the CComQIPtr constructor and check whether the resulting object contains a non-null pointer. You could use CComQIPtr in the code that uses your array, but there's no point in using it for the array itself.
CComPtr<...> assumes that you assign it a compatible interface. CComQIPtr<...> calls IUnknown::QueryInterface to get the right interface. That's why it takes an additional GUID as a template parameter.
For your purposes, you should go with CComPtr, since you know you will always be initializing entries with an IChild.