简体   繁体   中英

std::map allocators binded to heaps for all keys and values?

I wonder how could I create something like std::map<T1, T2>(T1allocator, T2allocator, T1deallocator, T2deallocator) so that when any one tries to insert a key<->value pair into my map from any heap or modify some data data will be created in original map creators heap and not in other heaps that try to pass into it thire own data?


Say we have a DLL library (on Windows) and we dinamically (at runtime) attach it to our main app. That library ( as the main app) was compiled with static runtime. So will potentially get 2 difrent STL's and deffenetly 2 difrent heaps - one with DLL one with App.

Say now we want for our plugin/dll to work only with memory from our main app heap.

Lets get to some simple demo code.

We created a simple plugin interface that is known to our main app:

class plugin:
{
public:
    virtual void pass_and_modify_data( boost::shared_ptr<std::map<std::string, std::string> >  a) =0;
};

We created pugin DLL with:

#include "plug_in_interface.h"
class my_plugin: public plugin
{
    public:
        virtual void pass_and_modify_data( boost::shared_ptr<std::map<std::string, std::string> >  a)
        {
            a->insert(std::pair<std::string, std::string>("hello", "World"));
            (*a)["world"] = "hello";
        }
};

Now we want to pass map from our app to plugin but make all walues passed to our map be allocated on Main apps heap.

How to do such thing - how to make std::map reallocate given keys and values into main app hash with out plugin code developer noticing? (here by noticing I mean stuff like putting into maps strings with custome deallocators or writting any special non trivial code)


Looking at sehe's answer and demo I want to create:

If I got it write my main would look like:

#include <iostream>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/flyweight.hpp>
#include "plug_in_interface.h"

using namespace boost;
using namespace boost::flyweights;
typedef flyweight<
    std::string,
    hashed_factory<
     boost::hash<std::string>,
    std::equal_to<key_value>,
    std::allocator<boost::mpl::_1> // here we get errors like C2065: 'key_value' : undeclared identifier    
    >
> customString;

int main()
{
 // boring part -  load plugin... into something like boost::shared_ptr<plugin> my_plugin 
 //intresting part - create map in main heap and make all its values and keys be forced to be allocated or reallocated in main heap

    std::cout << std::endl << "Map allocator mased memory management:" << std::endl;
    std::cin.get();
    {
        boost::shared_ptr<std::map<std::string, std::string> > a  (new std::map<customString, customString>());
        my_plugin->pass_and_modify_data(a);
        std::cout << "modified data: " << (*a)["hello"] << (*a)["world"] << std::endl;
    }
    std::cout << "removed data" << std::endl;
    std::cin.get();

  }

Currently I can not compile this thing because of the way customString type is defined.. compiler shows tons of compiler errors. How to make type def more correct?

Jenerally I am absolutly fine with stl::allocators only thing I really need is for allocator to be some how binded to heap (alike we can do with shared_ptrs), is such thing possible?

If you just want to provide functions to map that do the allocation, you're out of luck. The standard way to control memory management within an STL container is through allocators .

You cannot use separate allocators for the keys and values, because std::map only accepts one allocator template parameter ( std::map<Key, Value, Predicate, Allocator> ). But there is no reason to do so—a single allocator for both will suffice.

If you just want a custom allocator, it's straightforward to do. You can use one of the standard ones ( alloc , pthread_alloc , single_client_alloc , or malloc_alloc ), or read this tutorial to learn how to write your own. If you can provide more information about what problem you're trying to solve, I may be able to provide a more helpful answer.

You could use a Boost Flywheight or a Boost Optional.

Though not exactly like the standard containers, they allow factory/allocation strategies and you could use that. Of course, you'll end up with another level of indirection which may, or may not, be what you want.

See, eg http://www.boost.org/doc/libs/1_48_0/libs/flyweight/doc/tutorial/configuration.html#factories

hashed_factory<[Hash[,Pred[,Allocator]]]> ....

Suppose we would like to configure hashed_factory for a std::string flyweight with a special hash predicate special_hash and a custom allocator custom_allocator; this would be specified as follows:

 typedef flyweight< std::string, hashed_factory< special_hash<std::string>, std::equal_to<key_value>, custom_allocator<boost::mpl::_1> > > customString; 

Since Flyweights are inherently immutable , they would work better for the keys:

 std::map<customString, int> my_funky_map;

Now, use the default map allocator to specify where the map's elements (pairs) should be allocated.


The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM