ããããŒãã¡ã€ã«<memory_resource>ã§å®çŸ©ãããŠããã¡ã¢ãªãŒãªãœãŒã¹ã¯ãåçã¹ãã¬ãŒãžã確ä¿ããããã®C++17ã§è¿œå ãããã©ã€ãã©ãªã ããã®ç¹åŸŽã¯ä»¥äžã®éãã
- ã¢ãã±ãŒã¿ãŒã«å€ããæ°ããã€ã³ã¿ãŒãã§ãŒã¹ãšããŠã®ã¡ã¢ãªãŒãªãœãŒã¹
- ããªã¢ãŒãã£ãã¯ãªæ¯ãèããå¯èœã«ããã¢ãã±ãŒã¿ãŒ
- æšæºã§æäŸãããæ§ã ãªç¹æ§ãæã£ãã¡ã¢ãªãŒãªãœãŒã¹ã®å®è£
ã¡ã¢ãªãŒãªãœãŒã¹ã¯ã¢ãã±ãŒã¿ãŒã«å€ããæ°ããã¡ã¢ãªç¢ºä¿ãšè§£æŸã®ããã®ã€ã³ã¿ãŒãã§ãŒã¹ãšããŠã®æœè±¡ã¯ã©ã¹ã ãã³ã³ãã€ã«æã«æåãå€ããéçããªã¢ãŒãã£ãºã èšèšã®ã¢ãã±ãŒã¿ãŒãšéããã¡ã¢ãªãŒãªãœãŒã¹ã¯å®è¡æã«æåãå€ããåçããªã¢ãŒãã£ãºã èšèšãšãªã£ãŠããã
void f( memory_resource * mem )
{
// 10ãã€ãã®ã¹ãã¬ãŒãžã確ä¿
auto ptr = mem->allocate( 10 ) ;
// 確ä¿ããã¹ãã¬ãŒãžãè§£æŸ
mem->deallocate( ptr ) ;
}
ã¯ã©ã¹std::pmr::memory_resourceã®å®£èšã¯ä»¥äžã®éãã
namespace std::pmr {
class memory_resource {
public:
virtual ~ memory_resource();
void* allocate(size_t bytes, size_t alignment = max_align);
void deallocate(void* p, size_t bytes, size_t alignment = max_align);
bool is_equal(const memory_resource& other) const noexcept;
private:
virtual void* do_allocate(size_t bytes, size_t alignment) = 0;
virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0;
virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;
};
}
ã¯ã©ã¹memory_resourceã¯std::pmråå空éã¹ã³ãŒãã®ãªãã«ããã
memory_resourceã䜿ãã®ã¯ç°¡åã ãmemory_resourceã®ãªããžã§ã¯ãã確ä¿ããããã¡ã³ããŒé¢æ°allocate( bytes, alignment )ã§ã¹ãã¬ãŒãžã確ä¿ãããã¡ã³ããŒé¢æ°deallocate( p, bytes, alignment )ã§ã¹ãã¬ãŒãžãè§£æŸããã
void f( std::pmr::memory_resource * mem )
{
// 100ãã€ãã®ã¹ãã¬ãŒãžã確ä¿
void * ptr = mem->allocate( 100 ) ;
// ã¹ãã¬ãŒãžãè§£æŸ
mem->deallocate( ptr, 100 ) ;
}
äºã€ã®memory_resourceã®ãªããžã§ã¯ãa, bããããšããäžæ¹ã®ãªããžã§ã¯ãã§ç¢ºä¿ããã¹ãã¬ãŒãžãããäžæ¹ã®ãªããžã§ã¯ãã§è§£æŸã§ãããšããa.is_equal( b )ã¯trueãè¿ãã
void f( std::pmr::memory_resource * a, std::pmr::memory_resouce * b )
{
void * ptr = a->allocate( 1 ) ;
// aã§ç¢ºä¿ããã¹ãã¬ãŒãžã¯bã§è§£æŸã§ãããïŒ
if ( a->is_equal( *b ) )
{// ã§ãã
b->deallocate( ptr, 1 ) ;
}
else
{// ã§ããªã
a->deallocate( ptr, 1 ) ;
}
}
is_equalãåŒã³åºãoperator ==ãšoperator !=ãæäŸãããŠããã
void f( std::pmr::memory_resource * a, std::pmr::memory_resource * b )
{
bool b1 = ( *a == *b ) ;
bool b2 = ( *a != *b ) ;
}
ç¬èªã®ã¡ã¢ãªãŒã¢ãã±ãŒã¿ãŒãmemory_resouceã®ã€ã³ã¿ãŒãã§ãŒã¹ã«åãããŠäœãã«ã¯ãmemory_resourceããæŽŸçããäžã§ãdo_allocate, do_deallocate, do_is_equalã®3ã€ã®privateçŽç²virtualã¡ã³ããŒé¢æ°ããªãŒããŒã©ã€ããããå¿ èŠã«å¿ããŠãã¹ãã©ã¯ã¿ãŒããªãŒããŒã©ã€ãããã
class memory_resource {
// éå
Ž
static constexpr size_t max_align = alignof(max_align_t);
public:
virtual ~ memory_resource();
private:
virtual void* do_allocate(size_t bytes, size_t alignment) = 0;
virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0;
virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;
};
do_allocate(bytes, alignment)ã¯å°ãªããšãalignmentãã€ãã§ã¢ã©ã€ã¡ã³ããããbytesãã€ãã®ã¹ãã¬ãŒãžãžã®ãã€ã³ã¿ãŒãè¿ããã¹ãã¬ãŒãžã確ä¿ã§ããªãã£ãå Žåã¯ãé©åãªäŸå€ãthrowããã
do_deallocate(p, bytes, alignment)ã¯äºåã«åã*thisããåŒã³åºãããallocate( bytes, alignment )ã§è¿ããããã€ã³ã¿ãŒpãè§£æŸããããã§ã«è§£æŸããããã€ã³ã¿ãŒpãæž¡ããŠã¯ãªããªããäŸå€ã¯æããªãã
do_is_equal(other)ã¯ã*thisãšotherãäºãã«äžæ¹ã§ç¢ºä¿ããã¹ãã¬ãŒãžãããäžæ¹ã§è§£æŸã§ããå Žåã«trueãè¿ãã
ããšãã°ãmalloc/freeã䜿ã£ãmemory_resouceã®å®è£ ã¯ä»¥äžã®éãã
// malloc/freeã䜿ã£ãã¡ã¢ãªãŒãªãœãŒã¹
class malloc_resource : public std::pmr::memory_resource
{
public :
//
~malloc_resource() { }
private :
// ã¹ãã¬ãŒãžã®ç¢ºä¿
// 倱æããå Žåstd::bad_allocãthrowãã
virtual void * do_allocate( std::size_t bytes, std::size_t alignment ) override
{
void * ptr = std::malloc( bytes ) ;
if ( ptr == nullptr )
{ throw std::bad_alloc{} ; }
return ptr ;
}
// ã¹ãã¬ãŒãžã®è§£æŸ
virtual void do_deallocate( void * p, std::size_t bytes, std::size_t alignment ) override
{
std::free( p ) ;
}
virtual bool do_is_equal( const memory_resource & other ) const noexcept override
{
return dynamic_cast< const malloc_resource * >( &other ) != nullptr ;
}
} ;
do_allocateã¯mallocã§ã¹ãã¬ãŒãžã確ä¿ããdo_deallocateã¯freeã§ã¹ãã¬ãŒãžãè§£æŸãããã¡ã¢ãªãŒãªãœãŒã¹ã§0ãã€ãã®ã¹ãã¬ãŒãžã確ä¿ããããšãããšãã®èŠå®ã¯ãªãã®ã§ãmallocã®æåã«ä»»ãããmallocã¯0ãã€ãã®ã¡ã¢ãªã確ä¿ããããšãããšããC11ã§ã¯èŠå®ããªããposixã§ã¯nullãã€ã³ã¿ãŒãè¿ãããfreeã§è§£æŸå¯èœãªäœããã®ã¢ãã¬ã¹ãè¿ããã®ãšããŠããã
do_is_equalã¯ãmalloc_resourceã§ããããã°ã©ã®ãªããžã§ã¯ããã確ä¿ãããã¹ãã¬ãŒãžã§ãã£ãŠãè§£æŸã§ããã®ã§ã*thisãmalloc_resourceã§ãããã©ãããdynamic_castã§ç¢ºèªããŠããã
std::pmr::polymorphic_allocatorã¯ã¡ã¢ãªãŒãªãœãŒã¹ãåçããªã¢ãŒãã£ãºã ãšããŠæ¯ãèãã¢ãã±ãŒã¿ãŒã«ããããã®ã©ã€ãã©ãªã ã
åŸæ¥ã®ã¢ãã±ãŒã¿ãŒã¯ãéçããªã¢ãŒãã£ãºã ãå®çŸããããã«èšèšãããŠãããäŸãã°ç¬èªã®custom_int_allocatoråã䜿ãããå Žåã¯ä»¥äžã®ããã«æžãã
std::vector< int, custom_int_allocator > v ;
ã³ã³ãã€ã«æã«äœ¿ãã¹ãã¢ãã±ãŒã¿ãŒã決å®ã§ããå Žåã¯ããã§ããã®ã ããå®è¡æã«ã¢ãã±ãŒã¿ãŒãéžæãããå Žåãã¢ãã±ãŒã¿ãŒããã³ãã¬ãŒãåŒæ°ã«åãèšèšã¯åé¡ã«ãªãã
ãã®ãããC++17ã§ã¯ã¡ã¢ãªãŒãªãœãŒã¹ãã³ã³ã¹ãã©ã¯ã¿ãŒåŒæ°ã«ãšããã¡ã¢ãªãŒãªãœãŒã¹ããã¹ãã¬ãŒãžã確ä¿ããå®è¡æããªã¢ãŒãã£ãã¯ã®æ¯ãèããããstd::pmr::polymorphic_allocatorã远å ãããã
äŸãã°ãæšæºå ¥åããtrueãfalseãå ¥åããããã«ãã£ãŠãã·ã¹ãã ã®ããã©ã«ãã®ã¡ã¢ãªãŒãªãœãŒã¹ãšãmonotonic_buffer_resourceãå®è¡æã«åãæ¿ããã«ã¯ã以äžã®ããã«ãããã
int main()
{
bool b;
std::cin >> b ;
std::pmr::mempry_resource * mem ;
std::unique_ptr< memory_resource > mono ;
if ( b )
{ // ããã©ã«ãã®ã¡ã¢ãªãŒãªãœãŒã¹ã䜿ã
mem = std::pmr::get_default_resource() ;
}
else
{ // ã¢ããããã¯ãããã¡ãŒã䜿ã
mono = std::make_unique< std::pmr::monotonic_buffer_resource >( std::pmr::get_default_resource() ) ;
mem = mono.get() ;
}
std::vector< int, std::pmr::polymorphic_allocator<int> > v( std::pmr::polymorphic_allocator<int>( mem ) ) ;
}
std::pmr::polymorphic_allocatorã¯ä»¥äžã®ããã«å®£èšãããŠããã
namespace std::pmr {
template <class T>
class polymorphic_allocator ;
}
ãã³ãã¬ãŒãå®åŒæ°ã«ã¯std::allocator<T>ãšåããã確ä¿ããåãäžããã
polymorphic_allocator() noexcept;
polymorphic_allocator(memory_resource* r);
std::pmr::polymorphic_allocatorã®ããã©ã«ãã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãã¡ã¢ãªãŒãªãœãŒã¹ãstd::pmr::get_default_resource()ã§ååŸããã
memory_resource *ãåŒæ°ã«åãã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãæž¡ãããã¡ã¢ãªãŒãªãœãŒã¹ãã¹ãã¬ãŒãžç¢ºä¿ã«äœ¿ããpolymorphic_allocatorã®çåæéäžãã¡ã¢ãªãŒãªãœãŒã¹ãžã®ãã€ã³ã¿ãŒã¯åŠ¥åœãªãã®ã§ãªããã°ãªããªãã
int main()
{
// p1( std::pmr::get_default_resource () ) ãšåã
std::pmr::polymorphic_allocator<int> p1 ;
std::pmr::polymorphic_allocator<int> p2( std::pmr::get_default_resource() ) ;
}
åŸã¯éåžžã®ã¢ãã±ãŒã¿ãŒãšåãããã«æ¯ãèãã
C++17ã§ã¯ãããã°ã©ã å šäœã§äœ¿ãããã¡ã¢ãªãŒãªãœãŒã¹ãžã®ãã€ã³ã¿ãŒãååŸããããšãã§ããã
memory_resource* new_delete_resource() noexcept ;
颿°new_delete_resourceã¯ã¡ã¢ãªãŒãªãœãŒã¹ãžã®ãã€ã³ã¿ãŒãè¿ããåç §ãããã¡ã¢ãªãŒãªãœãŒã¹ã¯ãã¹ãã¬ãŒãžã®ç¢ºä¿ã«::operator newã䜿ããã¹ãã¬ãŒãžã®è§£æŸã«::operator deleteã䜿ãã
int main()
{
auto mem = std::pmr::new_delete_resource() ;
}
memory_resource* null_memory_resource() noexcept ;
颿°null_memory_resourceã¯ã¡ã¢ãªãŒãªãœãŒã¹ãžã®ãã€ã³ã¿ãŒãè¿ããåç §ãããã¡ã¢ãªãŒãªãœãŒã¹ã®allocateã¯å¿ ã倱æããstd::bad_allocãthrowãããdeallocateã¯äœãããªãã
ãã®ã¡ã¢ãªãŒãªãœãŒã¹ã¯ãã¹ãã¬ãŒãžã®ç¢ºä¿ã«å€±æããå Žåã®ã³ãŒãããã¹ãããç®çã§äœ¿ããã
memory_resource* set_default_resource(memory_resource* r) noexcept ;
memory_resource* get_default_resource() noexcept ;
ããã©ã«ãã»ã¡ã¢ãªãŒãªãœãŒã¹ã»ãã€ã³ã¿ãŒãšã¯ãã¡ã¢ãªãŒãªãœãŒã¹ãæç€ºçã«æå®ããããšãã§ããªãå Žåã«ãã·ã¹ãã ãããã©ã«ãã§å©çšããã¡ã¢ãªãŒãªãœãŒã¹ãžã®ãã€ã³ã¿ãŒã®ããšã ãåæå€ã¯new_delete_resource()ã®æ»ãå€ãšãªã£ãŠããã
çŸåšã®ããã©ã«ãã»ã¡ã¢ãªãŒãªãœãŒã¹ã»ãã€ã³ã¿ãŒãšååŸããããã«ã¯ã颿°get_default_resourceã䜿ããããã©ã«ãã»ã¡ã¢ãªãŒãªãœãŒã¹ã»ãã€ã³ã¿ãŒãç¬èªã®ã¡ã¢ãªãŒãªãœãŒã¹ã«å·®ãæ¿ããã«ã¯ã颿°set_default_resourceã䜿ãã
int main()
{
// çŸåšã®ããã©ã«ãã®ã¡ã¢ãªãŒãªãœãŒã¹ãžã®ãã€ã³ã¿ãŒ
auto init_mem = std::pmr::get_default_resource() ;
std::pmr::synchronized_pool_resource pool_mem ;
// ããã©ã«ãã®ã¡ã¢ãªãŒãªãœãŒã¹ã倿Žãã
std::pmr::set_default_resource( &pool_mem ) ;
auto current_mem = std::pmr::get_default_resource() ;
// true
bool b = current_mem == pool_mem ;
}
æšæºã©ã€ãã©ãªã¯ã¡ã¢ãªãŒãªãœãŒã¹ã®å®è£ ãšããŠãããŒã«ãªãœãŒã¹ãšã¢ããããã¯ãªãœãŒã¹ãæäŸããŠããããã®ã¡ã¢ãªãŒãªãœãŒã¹ã®è©³çްã¯åŸã«è§£èª¬ããããããã§ã¯ãã®ããã®äºåç¥èãšããŠãæ±çšçãªã¡ã¢ãªãŒã¢ãã±ãŒã¿ãŒäžè¬ã®è§£èª¬ãããã
ããã°ã©ããŒã¯ã¡ã¢ãªãŒãæ°è»œã«ç¢ºä¿ããŠãããäŸãã°47ãã€ããšã151ãã€ãã®ãããªäžéå端ãªãµã€ãºã®ã¡ã¢ãªãŒã以äžã®ããã«æ°è»œã«ç¢ºä¿ããŠããã
int main()
{
auto mem = std::get_default_resource() ;
auto p1 = mem->allocate( 47 ) ;
auto p2 = mem->allocate( 151 ) ;
mem->deallocate( p1 ) ;
mem->deallocate( p2 ) ;
}
ããããæ®å¿µãªããçŸå®ã®ããŒããŠã§ã¢ãOSã®ã¡ã¢ãªç®¡çã¯ããã®ããã«æè»ã«ã¯ã§ããŠããªããäŸãã°ãããã¢ãŒããã¯ãã£ãŒãšOSã§ã¯ãã¡ã¢ãªã¯ããŒãžãµã€ãºãšåŒã°ããåäœã§ãã確ä¿ã§ããªãããããŠæå°ã®ããŒãžãµã€ãºã§ãã4KBã§ãã£ãããããããã·ã¹ãã ã®äœçŽãªã¡ã¢ãªç®¡çã䜿ã£ãŠäžã®ã³ãŒããå®è£ ããããšãããšã47ãã€ãçšåºŠã®ã¡ã¢ãªã䜿ãã®ã«3KBè¶ ã®ç¡é§ãçããããšã«ãªãã
ä»ã«ãã¢ã©ã€ã¡ã³ãã®åé¡ããããã¢ãŒããã¯ãã£ã«ãã£ãŠã¯ã¡ã¢ãªã¢ãã¬ã¹ãé©åãªã¢ã©ã€ã¡ã³ãã«é 眮ãããŠããªããšã¡ã¢ãªã¢ã¯ã»ã¹ãã§ããªãããèããããã©ãŒãã³ã¹ãèœã¡ãããšãããã
mallocãoperator newãªã©ã®ã¡ã¢ãªãŒã¢ãã±ãŒã¿ãŒã¯ãäœçŽãªã¡ã¢ãªç®¡çãé å¿ããå°ããªãµã€ãºã®ã¡ã¢ãªç¢ºä¿ãå¹ççã«è¡ãããã®å®è£ ãããŠããã
äžè¬çã«ã¯ã倧ããªé£ç¶ããã¢ãã¬ã¹ç©ºéã®ã¡ã¢ãªã確ä¿ãããã®äžã«ç®¡ççšã®ããŒã¿æ§é ãäœããã¡ã¢ãªãå¿ èŠãªãµã€ãºã«åãåºãã
// å®è£
ã€ã¡ãŒãž
// ã¹ãã¬ãŒãžãåå²ããŠç®¡çããããã®ãªã³ã¯ãªã¹ãããŒã¿æ§é
struct alignas(std::max_align_t) chunk
{
chunk * next ;
chunk * prev ;
std::size_t size ;
} ;
class memory_allocator : public std::pmr::memory_resource
{
chunk * ptr ; // ã¹ãã¬ãŒãžã®å
é ãžã®ãã€ã³ã¿ãŒ
std::size_t size ; // ã¹ãã¬ãŒãžã®ãµã€ãº
std::mutex m ; // åæçš
public :
memory_allocator()
{
// 倧ããªé£ç¶ããã¹ãã¬ãŒãžã確ä¿
}
virtual void * do_allocate( std::size_t bytes, std::size_t alignment ) override
{
std::scoped_lock lock( m ) ;
// ãªã³ã¯ãªã¹ãããã©ããååãªå€§ããã®æªäœ¿çšé åãæ¢ãããªã³ã¯ãªã¹ãæ§é äœãæ§ç¯ããŠè¿ã
// ã¢ã©ã€ã¡ã³ãèŠæ±ã«æ³šæ
}
virtual void * do_allocate( std::size_t bytes, std::size_t alignment ) override
{
std::scoped_lock lock( m ) ;
// ãªã³ã¯ãªã¹ããã該åœããéšåãåé€
}
virtual bool do_is_equal( const memory_resource & other ) const noexcept override
{
// *thisãšotherã§çžäºã«ã¹ãã¬ãŒãžãè§£æŸã§ãããã©ããè¿ã
}
} ;
ããŒã«ãªãœãŒã¹ã¯C++17ã®æšæºã©ã€ãã©ãªãæäŸããŠããã¡ã¢ãªãŒãªãœãŒã¹ã®å®è£ ã ãsynchronized_pool_resourceãšunsynchronized_pool_resourceã®äºã€ãããã
ããŒã«ãªãœãŒã¹ã¯ä»¥äžã®ãããªç¹åŸŽãæã€ã
- ããŒã«ãªãœãŒã¹ã®ãªããžã§ã¯ããç Žæ£ããããšãããã®ãªããžã§ã¯ãããallocateã§ç¢ºä¿ããã¹ãã¬ãŒãžã¯ãæç€ºçã«deallocateãåŒã°ããšãè§£æŸãããã
void f()
{
std::pmr::synchronized_pool_resource mem ;
mem.allocate( 10 ) ;
// 確ä¿ããã¹ãã¬ãŒãžã¯ç Žæ£ããã
}
- ããŒã«ãªãœãŒã¹ã®æ§ç¯æã«ãäžæµã¡ã¢ãªãŒãªãœãŒã¹ãäžããããšãã§ãããããŒã«ãªãœãŒã¹ã¯äžæµã¡ã¢ãªãŒãªãœãŒã¹ãããã£ã³ã¯ã®ããã®ã¹ãã¬ãŒãžã確ä¿ããã
int main()
{
// get_default_resource()ã䜿ããã
std::pmr::synchronized_pool_resource m1 ;
// ç¬èªã®äžæµã¡ã¢ãªãŒãªãœãŒã¹ãæå®
custom_memory_resource mem ;
std::pmr::synchronized_pool_resource m2( &mem ) ;
}
-
ããŒã«ãªãœãŒã¹ã¯ã¹ãã¬ãŒãžã確ä¿ããäžæµã¡ã¢ãªãŒãªãœãŒã¹ãããããŒã«ãšåŒã°ããè€æ°ã®ã¹ãã¬ãŒãžã確ä¿ãããããŒã«ã¯è€æ°ã®ãã£ã³ã¯ãä¿æããŠããããã£ã³ã¯ã¯è€æ°ã®åäžãµã€ãºã®ãããã¯ãä¿æããŠãããããŒã«ãªãœãŒã¹ã«å¯Ÿããdo_allocate(size, alignment)ã¯ãå°ãªããšãsizeãã€ãã®ãããã¯ãµã€ãºã®ããŒã«ã®ããããã®ãã£ã³ã¯ã®ãããã¯ãå²ãåœãŠãããã
ãããæå€§ã®ãããã¯ãµã€ãºãè¶ ãããµã€ãºã®ã¹ãã¬ãŒãžã確ä¿ããããšããå Žåãäžæµã¡ã¢ãªãŒãªãœãŒã¹ãã確ä¿ãããã
// å®è£
ã€ã¡ãŒãž
namespace std::pmr {
// ãã£ã³ã¯ã®å®è£
template < size_t block_size >
class chunk
{
blocks<block_size> b ;
}
// ããŒã«ã®å®è£
template < size_t block_size >
class pool : public memory_resource
{
chunks<block_size> c ;
} ;
class pool_resource : public memory_resource
{
// ããããã®ãããã¯ãµã€ãºã®ããŒã«
pool<8> pool_8bytes ;
pool<16> pool_16bytes ;
pool<32> pool_32bytes ;
// äžæµã¡ã¢ãªãŒãªãœãŒã¹
memory_resource * mem ;
virtual void * do_allocate( size_t bytes, size_t alignment ) override
{
// 察å¿ãããããã¯ãµã€ãºã®ããŒã«ã«ãã£ã¹ããã
if ( bytes <= 8 )
return pool_8bytes.allocate( bytes, alignment ) ;
else if ( bytes <= 16 )
return pool_16bytes.allocate( bytes, alignment ) ;
else if ( bytes < 32 )
return pool_32bytes.allocate( bytes, alignment ) ;
else
// æå€§ãããã¯ãµã€ãºãè¶
ããã®ã§äžæµã¡ã¢ãªãŒãªãœãŒã¹ã«ãã£ã¹ããã
return mem->allocate( bytes, alignment ) ;
}
} ;
}
-
ããŒã«ãªãœãŒã¹ã¯æ§ç¯æã«pool_optionsãæž¡ãããšã«ãããæå€§ãããã¯ãµã€ãºãšæå€§ãã£ã³ã¯ãµã€ãºãèšå®ã§ããã
-
ãã«ãã¹ã¬ããããåŒã³åºããŠãå®å šãªåæãåãsynchronized_pool_resourceãšãåæããšããªãunsynchronized_pool_resourceãããã
ããŒã«ãªãœãŒã¹ã«ã¯ãsynchronized_pool_resourceãšunsynchronized_pool_resourceããããã©ã¡ããã¯ã©ã¹å以å€ã¯åãããã«äœ¿ããããã ããsynchronized_pool_resourceã¯è€æ°ã®ã¹ã¬ããããåæã«å®è¡ããŠã䜿ããããã«å éšã§åæãåãããŠããã®ã«å¯Ÿããunsynchronized_pool_resourceã¯åæãè¡ããªããunsyncrhonized_pool_resourceã¯è€æ°ã®ã¹ã¬ããããåæã«åŒã³åºãããšã¯ã§ããªãã
// å®è£
ã€ã¡ãŒãž
namespace std::pmr {
class synchronized_pool_resource : public memory_resource
{
std::mutex m ;
virtual void * do_allocate( size_t size, size_t alignment ) override
{
// åæãã
std::scoped_lock l(m) ;
return do_allocate_impl( size, alignment ) ;
}
} ;
class unsynchronized_pool_resource : public memory_resource
{
virtual void * do_allocate( size_t size, size_t alignment ) override
{
// åæããªã
return do_allocate_impl( size, alignment ) ;
}
} ;
}
pool_optionsã¯ããŒã«ãªãœãŒã¹ã®æåãæå®ããããã®ã¯ã©ã¹ã§ã以äžã®ããã«å®çŸ©ãããŠãã
namespace std::pmr {
struct pool_options {
size_t max_blocks_per_chunk = 0;
size_t largest_required_pool_block = 0;
};
}
ãã®ã¯ã©ã¹ã®ãªããžã§ã¯ããããŒã«ãªãœãŒã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã«äžããããšã§ãããŒã«ãªãœãŒã¹ã®æåãæå®ã§ããããã ããpool_optionsã«ããæå®ã¯ãããŸã§ãç®å®ã§ãå®è£ ã«ã¯åŸã矩åã¯ãªãã
max_blocks_per_chunkã¯ãäžæµã¡ã¢ãªãŒãªãœãŒã¹ããããŒã«ã®ãã£ã³ã¯ãè£å ããéã«äžåºŠã«ç¢ºä¿ããæå€§ã®ãããã¯æ°ã ããã®å€ããŒãããå®è£ ã®äžéãã倧ããå Žåãå®è£ ã®äžéã䜿ããããå®è£ ã¯æå®ãããå°ããå€ã䜿ãããšãã§ãããããŸãããŒã«ããšã«å¥ã®å€ã䜿ãããšãã§ããã
largest_required_pool_blockã¯ããŒã«æ©æ§ã«ãã£ãŠç¢ºä¿ãããæå€§ã®ã¹ãã¬ãŒãžã®ãµã€ãºã ããã®å€ãã倧ããªãµã€ãºã®ã¹ãã¬ãŒãžã確ä¿ããããšãããšãäžæµã¡ã¢ãªãŒã¹ãã¬ãŒãžããçŽæ¥ç¢ºä¿ãããããã®å€ããŒãããå®è£ ã®äžéããã倧ããå Žåãå®è£ ã®äžéã䜿ããããå®è£ ã¯æå®ããã倧ããå€ã䜿ãããšãã§ããã
ããŒã«ãªãœãŒã¹ã®æ ¹æ¬çãªã³ã³ã¹ãã©ã¯ã¿ãŒã¯ä»¥äžã®éããsynchronizedãšunsynchronizedã©ã¡ããåãã ã
pool_resource(const pool_options& opts, memory_resource* upstream);
pool_resource()
: pool_resource(pool_options(), get_default_resource()) {}
explicit pool_resource(memory_resource* upstream)
: pool_resource(pool_options(), upstream) {}
explicit pool_resource(const pool_options& opts)
: pool_resource(opts, get_default_resource()) {}
pool_optionsãšmemory_resource *ãæå®ãããæå®ããªãå Žåã¯ããã©ã«ãå€ã䜿ãããã
void release();
確ä¿ããã¹ãã¬ãŒãžå šãŠãè§£æŸãããããšãæç€ºçã«deallocateãåŒã³åºãããŠããªãã¹ãã¬ãŒãžãè§£æŸããã
int main()
{
synchronized_pool_resource mem ;
void * ptr = mem.allocate( 10 ) ;
// ptrã¯è§£æŸããã
mem.release() ;
}
memory_resource* upstream_resource() const;
æ§ç¯æã«æž¡ããäžæµã¡ã¢ãªãŒãªãœãŒã¹ãžã®ãã€ã³ã¿ãŒãè¿ãã
pool_options options() const;
æ§ç¯æã«æž¡ããpool_optionsãªããžã§ã¯ããšåãå€ãè¿ãã
ã¢ããããã¯ãããã¡ãŒãªãœãŒã¹ã¯C++17ã§æšæºã©ã€ãã©ãªã«è¿œå ãããã¡ã¢ãªãŒãªãœãŒã¹ã®å®è£ ã ãã¯ã©ã¹åã¯monotonic_buffer_resourceã
ã¢ããããã¯ãããã¡ãŒãªãœãŒã¹ã¯é«éã«ã¡ã¢ãªãŒã確ä¿ããäžæ°ã«è§£æŸãããšããçšéã«ç¹åããç¹æ®ãªèšèšãããŠãããã¢ããããã¯ãããã¡ãŒãªãœãŒã¹ã¯ã¡ã¢ãªãŒè§£æŸããããã¡ã¢ãªãŒäœ¿çšéãã¢ããããã¯ã«å¢ãç¶ããã®ã§ããã®ååãã€ããŠããã
äŸãã°ã²ãŒã ã§1ãã¬ãŒã ãæç»ããéã«å€§éã«å°ããªãªããžã§ã¯ãã®ããã®ã¹ãã¬ãŒãžã確ä¿ãããã®åŸç¢ºä¿ããã¹ãã¬ãŒãžããã¹ãŠè§£æŸãããå Žåãèãããéåžžã®ã¡ã¢ãªãŒã¢ãã±ãŒã¿ãŒã§ã¯ãã¡ã¢ãªãŒçãè§£æŸããããã«ã¡ã¢ãªãŒå šäœã«æ§ç¯ãããããŒã¿æ§é ã蟿ããããŒã¿æ§é ãæžãæããªããã°ãªããªãããã®åŠçã¯é«ãã€ãããã¹ãŠã®ã¡ã¢ãªãŒçãäžæã«è§£æŸããŠããã®ã§ããã°ãããŒã¿æ§é ããã¡ãã¡èŸ¿ã£ããæžãæãããããå¿ èŠã¯ãªããã¡ã¢ãªãŒã®ç®¡çã¯ãåã«ãã€ã³ã¿ãŒã ãã§ããã
// å®è£
ã€ã¡ãŒãž
namespace std::pmr {
class monotonic_buffer_resource : public memory_resource
{
// é£ç¶ããé·å€§ãªã¹ãã¬ãŒãžã®å
é ãžã®ãã€ã³ã¿ãŒ
void * ptr ;
// çŸåšã®æªäœ¿çšã¹ãã¬ãŒãžã®å
é ãžã®ãã€ã³ã¿ãŒ
std::byte * current ;
virtual void * do_allocate( size_t bytes, size_t alignment ) override
{
void * result = static_cast<void *>(current) ;
current += bytes ; // å¿
èŠã§ããã°ã¢ã©ã€ã¡ã³ã調æŽ
return result ;
}
virtual void do_deallocate( void * ptr, size_t bytes, size_t alignment ) override
{
// äœãããªã
}
public :
~monotonic_buffer_resource()
{
// ptrã®è§£æŸ
}
} ;
}
ãã®ããã«ãåºæ¬çãªå®è£ ãšããŠã¯ãdo_allocateã¯ãã€ã³ã¿ãŒãå ç®ããŠç®¡çããã ãã ããªããªãã°è§£æŸåŠçããããªããããåã ã®ã¹ãã¬ãŒãžçã管çããããã®ããŒã¿æ§é ãæ§ç¯ããå¿ èŠããªããdo_deallocateã¯ãªã«ãããªãããã¹ãã©ã¯ã¿ãŒã¯ã¹ãã¬ãŒãžå šäœãè§£æŸããã
ã¢ããããã¯ãããã¡ãŒãªãœãŒã¹ã¯ä»¥äžã®ãããªç¹åŸŽãæã€ã
- deallocateåŒã³åºãã¯äœãããªããã¡ã¢ãªãŒäœ¿çšéã¯ãªãœãŒã¹ãç Žæ£ããããŸã§ã¢ããããã¯ã«å¢ãç¶ããã
int main()
{
std::pmr::monotonic_buffer_resource mem ;
void * ptr = mem.allocate( 10 ) ;
// äœãããªã
// ã¹ãã¬ãŒãžã¯è§£æŸãããªãã
mem.deallocate( ptr ) ;
// memãç Žæ£ãããéã«ç¢ºä¿ããã¹ãã¬ãŒãžã¯ãã¹ãŠç Žæ£ããã
}
- ã¡ã¢ãªãŒç¢ºä¿ã«äœ¿ãåæãããã¡ãŒãäžããããšãã§ãããã¹ãã¬ãŒãžç¢ºä¿ã®éã«ãåæãããã¡ãŒã«ç©ºããããå Žåã¯ãããã確ä¿ããã空ãããªãå Žåã¯äžæµã¡ã¢ãªãŒãªãœãŒã¹ãããããã¡ãŒã確ä¿ããŠããããã¡ãŒãã確ä¿ããã
int main()
{
std::byte initial_buffer[10] ;
std::pmr::monotonic_buffer_resource mem( initial_buffer, 10, std::pmr::get_default_resource() ) ;
// åæãããã¡ãŒãã確ä¿
mem.allocate( 1 ) ;
// äžæµã¡ã¢ãªãŒãªãœãŒã¹ããã¹ãã¬ãŒãžã確ä¿ããŠåãåºããŠç¢ºä¿
mem.allocate( 100 ) ;
// ååã®ã¹ãã¬ãŒãžç¢ºä¿ã§ç©ºããããã°ãããã
// ãªããã°æ°ãã«äžæµãã確ä¿ããŠåãåºãã
mem.allocate( 100 ) ;
}
-
äžã€ã®ã¹ã¬ãããã䜿ãããšãåæã«èšèšãããŠãããallocateãšdeallocateã¯åæããªãã
-
ã¡ã¢ãªãŒãªãœãŒã¹ãç Žæ£ããããšç¢ºä¿ããããã¹ãŠã®ã¹ãã¬ãŒãžãè§£æŸããããæç€ºçã«deallocateãåŒã°ãªããŠãããã
ã¢ããããã¯ãããã¡ãŒãªãœãŒã¹ã«ã¯ä»¥äžã®ã³ã³ã¹ãã©ã¯ã¿ãŒãããã
explicit monotonic_buffer_resource(memory_resource *upstream);
monotonic_buffer_resource(size_t initial_size, memory_resource *upstream);
monotonic_buffer_resource(void *buffer, size_t buffer_size, memory_resource *upstream);
monotonic_buffer_resource()
: monotonic_buffer_resource(get_default_resource()) {}
explicit monotonic_buffer_resource(size_t initial_size)
: monotonic_buffer_resource(initial_size, get_default_resource()) {}
monotonic_buffer_resource(void *buffer, size_t buffer_size)
: monotonic_buffer_resource(buffer, buffer_size, get_default_resource()) {}
åæãããã¡ãŒãåããªãã³ã³ã¹ãã©ã¯ã¿ãŒã¯ä»¥äžã®éãã
explicit monotonic_buffer_resource(memory_resource *upstream);
monotonic_buffer_resource(size_t initial_size, memory_resource *upstream);
monotonic_buffer_resource()
: monotonic_buffer_resource(get_default_resource()) {}
explicit monotonic_buffer_resource(size_t initial_size)
: monotonic_buffer_resource(initial_size, get_default_resource()) {}
initial_sizeã¯ãäžæµã¡ã¢ãªãŒãªãœãŒã¹ããæåã«ç¢ºä¿ãããããã¡ãŒã®ãµã€ãº(åæãµã€ãº)ã®ãã³ããšãªããå®è£ ã¯ãã®ãµã€ãºãããããã¯å®è£ äŸåã®ãµã€ãºããããã¡ãŒãšããŠç¢ºä¿ããã
ããã©ã«ãã³ã³ã¹ãã©ã¯ã¿ãŒã¯äžæµã¡ã¢ãªãŒãªãœãŒã¹ã«std::pmr_get_default_resource()ãäžããã®ãšåãæåã«ãªãã
size_tã²ãšã€ã ããåãã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãåæãµã€ãºã ããäžããŠåŸã¯ããã©ã«ãã®æ±ãã«ãªãã
åæãããã¡ãŒããšãã³ã³ã¹ãã©ã¯ã¿ãŒã¯ä»¥äžã®éãã
monotonic_buffer_resource(void *buffer, size_t buffer_size, memory_resource *upstream);
monotonic_buffer_resource(void *buffer, size_t buffer_size)
: monotonic_buffer_resource(buffer, buffer_size, get_default_resource()) {}
åæãããã¡ãŒã¯å é ã¢ãã¬ã¹ãvoid *åã§æž¡ãããã®ãµã€ãºãsize_tåã§æž¡ãã
void release() ;
ã¡ã³ããŒé¢æ°releaseã¯ãäžæµãªãœãŒã¹ãã確ä¿ãããã¹ãã¬ãŒãžããã¹ãŠè§£æŸãããæç€ºçã«deallocateãåŒã³åºããŠããªãã¹ãã¬ãŒãžãè§£æŸãããã
int main()
{
std::pmr::monotonic_buffer_resource mem ;
mem.allocate( 10 ) ;
// ã¹ãã¬ãŒãžã¯ãã¹ãŠè§£æŸããã
mem.release() ;
}
memory_resource* upstream_resource() const;
ã¡ã³ããŒé¢æ°uptream_resourceã¯ãæ§ç¯æã«äžããããäžæµã¡ã¢ãªãŒãªãœãŒã¹ãžã®ãã€ã³ã¿ãŒãè¿ãã