как бы передать в шаблон NULL или INVALID_HANDLE_VALUE
От: gid_vvp  
Дата: 28.08.06 15:00
Оценка:
Hi All

есть такой класс

template<
            typename TyHandle, 
            TyHandle (*TyInvalidValue)(), 
            void (*TyHandleClose)(TyHandle)
        >
class HandlePolicy
{
public:
    typedef TyHandle HandleType;
        
    static HandleType InvalidValue()
    {
        return TyInvalidValue();
    }

    static void HandleClose(HandleType handle)
    {
        if (IsValid(handle))
        {
            TyHandleClose(handle);
        }
    }

    static bool IsValid(HandleType handle)
    {
        return (handle != InvalidValue());
    }
};


сейчас используется так:

namespace fp
{
    HANDLE InvalidValue()
    {
        return INVALID_HANDLE_VALUE;
    }

    void HandleClose(HANDLE handle)
    {
        ::CloseHandle(handle);
    }
}

namespace sp
{
    HANDLE InvalidValue()
    {
        return INVALID_HANDLE_VALUE;
    }

    void HandleClose(HANDLE handle)
    {
        ::FindClose(handle);
    }
}

namespace ep
{
    HANDLE InvalidValue()
    {
        return NULL;
    }

    void HandleClose(HANDLE handle)
    {
        ::CloseHandle(handle);
    }
}

namespace mp
{
    HMODULE InvalidValue()
    {
        return NULL;
    }

    void HandleClose(HMODULE handle)
    {
        ::FreeLibrary(handle);
    }
}

...

typedef HandlePolicy<HANDLE, &fp::InvalidValue, &fp::HandleClose> FileHandlePolicy;
typedef HandlePolicy<HANDLE, &sp::InvalidValue, &sp::HandleClose> SearchHandlePolicy;
typedef HandlePolicy<HANDLE, &ep::InvalidValue, &ep::HandleClose> EventHandlePolicy;
typedef HandlePolicy<HMODULE, &mp::InvalidValue, &mp::HandleClose> ModuleHandlePolicy;

...



как бы так извернуться, чтоб можно было делать так, вместо того что выше:

typedef HandlePolicy<HANDLE, INVALID_HANDLE_VALUE, &::CloseHandle> FileHandlePolicy;
typedef HandlePolicy<HANDLE, INVALID_HANDLE_VALUE, &::FindClose> SearchHandlePolicy;
typedef HandlePolicy<HANDLE, NULL, &::CloseHandle> EventHandlePolicy;
typedef HandlePolicy<HMODULE,NULL, &::FreeLibrary> ModuleHandlePolicy;

...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: как бы передать в шаблон NULL или INVALID_HANDLE_VALUE
От: Константин Л. Франция  
Дата: 28.08.06 15:49
Оценка: 2 (1)
Здравствуйте, gid_vvp, Вы писали:

_>Hi All


_>есть такой класс


_>
_>template<
_>            typename TyHandle, 
_>            long InvalidValue, 
_>            void (*TyHandleClose)(TyHandle)
        >>
_>class HandlePolicy
_>{
_>public:
_>    typedef TyHandle HandleType;
        
_>    static HandleType InvalidValue()
_>    {
_>        return (HandleType)InvalidValue;
_>    }

_>    static void HandleClose(HandleType handle)
_>    {
_>        if (IsValid(handle))
_>        {
_>            TyHandleClose(handle);
_>        }
_>    }

_>    static bool IsValid(HandleType handle)
_>    {
_>        return (handle != InvalidValue());
_>    }
_>};

_>
Re: как бы передать в шаблон NULL или INVALID_HANDLE_VALUE
От: Left2 Украина  
Дата: 28.08.06 16:18
Оценка:
ИМХО, ты задумал неудачную идею. Я бы юзал классы-traits вместо функций обёрнутых в namespace. Писанины немногим меньше, а гибкость выше — можешь наследовать их друг от друга, можешь добавить какие-то методы без изменения основного интерфейса.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: gid_vvp  
Дата: 28.08.06 16:20
Оценка:
_>>
_>>            long InvalidValue, 
_>>


а почему long ?
а другие варианты?

а как быть со функцией закрытия хандла (чтоб можно было передать оригинальную непосредстаенно в шаблон)?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: gid_vvp  
Дата: 28.08.06 16:24
Оценка:
INVALID_HANDLE_VALUE не прокатывает
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: gid_vvp  
Дата: 28.08.06 16:27
Оценка:
L>ИМХО, ты задумал неудачную идею. Я бы юзал классы-traits вместо функций обёрнутых в namespace. Писанины немногим меньше, а гибкость выше — можешь наследовать их друг от друга, можешь добавить какие-то методы без изменения основного интерфейса.

были traits...
но получалось что для новых хандлов они получались одинаковыми смотри что было:
class FileHandlePolicy
{
public:
    typedef HANDLE HandleType;

    static HandleType InvalidValue()
    {
        return INVALID_HANDLE_VALUE;
    }

    static void HandleClose(HandleType handle)
    {
        if (IsValid(handle))
        {
            ::CloseHandle(handle);
        }
    }

    static bool IsValid(HandleType handle)
    {
        return (handle != InvalidValue());
    }
};

class SearchHandlePolicy
{
public:
    typedef HANDLE HandleType;

    static HandleType InvalidValue()
    {
        return INVALID_HANDLE_VALUE;
    }

    static void HandleClose(HandleType handle)
    {
        if (IsValid(handle))
        {
            ::FindClose(handle);
        }
    }

    static bool IsValid(HandleType handle)
    {
        return (handle != InvalidValue());
    }
};

class EventHandlePolicy
{
public:
    typedef HANDLE HandleType;

    static HandleType InvalidValue()
    {
        return NULL;
    }

    static void HandleClose(HandleType handle)
    {
        if (IsValid(handle))
        {
            ::CloseHandle(handle);
        }
    }

    static bool IsValid(HandleType handle)
    {
        return (handle != InvalidValue());
    }
} ;

class ModuleHandlePolicy
{
public:

    typedef HMODULE HandleType;

    static HandleType InvalidValue()
    {
        return NULL;
    }

    static void HandleClose(HandleType handle)
    {
        if (IsValid(handle))
        {
            ::FreeLibrary(handle);
        }
    }

    static bool IsValid(HandleType handle)
    {
        return (handle != InvalidValue());
    }
};



а теперь сравни с тем что хочется:

typedef HandlePolicy<HANDLE, INVALID_HANDLE_VALUE, &::CloseHandle> FileHandlePolicy;
typedef HandlePolicy<HANDLE, INVALID_HANDLE_VALUE, &::FindClose> SearchHandlePolicy;
typedef HandlePolicy<HANDLE, NULL, &::CloseHandle> EventHandlePolicy;
typedef HandlePolicy<HMODULE,NULL, &::FreeLibrary> ModuleHandlePolicy;
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: gid_vvp  
Дата: 28.08.06 16:36
Оценка:
_>INVALID_HANDLE_VALUE не прокатывает
только вот так:

typedef HandlePolicy<HANDLE,    (LONGLONG)INVALID_HANDLE_VALUE,    &fp::HandleClose> FileHandlePolicy;


что то не очень мне нравиться...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: Константин Л. Франция  
Дата: 28.08.06 17:00
Оценка:
Здравствуйте, gid_vvp, Вы писали:

_>>>
_>>>            long InvalidValue, 
_>>>


_>а почему long ?


писал по-памяти. Думал INVALID_HANDLE_VALUE это лонг

_>а другие варианты?


_>а как быть со функцией закрытия хандла (чтоб можно было передать оригинальную непосредстаенно в шаблон)?


_>>[ccode]

_>>template<
_>> typename TyHandle,
_>> TyHandle InvalidValue, //так может прокатить. Можно попробовать заменить на void*
typename TyHandleCloseReturnType,
_>> TyHandleCloseReturnType ( /*__stdcall ???*/ *TyHandleClose)(TyHandle)
>>>
_>>class HandlePolicy
_>>{
_>>public:
_>> typedef TyHandle HandleType;

_>> static HandleType InvalidValue()

_>> {
_>> return InvalidValue;
_>> }

_>> static TyHandleCloseReturnType HandleClose(HandleType handle)

_>> {
_>> if (IsValid(handle))
_>> {
_>> return TyHandleClose(handle);
_>> }
_>> return TyHandleCloseReturnType();//временно, см комментарий
_>> }

_>> static bool IsValid(HandleType handle)

_>> {
_>> return (handle != InvalidValue());
_>> }
_>>};

Для HandleClose, похоже, придется писать спецификацию для типов void и BOOL(int).
Re[4]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: Константин Л. Франция  
Дата: 28.08.06 17:06
Оценка: 3 (1)
Здравствуйте, Константин Л., Вы писали:

сорри:

[ccode]
template<
typename TyHandle,
TyHandle InvalidValue, //так может прокатить. Можно попробовать заменить на void*
typename TyHandleCloseReturnType,
TyHandleCloseReturnType ( /*__stdcall ???*/ *TyHandleClose)(TyHandle)
>
class HandlePolicy
{
public:
typedef TyHandle HandleType;

static HandleType InvalidValue()
{
return InvalidValue;
}

static TyHandleCloseReturnType HandleClose(HandleType handle)
{
if (IsValid(handle))
{
return TyHandleClose(handle);
}
return TyHandleCloseReturnType();//временно, см комментарий
}

static bool IsValid(HandleType handle)
{
return (handle != InvalidValue());
}
};
Re[5]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: Константин Л. Франция  
Дата: 28.08.06 17:08
Оценка:
Здравствуйте, Константин Л., Вы писали:

сорри повторно

template<
     typename TyHandle, 
     TyHandle InvalidValue, //так может прокатить. Можно попробовать заменить на void* 
     typename TyHandleCloseReturnType,
     TyHandleCloseReturnType ( /*__stdcall ???*/ *TyHandleClose)(TyHandle) 
>
class HandlePolicy
{
public:
     typedef TyHandle HandleType;

     static HandleType InvalidValue()
     {
          return InvalidValue;
     }

     static TyHandleCloseReturnType HandleClose(HandleType handle)
     {
          if (IsValid(handle))
          {
               return TyHandleClose(handle);
          } 
          return TyHandleCloseReturnType();//временно, см комментарий 
     }

     static bool IsValid(HandleType handle)
     {
          return (handle != InvalidValue());
     }
};
Re[5]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: gid_vvp  
Дата: 28.08.06 17:10
Оценка:
template<
     typename TyHandle, 
     TyHandle InvalidValue, //так может прокатить. Можно попробовать заменить на void*


это не прокатит, а вот void* похоже самое то
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: gid_vvp  
Дата: 28.08.06 17:24
Оценка:
с функцией закрытия хандлов я намутил
они оказывается одинаковый прототип имеют и такое вполне прокатит...
пока не найдётся какая-нибудь не укладывающаяся сюда

КЛ>
КЛ>template<
КЛ>     typename TyHandleCloseReturnType,
КЛ>     BOOL ( WINAPI *TyHandleClose)(TyHandle) 
>>
КЛ>
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: gid_vvp  
Дата: 28.08.06 17:28
Оценка:
окончательный вариант

template<
            typename TyHandle, 
            void* TyInvalidValue, 
            BOOL (WINAPI * TyHandleClose)(TyHandle)
        >
class HandlePolicy
{
public:
    typedef TyHandle HandleType;
        
    static HandleType InvalidValue()
    {
        return static_cast<HandleType>(TyInvalidValue);
    }

    static void HandleClose(HandleType handle)
    {
        if (IsValid(handle))
        {
            TyHandleClose(handle);
        }
    }

    static bool IsValid(HandleType handle)
    {
        return (handle != InvalidValue());
    }
};



typedef HandlePolicy<HANDLE,  INVALID_HANDLE_VALUE, &::CloseHandle> FileHandlePolicy;
typedef HandlePolicy<HANDLE,  INVALID_HANDLE_VALUE, &::FindClose>   SearchHandlePolicy;
typedef HandlePolicy<HANDLE,  NULL,                 &::CloseHandle> EventHandlePolicy;
typedef HandlePolicy<HMODULE, NULL,                 &::FreeLibrary> ModuleHandlePolicy;
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: как бы передать в шаблон NULL или INVALID_HANDLE_VALUE
От: IceStudent Украина  
Дата: 28.08.06 18:40
Оценка:
Здравствуйте, gid_vvp, Вы писали:

_>Hi All


_>есть такой класс


А как насчёт альтернативы? Правда, это только для HANDLE. Для SOCKET, например, пришлось писать другой тип из-за специфичности.

struct SystemCloseHandlePolicy
{
    static inline BOOL CloseHandle(HANDLE h)
    {
        return ::CloseHandle(h);
    }
};

template<bool duplicate_t,class CloseHandlePolicy = SystemCloseHandlePolicy>
class CHandleEx_t
{
public:
    ...
    void Close() throw()
    {
        if(IsValid())
            CloseHandlePolicy::CloseHandle(this->m_h);
        this->m_h = NULL;
    }
    ...
}
--
wbr, icestudent
Re[3]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: IceStudent Украина  
Дата: 29.08.06 05:52
Оценка:
Здравствуйте, gid_vvp, Вы писали:

_>были traits...

_>но получалось что для новых хандлов они получались одинаковыми смотри что было:
Было бы использовать свойство для получения неверного значения хэндла (лучше функция, т.к. неверными могут быть и NULL, и -1 одновременно), а стратегию — для закрытия хэндла. Тогда одно свойство можно использовать в комбинации с разными стратегиями.
--
wbr, icestudent
Re[4]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: gid_vvp  
Дата: 29.08.06 06:48
Оценка:
IS>Было бы использовать свойство для получения неверного значения хэндла (лучше функция, т.к. неверными могут быть и NULL, и -1 одновременно), а стратегию — для закрытия хэндла. Тогда одно свойство можно использовать в комбинации с разными стратегиями.

откуда дровишки?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: gid_vvp  
Дата: 29.08.06 06:48
Оценка:
IS>А как насчёт альтернативы? Правда, это только для HANDLE. Для SOCKET, например, пришлось писать другой тип из-за специфичности.

IS>
struct SystemCloseHandlePolicy
IS>{
IS>    static inline BOOL CloseHandle(HANDLE h)
IS>    {
IS>        return ::CloseHandle(h);
IS>    }
IS>};

IS>template<bool duplicate_t,class CloseHandlePolicy = SystemCloseHandlePolicy>
IS>class CHandleEx_t
IS>{
IS>public:
IS>    ...
IS>    void Close() throw()
IS>    {
IS>        if(IsValid())
IS>            CloseHandlePolicy::CloseHandle(this->m_h);
        this->>m_h = NULL;
IS>    }
IS>    ...
IS>}


не могу уловить фишку...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: Left2 Украина  
Дата: 29.08.06 07:52
Оценка:
А для того чтобы они не получались одинаковыми есть такая замечательная вещь как наследование. Причём поскольку функции тут только статик, то ты запросто можешь юзать даже множественное наследование (никаких оверхедов не будет).
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: IceStudent Украина  
Дата: 29.08.06 08:13
Оценка:
Здравствуйте, gid_vvp, Вы писали:

IS>>Было бы использовать свойство для получения неверного значения хэндла (лучше функция, т.к. неверными могут быть и NULL, и -1 одновременно), а стратегию — для закрытия хэндла. Тогда одно свойство можно использовать в комбинации с разными стратегиями.


_>откуда дровишки?

Из-за инициализации HANDLE через NULL, а не INVALID_HANDLE_VALUE (в том же ATL::CHandle или если принимаешь уже инициализированный так HANDLE).
--
wbr, icestudent
Re[3]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: IceStudent Украина  
Дата: 29.08.06 08:13
Оценка:
Здравствуйте, gid_vvp, Вы писали:

_>не могу уловить фишку...

Ну это то, о чём я говорил выше, что вместо значения использовать функцию, проверяющую хэндл на валидность. Но с другой стороны — можно взять за правило инициализацию через -1, тогда проблема отпадает.
--
wbr, icestudent
Re[6]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: gid_vvp  
Дата: 29.08.06 09:11
Оценка:
IS>Из-за инициализации HANDLE через NULL, а не INVALID_HANDLE_VALUE (в том же ATL::CHandle или если принимаешь уже инициализированный так HANDLE).

1. довольно странная идея использовать одну обёртку для хандлов вместе с другой
2. ATL::CHandle не стоит использовать с хандлами файлов ибо CreateFile в случае ошибки возвращает ни что иное как INVALID_HANDLE_VALUE и следовательно невалидный хандл файла это INVALID_HANDLE_VALUE и ни что больше
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: gid_vvp  
Дата: 29.08.06 10:11
Оценка:
L>А для того чтобы они не получались одинаковыми есть такая замечательная вещь как наследование. Причём поскольку функции тут только статик, то ты запросто можешь юзать даже множественное наследование (никаких оверхедов не будет).

Имеешь в виду нечто такое?
struct InvalidValuePolicy
{
   typedef HANDLE HandleType;

    static HandleType InvalidValue()
    {
        return NULL;
    }
};

struct CloseHandlePolicy
{
   typedef HANDLE HandleType;

    static void HandleClose(HandleType handle)
    {
        if (IsValid(handle))
        {
            ::FreeLibrary(handle);
        }
    }

};

class ModuleHandlePolicy
    : public InvalidValuePolicy
    , public CloseHandlePolicy
{
public:
     static bool IsValid(HandleType handle)
    {
        return (handle != InvalidValue());
    }
};


помоему ни чем не лучше такого


    HMODULE InvalidValue()
    {
        return NULL;
    }

...
    void HandleClose(HMODULE handle)
    {
        ::FreeLibrary(handle);
    }

...

typedef HandlePolicy<HMODULE, &InvalidValue, &HandleClose> ModuleHandlePolicy;


и намного хуже этого
typedef HandlePolicy<HMODULE, NULL, &::FreeLibrary> ModuleHandlePolicy;
...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: IceStudent Украина  
Дата: 29.08.06 10:24
Оценка:
Здравствуйте, gid_vvp, Вы писали:

_>1. довольно странная идея использовать одну обёртку для хандлов вместе с другой

Не вместе. Просто пример реализации.

_>2. ATL::CHandle не стоит использовать с хандлами файлов ибо CreateFile в случае ошибки возвращает ни что иное как INVALID_HANDLE_VALUE и следовательно невалидный хандл файла это INVALID_HANDLE_VALUE и ни что больше

ATL::CHandle — это просто обёртка для HANDLE, чтобы автоматически закрывать хэндл при выходе из области видимости или при исключении.
--
wbr, icestudent
Re[8]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: gid_vvp  
Дата: 29.08.06 10:47
Оценка:
_>>1. довольно странная идея использовать одну обёртку для хандлов вместе с другой
IS>Не вместе. Просто пример реализации.
Зачем этот пример?
Как неследует делать?

_>>2. ATL::CHandle не стоит использовать с хандлами файлов ибо CreateFile в случае ошибки возвращает ни что иное как INVALID_HANDLE_VALUE и следовательно невалидный хандл файла это INVALID_HANDLE_VALUE и ни что больше

IS>ATL::CHandle — это просто обёртка для HANDLE, чтобы автоматически закрывать хэндл при выходе из области видимости или при исключении.

ещё раз повторяю невалидный хандл файла это INVALID_HANDLE_VALUE и ни что больше
для други хандлов другие невалидные значения бывают.

смотри пример

ATL::CHandle h = CreateFile(....); // допустим что неудачно завершилась функция и h == INVALID_HANDLE_VALUE
и конечно в своём деструкторе он попытается закрыть хандл равный INVALID_HANDLE_VALUE

ни чего страшного не случится потому что внутри CloseHandle скорее всего есть проверка...
но неправильное использование налицо

или вот ещё замечательный пример иллюстрирующий убожество ATL::CHandle и мои слова о том что его лучше не использовать для хандлов файлов

ATL::CHandle h(CreateFile(....));// допустим что неудачно завершилась функция и h == INVALID_HANDLE_VALUE
if(h)
{
    // работаем с файлом... даже если он не открылся :))
}
else
{
    //обработка ошибок... только сюда мы никогда не попадём :)
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: Left2 Украина  
Дата: 29.08.06 11:34
Оценка:
Да, что-то типа такого. Ну кроме того что я бы наверное и typedef для HANDLE вынес в отдельного предка и от него бы всё наследовал.

А какими критериями ты определяешь что лучше а что нет? По количеству кода?
Я бы не стал экономить на количестве строк, благо такого кода у тебя всё равно не будет много — вариантов хэндлов с разными политиками пару десятков, не больше.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: как бы передать в шаблон NULL или INVALID_HANDLE_VALU
От: gid_vvp  
Дата: 29.08.06 11:38
Оценка:
L>Да, что-то типа такого. Ну кроме того что я бы наверное и typedef для HANDLE вынес в отдельного предка и от него бы всё наследовал.

L>А какими критериями ты определяешь что лучше а что нет? По количеству кода?

L>Я бы не стал экономить на количестве строк, благо такого кода у тебя всё равно не будет много — вариантов хэндлов с разными политиками пару десятков, не больше.

По варазительности и простоте
Но конечно это субъективно...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.