
On Wed, Jun 24, 2009 at 3:49 AM, Stewart, Robert <Robert.Stewart@sig.com>wrote:
Simonson, Lucanus J wrote On Tuesday, June 23, 2009 11:38 AM
For multiple threads to use the allocator without interacting (we would prefer not to pay for locks if we aren't actually sharing information between threads) the allocator must differ by type. The only way that can be accomplished is if every thread calls a different function with a diferent instantiation of the allocator. We don't want to instantiate dozens of copies of the same functions at compile time to support many threads.
Only the storage need be unique in each case. Factor out the code that doesn't depend upon the tag type -- the behavior -- from that which does.
That said, it would be painful to create unique tags for each thread. Is it a problem for the allocator to look in TLS for that thread's storage?
I have thought on this and refactored the allocator signature to deal with both of these issues: template < class T , class Region = default_region_tag , class Access = default_access_tag> struct allocator; The basic usage is: struct region0 {}; struct region1 {}; struct region2 {}; BOOST_AUTO_TEST_CASE(test_shared_allocation) { // use default region and access std::list<int, monotonic::allocator<int> > list; // use specific region and access std::list<int, monotonic::allocator<int, region0, monotonic::shared_access_tag> > list; std::list<int, monotonic::allocator<int, region0, monotonic::thread_local_access_tag> > list; // equivalently: std::list<int, monotonic::shared_allocator<int, region0> > list; std::list<int, monotonic::thread_local_allocator<int, region0> > list; // equivalently, using wrapped container types defined in monotonic/container/*.hpp: monotonic::list<int> list; monotonic::list<int, region0, monotonic::shared_access_tag> list; monotonic::list<int, region1, monotonic::thread_local_access_tag> list; // use different regions monotonic::map<int, monotonic::list<monotonic::string<region2>, region1>, region0> map; } See https://svn.boost.org/svn/boost/sandbox/monotonic/boost/monotonic/ This deals with allocation from different regions based on a tag-type, and also allows the user to specifiy what access type to use. The remaining issue is that of local storage: BOOST_AUTO_TEST_CASE(test_local) { monotonic::local<region0> storage0; monotonic::local<region1> storage1; { std::list<int, monotonic::allocator<int, region0> > list0; std::list<int, monotonic::allocator<int, region1> > list1; fill_n(back_inserter(list0), 100, 42); fill_n(back_inserter(list1), 100, 42); std::basic_string<char, std::char_traits<char>, monotonic::allocator<char, region0> > str("foo"); str += "bar"; } } // region0 and region1 will be reset automatically Now, in this last case, it can be said that this is not re-entrant which is correct. However, there is a simple idiom that can be used: template <class Storage> void Reenter(Storage &store, size_t count) { if (count-- == 0) return; // use the Storage type to make new allocators typedef std::basic_string<char, std::char_traits<char>, typename Storage::template allocator<char>::type> String; std::list<String, typename Storage::template allocator<String>::type> list; /// ... use list and string types... they will use the storage correctly // can also use storage directly: char *bytes = store.allocate_bytes<123>(); string &str = store.create<string>("foo"); array<int, 300> &nums = store.create<array<int, 300> >(); store.destroy(str); Reenter(store, count); } struct my_local_region {}; void Start() { monotonic::local<my_local_region/*, access_type_tag*/> storage; Reenter(storage, 500); } // storage is reset on exit Of course, Start() is still not reentrant. It can't be, because it uses a static global. However, Reenter() is. It's the best that we can do. I did a test that used this idiom over using a normal allocator and thrashed a list of strings. The monotonic answer was twice the speed. Sure, it is more work, but twice the speed is twice the speed. I am interested to hear what people think of the new allocator model with tags for Region and Access, and the local model that is based on tags as well. Regards, Christian.