Управление ресурсами

Содержание

Слайд 2

Ресурс – это физический или виртуальный компонент компьютерной системы, обладающий свойством ограниченности. (©Wikipedia)

Ресурс – это физический или виртуальный компонент компьютерной системы, обладающий свойством

ограниченности.
(©Wikipedia)
Слайд 3

Физические ресурсы Процессор Оперативная память Жесткий диск Сетевой адаптер Видеокарта Звуковая

Физические ресурсы

Процессор
Оперативная память
Жесткий диск
Сетевой адаптер
Видеокарта
Звуковая карта
Устройства ввода/вывода (клавиатура, мышь, принтер, сканер

и т.п.)
Слайд 4

Виртуальные ресурсы Виртуальная память Файлы Сокеты Объекты синхронизации (мьютекс, критическая секция,

Виртуальные ресурсы

Виртуальная память
Файлы
Сокеты
Объекты синхронизации (мьютекс, критическая секция, семафор и т.п.)
Объекты межпроцессного

взаимодействия (pipes, mapped files, mailslots и т.п.)
Аттрибуты безопасности, дескрипторы объектов ОС и т.п.
Слайд 5

C++ storage duration categories Static – глобальные переменные, статические локальные переменные,

C++ storage duration categories

Static – глобальные переменные, статические локальные переменные, статические

члены классов. Создаются при запуске приложения и разрушаются при выходе.
Thread storage (C++ 11) – переменные, доступные только в потоке (обозначаются ключевым словом thread_local). Создаются при старте потока, разрушаются при завершении его работы.
Automatic – локальные переменные. Разрушаются на выходе из блока, в котором они созданы.
Dynamic – создаются при помощи операторов new и разрушаются при помощи операторов delete.
Слайд 6

Объекты с автоматической продолжительностью хранения Преимущества: 1. Быстрое выделение памяти. 2.

Объекты с автоматической продолжительностью хранения

Преимущества:
1. Быстрое выделение памяти.
2. Объекты на стеке

автоматически разрушаются при выходе из области видимости.
Недостатки:
1. Размер стека ограничен (по умолчанию в Visual C++ 1Mb для каждого потока).
2. Нужно знать размер объекта на этапе компиляции.
3. Стеком сложнее управлять.
Слайд 7

Специальные методы классов 1. Версии конструкторов копирования и операторов присваивания, генерируемые

Специальные методы классов

1. Версии конструкторов копирования и операторов присваивания, генерируемые компилятором,

осуществляют “shallow copy” членов. Необходимо переопределять их, если такое поведение неверно.
class Test {
int* m_data;
Test(const Test& other) {
m_data = new int(*other.m_data);
}
};
Слайд 8

Специальные методы классов 2. Проверяйте в операторе присваивание случай самоприсваивания: Test&

Специальные методы классов

2. Проверяйте в операторе присваивание случай самоприсваивания:
Test& operator=(const Test&

other) {
if (this != &other) {
delete m_data;
m_data = new int(*other.m_data);
}
return *this;
}
Слайд 9

Общая схема работы с ресурсами Захватить ресурс (open, create, allocate, attach)

Общая схема работы с ресурсами

Захватить ресурс (open, create, allocate, attach)
Использовать ресурс
Освободить

ресурс (close, free, delete, detach)
Внимание:
Если операция захвата ресурса возвращает статус успешности, всегда проверяйте его.
Используйте правильную операцию для освобождения ресурса
Слайд 10

Захват ресурса без освобождения class Singleton { static Singleton& get() {

Захват ресурса без освобождения

class Singleton
{
static Singleton& get()
{
static Singleton

instance;
return instance;
}
};

class Log {
void Flush();
~Log() { Flush() };
vector buffer;
};
int main() {
Log *log = new Log();
...
return 0;
}

Слайд 11

“Ручное” управление ресурсами void f() { Test *test = new Test;

“Ручное” управление ресурсами

void f() {
Test *test = new Test;
DoSomething(test);

delete test;
}

CRITICAL_SECTION cs;
void do_work()
{
::EnterCriticalSection(&cs);
f();
::LeaveCriticalSection(&cs);
}
void f()
{
throw runtime_error(“err”);
}

bool f() {
Test *tst = new Test;

// Fixed issue #12
if (!CheckSome()) {
return false;
}

test->Action();
delete test;
return true;
}

Слайд 12

Stack unwinding class Test { public: ~Test() { throw std::runtime_error(""); //

Stack unwinding

class Test {
public:
~Test()
{
throw std::runtime_error("");
// DON’T

DO IT!!!
}
};
void f() {
std::string s1{ "str" };
Test test;
throw std::runtime_error("");
}

void func()
{
string s1{ "test" };
vector v1{ 1, 4, 5 };
throw runtime_error("");
}

Слайд 13

Использование RAII (guards) class SocketGuard { public: SocketGuard(SOCKET sock_) : sock_

Использование RAII (guards)

class SocketGuard {
public:
SocketGuard(SOCKET sock_) :
sock_ (sock)

{}
operator SOCKET()
{
return sock_;
}
~ SocketGuard()
{
::closesocket(sock_);
}
private:
SOCKET sock_;
};

void f()
{
SOCKET sock = ::socket(…);
if (sock != INVALID_SOCKET)
{
SocketGuard guard(sock);
::connect(guard, …);
}
}

Слайд 14

std::auto_ptr class Test { }; void f() { std::auto_ptr p(new Test);

std::auto_ptr

class Test
{
};
void f()
{
std::auto_ptr p(new Test);
...
}

void f()
{
std::auto_ptr p1(new

Test);
...
std::auto_ptr p2 = p1;
}
// Unsafe, don't do it!!!
std::vector> vec;
Слайд 15

std::auto_ptr Недостатки: Не может использоваться в контейнерах STL. Не может быть

std::auto_ptr

Недостатки:
Не может использоваться в контейнерах STL.
Не может быть использован с new[].
Неочевидная

передача владения (при копировании и передаче в качестве параметра функции по значению).
Нельзя использовать с другими типами ресурсов, отличными от памяти.
Слайд 16

std::unique_ptr template default_delete > class unique_ptr { typedef ... pointer; typedef

std::unique_ptr

template default_delete>
class unique_ptr
{
typedef ... pointer;


typedef T element_type;
typedef D deleter_type;
};

// Specialization for arrays
template
class unique_ptr
{
typedef ... pointer;
typedef T element_type;
typedef D deleter_type;
};

Слайд 17

std::unique_ptr unique_ptr p1{ new int(10) }; //Error: assignment operator is deleted

std::unique_ptr

unique_ptr p1{ new int(10) };
//Error: assignment operator is deleted
unique_ptr p2 =

p1;
// Correct
unique_ptr p2 = std::move(p1);
// Array
unique_ptr p{ new int[10] };
// In container
vector> vec;
Слайд 18

std::unique_ptr void del(void* data){ VirtualFree(data, 0, MEM_RELEASE); } void *pData =

std::unique_ptr

void del(void* data){
VirtualFree(data, 0, MEM_RELEASE);
}
void *pData = VirtualAlloc(
nullptr,

0x4000,
MEM_COMMIT,
PAGE_READWRITE);
unique_ptr p(
pData, del);

auto del = [](void *data)
{
VirtualFree(data, 0, MEM_RELEASE);
};
unique_ptr p(
pData, del);

Слайд 19

std::make_unique unique_ptr p1{ new int(100) }; // The same unique_ptr p2{

std::make_unique

unique_ptr p1{ new int(100) };
// The same
unique_ptr p2{ make_unique(100)};
void f(unique_ptr p1,

bool);
bool f2(); // Can throw
{
// Not exception safe
f(unique_ptr(new SomeClass), f2());
}

// Exception safe
f(make_unique(), f2());
// Take ownership and can throw
void f(SomeClass* p1);
unique_ptr t{ new SomeClass };
f(t.get());
t.release();

Слайд 20

std::shared_ptr std::shared_ptr p1{new SomeClass }; std::shared_ptr p2 = p1; std::shared_ptr p{

std::shared_ptr

std::shared_ptr p1{new SomeClass };
std::shared_ptr p2 = p1;
std::shared_ptr p{ new int[10] };

// Compiles, but is an error
std::shared_ptr p{ new int[10], std::default_delete() };
void thread_func(shared_ptr>& vec) {
...
vec->push_back(5); // Not thread safe
...
}
Слайд 21

std::shared_ptr void del(void* data){ VirtualFree(data, 0, MEM_RELEASE); } void *pData =

std::shared_ptr

void del(void* data){
VirtualFree(data, 0, MEM_RELEASE);
}
void *pData = VirtualAlloc(
nullptr,

0x4000,
MEM_COMMIT,
PAGE_READWRITE);
shared_ptr p(pData, del);
Слайд 22

Внутреннее устройство shared_ptr

Внутреннее устройство shared_ptr

Слайд 23

Пример использования weak_ptr class ObjectLoader { map > cache_; shared_ptr LoadObject(int

Пример использования weak_ptr

class ObjectLoader {
map> cache_;
shared_ptr LoadObject(int id)
{
std::shared_ptr object;
std::weak_ptr cached = cache_.find(id);
if (cached != cache_.end()) {
object = cached.lock();
if (object != nullptr) return object;
}
object = LoadFromDatabase(id);
cache[id] = object;
}
};
Слайд 24

Передача smart pointers как аргумента void f(std::unique_ptr p); f(make_unique (10)); void

Передача smart pointers как аргумента

void f(std::unique_ptr p);
f(make_unique(10));
void f(std::unique_ptr& p)
{
p.reset(new

int(100));
}
std::unique_ptr p(new int(10));
f(p);

// Possible but meaningless
void f(const unique_ptr& p);
// If parameter cannot be null
void f(const Tst& p);
// If parameter can be null
void f(const Tst* p);

Слайд 25

Передача smart pointers как аргумента void f(std::shared_ptr arg); { std::shared_ptr p(new int(10); f(p); }

Передача smart pointers как аргумента

void f(std::shared_ptr arg);
{
std::shared_ptr p(new int(10);
f(p);


}
Слайд 26

Контейнеры void FillBuffer( void* pBuffer, size_t bufferSize); // version with raw

Контейнеры

void FillBuffer(
void* pBuffer,
size_t bufferSize);
// version with raw ponter
uint8_t

*buf = new uint8_t[size];
FillBuffer(buf, size);
delete[] buf;

// version with smart pointer
std::unique_ptr buffer{
new uint8_t[1024] };
FillBuffer(buffer.get(), 1024);
// version with vector
vector buffer(size);
FillBuffer(&buffer[0], size);

Слайд 27

Контейнеры // First DLL vector messages; FillMessages(messages); // Second DLL void

Контейнеры

// First DLL
vector messages;
FillMessages(messages);

// Second DLL
void FillMessages(vector&
messages)
{
for

(int i = 0; i < MsgCount(); ++i)
{
messages.push_back(GetMsg(i));
}
}
Слайд 28

Exception safety 1. Базовая гарантия – контейнер при возникновении исключения остается

Exception safety

1. Базовая гарантия – контейнер при возникновении исключения остается в

согласованном состоянии; нет утечек ресурсов (пример – вставка диапазона элементов).
2. Строгая гарантия – либо операция заканчивается успешно, либо она не выполняется вообще (пример vector::push_back).
3. No-throw (nofail) гарантия – операция всегда заканчивается успешно (пример std::swap).
Гарантия предоставляется, если код, предоставляемый пользователем, не оставляет элементы контейнера в недопустимом состоянии; не приводит к утечкам ресурсов и деструкторы не кидают исключений.