Re[3]: Шаблон для идиомы RAII
От: Юрий Жмеренецкий ICQ 380412032
Дата: 29.12.09 15:38
Оценка:
Здравствуйте, Basil2, Вы писали:

B>Здравствуйте, jazzer, Вы писали:


B>>>А вопрос такой. Наверняка эт не я один умный , и такие шаблоны уже существует. Линканите плз какой-нибудь более-менее известный и стандартный. (Без заточки под винду, как у меня, да и вообще хочется посмотреть на "тру" RAII-шаблон )


J>>Boost.ScopeExit

J>>http://www.boost.org/libs/scope_exit/doc/html/index.html

B>Дык я, собственно, как на ScopeExit посмотрел, так сразу и понял что надо делать свое


B>ScopeExit некрасив, использует макросы и генерит скрытый код. А мне нужно тупо вызвать CloseHandle() по окончанию блока, и все. Я и сделал, фактически, тот же ScopeExit, но для _одной_ функции и потому куда как более простой. Однако мой шаблон заточен именно под виндовый CloseHandle(). В частности, в нем даже прописано что функция возвращает int (т.е. виндовый BOOL), т.к. именно это CloseHandle() и возвращает. Т.е. как минимум для универсальности надо добавить в параметры шаблона возвращаемое значение, как-то избавиться от __stdcall (или не надо?), запретить копирование.


B>Мне казалось, что кто-нибудь это уже проделал...


В качестве идеи:


#include <boost/aligned_storage.hpp>
#include <boost/static_assert.hpp>
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <iostream>

namespace detail {

struct holder_base
{
    virtual ~holder_base(){}
};

template<class T>
struct holder : holder_base
{
    holder(const T& v) : functor(v) {}
    
    ~holder() {
        functor();
    }
    
    T functor;
};

template<std::size_t size>
struct on_scope_exit_base : boost::noncopyable
{
    template<class functor>
    on_scope_exit_base(const functor& e) {
        BOOST_STATIC_ASSERT(size > sizeof holder<functor>);
        ::new(this->data.address()) holder<functor>(e);
    }
    
    ~on_scope_exit_base() {
        static_cast<holder_base*>(this->data.address())->~holder_base();
    }

    boost::aligned_storage<size> data;
};

} // detail

typedef detail::on_scope_exit_base<32> on_scope_exit;



void print(int v)
{
    std::cout << v << std::endl;
}

void test(bool e)
{
    try
    {
        on_scope_exit print10 = boost::bind(&print, 10);
        
        if(e)
            throw 1;

        std::cout << 2 << std::endl;
    }
    catch(...)
    {
        std::cout << "e" << std::endl;
    }
}


int main()
{
    test(true);
    std::cout << "--" << std::endl;
    test(false);
}

/*
    10
    e
    --
    2
    10
*/
Re[3]: Шаблон для идиомы RAII
От: jazzer Россия Skype: enerjazzer
Дата: 30.12.09 04:41
Оценка: +1
Здравствуйте, Basil2, Вы писали:

B>Здравствуйте, jazzer, Вы писали:


B>>>А вопрос такой. Наверняка эт не я один умный , и такие шаблоны уже существует. Линканите плз какой-нибудь более-менее известный и стандартный. (Без заточки под винду, как у меня, да и вообще хочется посмотреть на "тру" RAII-шаблон )


J>>Boost.ScopeExit

J>>http://www.boost.org/libs/scope_exit/doc/html/index.html

B>Дык я, собственно, как на ScopeExit посмотрел, так сразу и понял что надо делать свое


B>ScopeExit некрасив, использует макросы и генерит скрытый код.

К сожалению, без этого пока что не обойтись из-за ограничений языка, если мы хотим иметь возможность исполнять при выходе произвольный код.
В С++0х будет легче.

B>А мне нужно тупо вызвать CloseHandle() по окончанию блока, и все. Я и сделал, фактически, тот же ScopeExit, но для _одной_ функции и потому куда как более простой.


Пока тебе достаточно просто звать функцию без параметров — да, Boost.ScopeExit будет оверкиллом.
Но как только тебе понадобится нечто посложнее (например, та же функция, но срабатывающая в зависимости от флага — стандартная ситуация) — ты проклянешь все, пытаясь собрать функтор при помощи Boost.Bind/Boost.Lambda. Не говоря уже о читабельности того, что у тебя получится, в сравнении с Boost.ScopeExit.

B>Мне казалось, что кто-нибудь это уже проделал...


shared_ptr, я же дал ссылку на их страничку, посвященную именно этому.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Шаблон для идиомы RAII
От: Alexander G Украина  
Дата: 30.12.09 07:48
Оценка: 37 (2)
Здравствуйте, denisko, Вы писали:

К>>Лучше написать и отполировать свой велосипед.

К>>Тем более, что не так уж там много нужно для полировки.
D>Несколько возражений.
D>1) Семантически любой Хендл является указателем с флагами.Так что совесть зверский каст оправдает.

Возвращаемый AcquireCredentialsHandle даже по размеру больше указателя.

нет, если shared_ptr использовать, то стоит биндить хендл в удалитель.
void FreeHandle(int h);

int main()
{
  int handle = 3;
  boost::shared_ptr<void const> p("", boost::bind(FreeHandle, handle));
}



D>2) Можно принимать указатель на хендл, который валяется рядом стеке. Вероятность того, что он запорется, а содержимое shared/scoped ptr останется в целости и сохранности стремительно стремится.


ничего не понял.

D>3) Автор, судя по стилю, не сильно склонен заморачиваться с спецификацией исключений и explicitamи. А это вторые и третьи грабли после тех, которые укзазал rg45. Если они начнут срабатывать когда кодом будет пользоваться не только он один, его будут бить. Возможно, даже ногами.


explicit конечно нужен. а спецификация исключений — нет.
Русский военный корабль идёт ко дну!
Re[5]: Шаблон для идиомы RAII
От: Basil2 Россия https://starostin.msk.ru
Дата: 30.12.09 14:32
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>explicit конечно нужен. а спецификация исключений — нет.


Зачем там нужен explicit?
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re[4]: Шаблон для идиомы RAII
От: Basil2 Россия https://starostin.msk.ru
Дата: 30.12.09 14:39
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Пока тебе достаточно просто звать функцию без параметров — да, Boost.ScopeExit будет оверкиллом.

J>Но как только тебе понадобится нечто посложнее (например, та же функция, но срабатывающая в зависимости от флага — стандартная ситуация) — ты проклянешь все, пытаясь собрать функтор при помощи Boost.Bind/Boost.Lambda. Не говоря уже о читабельности того, что у тебя получится, в сравнении с Boost.ScopeExit.

Для "посложнее" я просто напишу новый конструктор, который будет принимать ф-цию с двумя параметрами

B>>Мне казалось, что кто-нибудь это уже проделал...

J>shared_ptr, я же дал ссылку на их страничку, посвященную именно этому.

Реально в тему дал ссылку пользователь Bell, а ссылка такая:
http://www.ddj.com/cpp/184403758

Там действительно именно то, что я хотел.
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re: Шаблон для идиомы RAII
От: artiz  
Дата: 04.01.10 13:43
Оценка: 2 (1)
Здравствуйте, Basil2, Вы писали:

B>Чисто чтобы не забывать закрывать виндовые хендлы, набросал примитивный шаблон:


B>А вопрос такой. Наверняка эт не я один умный , и такие шаблоны уже существует. Линканите плз какой-нибудь более-менее известный и стандартный. (Без заточки под винду, как у меня, да и вообще хочется посмотреть на "тру" RAII-шаблон )


Вот еще мои велосипедики — util.guards.hpp

Я там еще reset()/release() прикручивал, как у auto_ptr — может пригодится.
Re[8]: Шаблон для идиомы RAII
От: denisko http://sdeniskos.blogspot.com/
Дата: 06.01.10 15:50
Оценка:
Здравствуйте, Тот кто сидит в пруду, Вы писали:

ТКС>Код, иллюстрирующий указанную ситуацию, можете предложить? А я потом объясню, как там обойтись без shared_ptr А то софистикой заниматься лениво.

Пожалте.
void someFunction()
{
ResourceGuard someResource;
anotherManFunction(someResource);//вот тут товарищь кешировал у себя значение, хранимое
                                // в someResource и через некоторое время начинал себя странно вести. 
                                // Предложи код, который бы мог отследить незаконный захват ресурса товарищем, 
                                 //если товарищ имеет использовать и клонировать только обертку но не сам ресурс.


}
<Подпись удалена модератором>
Re[9]: Шаблон для идиомы RAII
От: Тот кто сидит в пруду Россия  
Дата: 06.01.10 19:43
Оценка:
Здравствуйте, denisko, Вы писали:

D>Здравствуйте, Тот кто сидит в пруду, Вы писали:


ТКС>>Код, иллюстрирующий указанную ситуацию, можете предложить? А я потом объясню, как там обойтись без shared_ptr А то софистикой заниматься лениво.

D>Пожалте.
D>
D>void someFunction()
D>{
D>ResourceGuard someResource;
D>anotherManFunction(someResource);//вот тут товарищь кешировал у себя значение, хранимое
D>                                // в someResource и через некоторое время начинал себя странно вести. 
D>                                // Предложи код, который бы мог отследить незаконный захват ресурса товарищем, 
D>                                 //если товарищ имеет использовать и клонировать только обертку но не сам ресурс.


D>}

D>


Если товарищ запасает голый хэндл, то shared_ptr с закрывателем хэндла ему все равно не поможет (т.к. защищаемый хэндл все равно закроется при разрушении someResource). Если же он пытается сохранить ResourceGuard, то ситуация просто не попадает под определение "когда вызов метода какого-нибудь объекта в скопе приведет к тому, что защищаемый хендл сохранится внутрях этого объекта". Так что извольте другой пример.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re: Шаблон для идиомы RAII
От: andrey_nado  
Дата: 08.01.10 10:38
Оценка: +2
Здравствуйте, Basil2, Вы писали:

B>Используется, понятное дело, так:

B>
B>CallOnScopeLeave<HANDLE>(&CloseHandle, hFile);
B>


Могу ошибаться, но по-моему правильно использовать так:

B>
B>CallOnScopeLeave<HANDLE> anyName(&CloseHandle, hFile);
B>


В Вашем же случае анонимный объект удаляется в месте объявления.
Re[6]: Шаблон для идиомы RAII
От: Alexander G Украина  
Дата: 08.01.10 10:43
Оценка:
Здравствуйте, Basil2, Вы писали:

B>Зачем там нужен explicit?


Чтобы избежать неявного конструирования из хендла, владение которым не должно передаваться.
Русский военный корабль идёт ко дну!
Re[7]: Шаблон для идиомы RAII
От: Basil2 Россия https://starostin.msk.ru
Дата: 11.01.10 11:08
Оценка: 1 (1)
Здравствуйте, Alexander G, Вы писали:

B>>Зачем там нужен explicit?


AG>Чтобы избежать неявного конструирования из хендла, владение которым не должно передаваться.


Как вы представляете неявное конструирование от конструктора с _двумя_ аргументами??
Или я что-то недопонимаю в С++?..
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.