Yazılım geliştirme: C++17 ile özel ayırıcılar

Adanali

Active member
Yazılım geliştirme: C++17 ile özel ayırıcılar


  1. Yazılım geliştirme: C++17 ile özel ayırıcılar

Son yazımda “Yazılım Geliştirme: C++17 ile Polimorfik Ayırıcılar” C++17’de polimorfik ayırıcılar teorisini tanıttım. Bugün teoriyi uygulayacağım.

Duyuru








Rainer Grimm uzun yıllardır yazılım mimarı, ekip ve eğitim yöneticisi olarak çalışmaktadır. C++, Python ve Haskell programlama dilleri üzerine makaleler yazmaktan hoşlanıyor, aynı zamanda özel konferanslarda sık sık konuşmaktan da hoşlanıyor. Modern C++ adlı blogunda C++ tutkusunu yoğun bir şekilde ele alıyor.







Devam etmeden önce son yazım olan “Yazılım Geliştirme: C++17 ile Polimorfik Ayırıcılar” makalemin en önemli kısımlarını burada bulabilirsiniz.

Hızlı bir hatırlatma


Aşağıdaki program polimorfik ayırıcıları kullanır:


// polymorphicAllocator.cpp

#include <array>
#include <cstddef>
#include <memory_resource>
#include <vector>

int main() {

std::array<std::byte, 200> buf1; // (1)
std::pmr::monotonic_buffer_resource pool1{buf1.data(),
buf1.size()};
std::pmr::vector<int> myVec1{&pool1}; // (3)
for (int i = 0; i < 5; ++i) {
myVec1.push_back(i);
}

char buf2[200] = {}; // (2)
std::pmr::monotonic_buffer_resource pool2{std::data(buf2),
std::size(buf2)};
std::pmr::vector<int> myVec2{&pool2};
for (int i = 0; i < 200; ++i) {
myVec2.push_back(i);
}

}


Şimdi kalkmak istiyorum myVec2 odak. 200 intaçık olacak std::pmr::vector<int> itti. Bu 200 intBirine sığmıyor char buf[200] ve sonra atla std::pmr::new_delete_resource() yukarı akış tahsiscisi olarak adlandırılan ve küresel olanı çağıran new kalan elemanlar için Şimdi yukarı akış ayırıcısını araçsallaştıracağım.

Bir izleme ayırıcısı


Aşağıdaki program bir öncekini temel alır, bir izleme ayırıcısı kullanır ve dinamik bellek ayırmayı ve ayırmayı kaldırmayı görünür hale getirir.


// trackAllocator.cpp

#include <array>
#include <cstdlib>
#include <format>
#include <iostream>
#include <memory_resource>
#include <vector>

class TrackAllocator : public std::pmr::memory_resource {
void* do_allocate(std::size_t bytes,
std::size_t alignment) override {
void* p = std::pmr::new_delete_resource()->
allocate(bytes, alignment);
std::cout <<
std::format(" do_allocate: {:6} bytes at {}n",
bytes, p);
return p;
}

void do_deallocate(void* p,
std::size_t bytes,
std::size_t alignment) override {
std::cout <<
std::format(" do_deallocate: {:4} bytes at {}n",
bytes, p);
return
std::pmr::new_delete_resource()->
deallocate(p, bytes, alignment);
}

bool do_is_equal(const std::pmr::memory_resource& other)
const noexcept override {
return std::pmr::new_delete_resource()->is_equal(other);
}
};


int main() {

std::cout << 'n';

TrackAllocator trackAllocator; // (1)
std::pmr::set_default_resource(&trackAllocator); // (2)

std::cout << "myVec1n";

std::array<std::byte, 200> buf1;
std::pmr::monotonic_buffer_resource pool1{buf1.data(),
buf1.size()};
std::pmr::vector<int> myVec1{&pool1}; // (3)
for (int i = 0; i < 5; ++i) {
myVec1.push_back(i);
}

std::cout << "myVec2n";

char buf2[200] = {};
std::pmr::monotonic_buffer_resource pool2{std::data(buf2),
std::size(buf2)};
std::pmr::vector<int> myVec2{&pool2}; // (4)
for (int i = 0; i < 200; ++i) {
myVec2.push_back(i);
}

std::cout << 'n';

}


TrackAllocator bellek tahsisini ve serbest bırakılmasını takip eden bir ayırıcıdır. Arayüz sınıfından gelir std::pmr::memory_resource tüm depolama kaynaklarının türetildiği yer. TrackAllocator gerekli üç üye işlevini tanımlar do_allocate, do_deallocate VE do_is_equal. Her çağrı onu, gelen çağrıya yönlendirir. std::pmr::new_delete_resource daha öte. std:pmr::new_delete_resource varsayılan depolama alanıdır ve global çağrıları yapar new VE delete AÇIK. Üye fonksiyonunun görevi do_is_equal iki bellek kaynağının eşit olup olmadığını kontrol etmektir. Örneğin ilginç noktası, üye işlevlerde hafızayı tahsis etmem ve tahsis etmemdir. do_allocate VE do_deallocate görüş.

Biz bunu somutlaştırıyoruz TrackAllocator (satır 1) ve onu varsayılan kaynak (2) yapın. myVec1 (3) e myVec2 (4) bunu yukarı akış ayırıcısı olarak kullanın. Bu ayırıcı, birincil ayırıcı tüketildiğinde devreye girer. Bu geri dönüş şunun içindir: myVec1 için gerekli değil myVec2 Fakat sevimli.

Bu çıktı, dinamik tahsisi ve serbest bırakılmasını gösterir. myVec2Değin std::pmr::vector<int> Tüm intev sahipliği yapabilir.








Belirli bir kaba bir yukarı akış ayırıcısı da eklenebilir.

Tahsis etmeyen bir tahsis edici


std::pmr::null_resource_allocator özel bir distribütördür. Bunları tahsis için kullanmak tek bir sonuçla sonuçlanır std::bad_alloc-İstisna. Bu bellek kaynağı, belleğin yığında rastgele ayrılmamasını sağlar:


// nullMemoryResource.cpp

#include <array>
#include <cstddef>
#include <iostream>
#include <memory_resource>
#include <string>
#include <vector>

int main() {

std::cout << 'n';

std::array<std::byte, 2000> buf;
std::pmr::monotonic_buffer_resource pool{buf.data(),
buf.size(), // (1)
std::pmr::null_memory_resource()};
std::pmr::vector<std::pmr::string> myVec{&pool}; // (2)
try {
for (int i = 0; i < 100; ++i) { // (3)
std::cerr << i << " ";
myVec.emplace_back("A short string");
}
}
catch (const std::bad_alloc& e) { // (4)
std::cerr << 'n' << e.what() << 'n';
}

std::cout << 'n';

}


İlk önce yığına bellek ayırıyorum ve başlatıyorum std::pmr::monotonic_buffer_resource Bununla birlikte. Bu yüzden bu hafıza kaynağını kullanıyorum ve std::pmr::null_memory_resource bir yukarı akış distribütörü olarak (1). (2)’de bir tane yaratıyorum std::pmr::vector<std::pmr::string>. bende bir tane olduğundan std::pmr::string dize ayrıca bellek kaynağını ve onun yukarı akış ayırıcısını kullanır. Eğer ben std::pmr::vector<std::string> kullanmak, kullanmak std::string küresel tahsisçiler new VE delete. Son olarak (3)’te 100 dize oluşturuyorum ve (4)’te bir tane yakalıyorum. std::bad_alloc-İstisna. Hak ettiğimi aldım: 100 tel bir dizeye sığmıyor std::array<std::byte, 2000>-Tampon. 17 dizeden sonra arabellek tükenir.








Sıradaki ne?


THE std::pmr::monotonic_buffer Mükemmel özelliklere sahiptir. Oldukça hızlıdır ve hafızada yer açmaz. Bir sonraki yazımda rakamları sunacağım.


(kendim)



Haberin Sonu
 
Üst