RAII і Maybe-семантика
Sep. 2nd, 2011 08:53 pmУ C++ ідіома RAII, мабуть, одна із найкорисніших і найбільш широко вживаних штук. Починаючи від ScopedPtr і ScopedLock, і закінчуючи BusyCursor (встановлення курсора "зайнятості" для довготривалих процесів) і Logger (Logger(Level::debug).stream() << "Debug output";) . Але іноді її властивостей виконувати роботу на початку і в кінці scope не вистачає.
Візьмемо, наприклад, створення pid-файлу. RAII чудово підходить: після "демонизації" створюємо файл, при зупинці знищуємо. А що робити, коли програма запускається без "демонизації"?
- не працює, бо scope замалий. Потрібний такий RAII, що може не існувати. Maybe-RAII. Можна, звісно, зробити так:
але тоді ми отримуємо всі "мінуси" додаткового конструктора. А саме, проміжний стан об’єкту: створений, але ще невалідний. Ні риба ні м’ясо.
Еквівалентом Maybe у C і C++ виступає вказівник. Він може вказувати на значення (Just T) або бути NULL (Nothing). Але простий вказівник не реалізує RAII. Тоді на допомогу приходить ScopedPtr:
Найцікавішим тут є той факт що RAII використовується двічі: для ScopedPtr і для PIDFile. У якості ScopedPtr можна використати, наприклад, boost::scoped_ptr.
Візьмемо, наприклад, створення pid-файлу. RAII чудово підходить: після "демонизації" створюємо файл, при зупинці знищуємо. А що робити, коли програма запускається без "демонизації"?
if (options.isDaemon()) { MakeDaemon(...); PIDFile pid(...); }
- не працює, бо scope замалий. Потрібний такий RAII, що може не існувати. Maybe-RAII. Можна, звісно, зробити так:
PIDFile pid(...); if (options.isDaemon()) { MakeDaemon(...); } pid.init();
але тоді ми отримуємо всі "мінуси" додаткового конструктора. А саме, проміжний стан об’єкту: створений, але ще невалідний. Ні риба ні м’ясо.
Еквівалентом Maybe у C і C++ виступає вказівник. Він може вказувати на значення (Just T) або бути NULL (Nothing). Але простий вказівник не реалізує RAII. Тоді на допомогу приходить ScopedPtr:
ScopedPtrpid; if (options.isDaemon()) { pid = new PIDFile(...); MakeDaemon(...); }
Найцікавішим тут є той факт що RAII використовується двічі: для ScopedPtr і для PIDFile. У якості ScopedPtr можна використати, наприклад, boost::scoped_ptr.