Re: RAII для дескрипторов типа int.
От: okman Беларусь https://searchinform.ru/
Дата: 02.04.14 14:10
Оценка: +4
Здравствуйте, antonio_banderas, Вы писали:

_>1. Есть ли готовые решения, чтоб держать дескриптор типа, например, int? (RAII)

_>2. Какими решениями пользуетесь вы, когда вам нужно держать дескриптор типа-не-указателя, чтоб не потерять его закрытие?

BOOST_SCOPE_EXIT либо аналоги.
http://www.boost.org/doc/libs/1_50_0_beta1/libs/scope_exit/doc/html/BOOST_SCOPE_EXIT.html
Re: RAII для дескрипторов типа int.
От: Abyx Россия  
Дата: 02.04.14 14:15
Оценка: 7 (2) +1
Здравствуйте, antonio_banderas, Вы писали:

_>Для типов-не-указателей std::unique_ptr не подходит.

подходит. у deletera'а надо определить pointer

struct my_deleter {
    typedef pointer int;
    void operator()(pointer x) { my_close(x); }
};

std::unique_ptr<int, my_deleter> p;
In Zen We Trust
Re[2]: RAII для дескрипторов типа int.
От: Кодт Россия  
Дата: 02.04.14 15:52
Оценка: +1
Здравствуйте, Abyx, Вы писали:

_>>Для типов-не-указателей std::unique_ptr не подходит.

A>подходит. у deletera'а надо определить pointer

Проблема в том, что выделенным нуль-значением он считает 0.
Что, в случае с дескрипторами, не обязательно справедливо. Там выделенным значением бывает -1, а 0 — рядовым.

Чтобы обойти это, придётся использовать обёртку. Заодно и багофичу gcc обойти получится
struct num
{
    int v;
    num(int v = -1) : v(v) {}
    bool operator == (num const& other) const { return v == other.v; }
    bool operator != (num const& other) const { return v != other.v; }

    bool operator == (std::nullptr_t) const { return *this == num(); }
    bool operator != (std::nullptr_t) const { return *this != num(); }
};

num install(int v) { std::cout << "install " << v << std::endl; return v; }
void utilize(num x) { std::cout << "utilize " << x.v << std::endl; }

struct num_deleter
{
    typedef num pointer;
    void operator()(pointer x) const { utilize(x); }
};

int main()
{
    std::cout << "{" << std::endl;
    {
        std::unique_ptr<num, num_deleter> p(install(123)), q(install(0)), r;
        std::cout << p.get().v << " " << q.get().v << " " << r.get().v << std::endl;
    }
    std::cout << "}" << std::endl;
}
Перекуём баги на фичи!
Re[4]: RAII для дескрипторов типа int.
От: Кодт Россия  
Дата: 07.04.14 08:05
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>Тогда уж проще сделать нормальную RAII-обёртку.

Разумеется!

E>Плохо, что её так и не появилось в std, ну да это же обычная история не?


Это заговор!
Не захотели вдобавок к указателям на объект и указателям на массив сделать семейство дескрипторов.
Был бы unique_ptr/unique_array/unique_handle и shared_ptr/shared_array/shared_handle
Всего-то и нужно, — трейтс "что такое нуль и что с этим делать".
Перекуём баги на фичи!
RAII для дескрипторов типа int.
От: antonio_banderas Россия  
Дата: 02.04.14 13:54
Оценка:
Есть дескриптор, есть функции создания-закрытия дескриптора, и функции для работы с дескриптором.
Цель — объект-обертка, который держит дескриптор и при выходе из области видимости его закрывает.
Если дескриптор имеет тип "указатель на что-нибудь", то с этим прекрасно справляется std::unique_ptr, например:
std::unique_ptr<FILE, int(*)(FILE*)> myfile(fopen("xxx.txt", "rb"), fclose); — и дальше работаем с файлом, не боясь потерять его закрытие.

Для типов-не-указателей std::unique_ptr не подходит.
Например, дескрипторы файлов в linux имеют тип int: int f = open("xxx.txt", O_RDONLY, 0); close(f);
Писать обертки-велосипеды я умею, в том числе шаблонные, если готовых решений нет, то придется так и делать.
Вопросы:
1. Есть ли готовые решения, чтоб держать дескриптор типа, например, int? (RAII)
2. Какими решениями пользуетесь вы, когда вам нужно держать дескриптор типа-не-указателя, чтоб не потерять его закрытие?
Re[2]: RAII для дескрипторов типа int.
От: antonio_banderas Россия  
Дата: 02.04.14 14:57
Оценка:
Здравствуйте, Abyx, Вы писали:

_>>Для типов-не-указателей std::unique_ptr не подходит.

A>подходит. у deletera'а надо определить pointer

A>
A>struct my_deleter {
A>    typedef pointer int;
A>    void operator()(pointer x) { my_close(x); }
A>};

A>std::unique_ptr<int, my_deleter> p;
A>


Идея хорошая, но пока не работает:

struct IntFileCloserDeleter
{
    typedef int pointer;
    void operator()(pointer x) { if (x != -1) ::close(x); }
};

int file1 = ::open(filenameOutput, O_WRONLY|O_CREAT|O_TRUNC, 0);
std::unique_ptr<int, IntFileCloserDeleter> filecloser { file1 };



/usr/include/c++/4.8/bits/unique_ptr.h: In instantiation of 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = int; _Dp = IntFileCloserDeleter]':
/home/antonio/workspace/...............cpp:55:78: required from here
/usr/include/c++/4.8/bits/unique_ptr.h:183:12: error: invalid operands of types 'int' and 'std::nullptr_t' to binary 'operator!='
if (__ptr != nullptr)


Вот это место в файле unique_ptr.h:
      // Destructor.
      ~unique_ptr() noexcept
      {
    auto& __ptr = std::get<0>(_M_t);
    if (__ptr != nullptr)
      get_deleter()(__ptr);
    __ptr = pointer();
      }


g++ 4.8.1 with flag -std=c++11
Re[3]: RAII для дескрипторов типа int.
От: Abyx Россия  
Дата: 02.04.14 15:02
Оценка:
Здравствуйте, antonio_banderas, Вы писали:

_>Идея хорошая, но пока не работает:


_> if (__ptr != nullptr)


_>g++ 4.8.1 with flag -std=c++11


это баг gcc.
In Zen We Trust
Re[4]: RAII для дескрипторов типа int.
От: antonio_banderas Россия  
Дата: 02.04.14 15:12
Оценка:
Здравствуйте, Abyx, Вы писали:

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


_>>Идея хорошая, но пока не работает:


_>> if (__ptr != nullptr)


_>>g++ 4.8.1 with flag -std=c++11


A>это баг gcc.


Читать стандарт, чтоб выяснить, у кого баг, в гцц или в коде, некогда, да и, на самом деле, какая разница, если оно всё равно от этого работать не станет.
Поскольку gcc ближе всех следует стандарту (насколько я знаю), решение можно признать не рабочим — будь то только де-факто, или де-юро тоже.
Еще коллега мнение высказал, что объявлять int поинтером — это грязный хак (насчет грязного не согласен). Возможно, gcc аналогичного мнения, и потому фейлит это.
Re[2]: RAII для дескрипторов типа int.
От: fin_81  
Дата: 02.04.14 15:33
Оценка:
Здравствуйте, Abyx, Вы писали:

A>подходит. у deletera'а надо определить pointer


A>
A>struct my_deleter {
A>    typedef pointer int;
A>    void operator()(pointer x) { my_close(x); }
A>};

A>std::unique_ptr<int, my_deleter> p;
A>


Думаю так нельзя, потому что неизвестно как надо реализовать operator bool для unique_ptr для не указателя.
Re: RAII для дескрипторов типа int.
От: antonio_banderas Россия  
Дата: 02.04.14 15:34
Оценка:
Здравствуйте, antonio_banderas, Вы писали:

_>Вопросы:

_>1. Есть ли готовые решения, чтоб держать дескриптор типа, например, int? (RAII)
_>2. Какими решениями пользуетесь вы, когда вам нужно держать дескриптор типа-не-указателя, чтоб не потерять его закрытие?

В общем пока обошелся написанным за несколько минут велосипедом:


template <class Descriptor, class FuncType, FuncType Function>
class DescriptorCloser
{
public:
    inline explicit DescriptorCloser(Descriptor file, Descriptor null = -1) : d_(file), null_(null) {}
    inline ~DescriptorCloser() { if (d_ != null_) Function(d_); }
    inline Descriptor get() const { return d_; }
    inline Descriptor release() { Descriptor d = d_; d_ = null_; return d; }
private:
    Descriptor d_;
    Descriptor null_;
};

typedef DescriptorCloser<int, int(*)(int), ::close> FileCloser;


Использование простое:

int myfile = ::open(...);
FileCloser filecloser(myfile);
Re[2]: RAII для дескрипторов типа int.
От: antonio_banderas Россия  
Дата: 02.04.14 15:37
Оценка:
Здравствуйте, okman, Вы писали:

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


_>>1. Есть ли готовые решения, чтоб держать дескриптор типа, например, int? (RAII)

_>>2. Какими решениями пользуетесь вы, когда вам нужно держать дескриптор типа-не-указателя, чтоб не потерять его закрытие?

O>BOOST_SCOPE_EXIT либо аналоги.

O>http://www.boost.org/doc/libs/1_50_0_beta1/libs/scope_exit/doc/html/BOOST_SCOPE_EXIT.html

Слишком сложно.
Я за пару минут так и не понял, как его надо использовать. В документации подходящих примеров не нашел.
Наверно, в некоторых кругах считается, что чем более сложными конструкциями пользуется человек, тем он круче, но я предпочитаю обратный подход: чем проще — тем лучше.
Самодельный велосипед (см. сообщение ниже) занял несколько минут.
Re[2]: RAII для дескрипторов типа int.
От: antonio_banderas Россия  
Дата: 02.04.14 19:36
Оценка:
Здравствуйте, antonio_banderas, Вы писали:

_>В общем пока обошелся написанным за несколько минут велосипедом:


Лучше так:

template <class Descriptor, Descriptor NullValue, class FuncType, FuncType Function>
class DescriptorCloser : private boost::noncopyable
{
public:
    inline explicit DescriptorCloser(Descriptor file) : d_(file) {}
    inline ~DescriptorCloser() { if (d_ != NullValue) Function(d_); }
    inline Descriptor get() const { return d_; }
    inline Descriptor release() { Descriptor d = d_; d_ = NullValue; return d; }
private:
    Descriptor d_;
};

typedef DescriptorCloser<int, -1, int(*)(int), ::close> FileCloser;



Использование прежнее.

_>
_>int myfile = ::open(...);
_>FileCloser filecloser(myfile);
_>
Re: RAII для дескрипторов типа int.
От: c-smile Канада http://terrainformatica.com
Дата: 03.04.14 05:37
Оценка:
Здравствуйте, antonio_banderas, Вы писали:

_>2. Какими решениями пользуетесь вы, когда вам нужно держать дескриптор типа-не-указателя, чтоб не потерять его закрытие?


Ну дык SCOPE_EXIT же...

{
  FILE * fp = fopen("test.out", "wb"); SCOPE_EXIT(fclose(fp));
...
  fread();
}


отсюда http://the-witness.net/news/2012/11/scopeexit-in-c11/
Re: RAII для дескрипторов типа int.
От: uzhas Ниоткуда  
Дата: 03.04.14 07:59
Оценка:
Здравствуйте, antonio_banderas, Вы писали:

_>1. Есть ли готовые решения, чтоб держать дескриптор типа, например, int? (RAII)

BOOST_SCOPE_EXIT, лично я его не использую

_>2. Какими решениями пользуетесь вы, когда вам нужно держать дескриптор типа-не-указателя, чтоб не потерять его закрытие?

a) пишу класс, который в деструкторе освобождает ресурсы.
b) еще можно int скопировать в динамическую память
std::shared_ptr<int> Wrap(int handle)
{
  return std::shared_ptr<int>(new int(handle), [](int* handle)
  {
    if (!handle)
      return;

    CloseMyHandle(*handle);
    delete handle;
  });
}

//usage
int myHandle = OpenMyHandle();//get handle;
std::shared_ptr<int> safeHandle = Wrap(myHandle);
//use safeHandle
UseHandle(*safeHandle);
Re[3]: RAII для дескрипторов типа int.
От: rg45 СССР  
Дата: 03.04.14 09:11
Оценка:
Здравствуйте, antonio_banderas, Вы писали:

O>>BOOST_SCOPE_EXIT либо аналоги.

O>>http://www.boost.org/doc/libs/1_50_0_beta1/libs/scope_exit/doc/html/BOOST_SCOPE_EXIT.html

_>Слишком сложно.

_>Я за пару минут так и не понял, как его надо использовать. В документации подходящих примеров не нашел.

Ничего сложного:

   const int f = open("xxx.txt", O_RDONLY, 0);
   BOOST_SCOPE_EXIT((f)) {
      close(f);
   } BOOST_SCOPE_EXIT_END
   // . . .

Выгода в том, что не нужно определять для каждого случая новый класс.
--
Справедливость выше закона. А человечность выше справедливости.
Re[5]: RAII для дескрипторов типа int.
От: Abyx Россия  
Дата: 03.04.14 09:23
Оценка:
Здравствуйте, antonio_banderas, Вы писали:

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


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


_>>>Идея хорошая, но пока не работает:


_>>> if (__ptr != nullptr)


_>>>g++ 4.8.1 with flag -std=c++11


A>>это баг gcc.


_>Читать стандарт, чтоб выяснить, у кого баг, в гцц или в коде, некогда, да и, на самом деле, какая разница, если оно всё равно от этого работать не станет.

_>Поскольку gcc ближе всех следует стандарту (насколько я знаю), решение можно признать не рабочим — будь то только де-факто, или де-юро тоже.
_>Еще коллега мнение высказал, что объявлять int поинтером — это грязный хак (насчет грязного не согласен). Возможно, gcc аналогичного мнения, и потому фейлит это.

да, всетаки это не баг. указатель должен удовлетворять требованиям NullPointer а туда входит сравнение с nullptr
In Zen We Trust
Re: RAII для дескрипторов типа int.
От: B0FEE664  
Дата: 03.04.14 10:38
Оценка:
Здравствуйте, antonio_banderas, Вы писали:

_>Для типов-не-указателей std::unique_ptr не подходит.

_>Например, дескрипторы файлов в linux имеют тип int: int f = open("xxx.txt", O_RDONLY, 0); close(f);

Обычно я пишу отдельный класс под каждый случай, но иногда думаю вот в этом направлении:
      int handle = open("xxx.txt", O_RDONLY, 0);
      auto FunOnExit = [](int* pHandle){ return close(*pHandle); };
      std::unique_ptr<int, decltype(FunOnExit)> myfile(&handle, FunOnExit);


Иногда пишу так:
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>

...

      int handle = open("xxx.txt", O_RDONLY, 0);
      boost::shared_ptr<void> guard(static_cast<void*>(0), boost::bind(close, handle));
И каждый день — без права на ошибку...
Re[3]: RAII для дескрипторов типа int.
От: Erop Россия  
Дата: 07.04.14 06:39
Оценка:
Здравствуйте, fin_81, Вы писали:

_>Думаю так нельзя, потому что неизвестно как надо реализовать operator bool для unique_ptr для не указателя.


Почему, для FILE* известно, а для int неизвестно?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: RAII для дескрипторов типа int.
От: Erop Россия  
Дата: 07.04.14 06:41
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Чтобы обойти это, придётся использовать обёртку. Заодно и багофичу gcc обойти получится

К>
К>struct num
К>{
К>    int v;
К>    num(int v = -1) : v(v) {}
К>    bool operator == (num const& other) const { return v == other.v; }
К>    bool operator != (num const& other) const { return v != other.v; }

К>    bool operator == (std::nullptr_t) const { return *this == num(); }
К>    bool operator != (std::nullptr_t) const { return *this != num(); }
К>};

К>num install(int v) { std::cout << "install " << v << std::endl; return v; }
К>void utilize(num x) { std::cout << "utilize " << x.v << std::endl; }

К>struct num_deleter
К>{
К>    typedef num pointer;
К>    void operator()(pointer x) const { utilize(x); }
К>};

К>int main()
К>{
К>    std::cout << "{" << std::endl;
К>    {
К>        std::unique_ptr<num, num_deleter> p(install(123)), q(install(0)), r;
К>        std::cout << p.get().v << " " << q.get().v << " " << r.get().v << std::endl;
К>    }
К>    std::cout << "}" << std::endl;
К>}
К>



Тогда уж проще сделать нормальную RAII-обёртку.
Плохо, что её так и не появилось в std, ну да это же обычная история не?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: RAII для дескрипторов типа int.
От: antonio_banderas Россия  
Дата: 07.04.14 10:39
Оценка:
Здравствуйте, Erop, Вы писали:

_>>Думаю так нельзя, потому что неизвестно как надо реализовать operator bool для unique_ptr для не указателя.


E>Почему, для FILE* известно, а для int неизвестно?


Ну вот КО мне подсказывает, потому, что FILE* это указатель.
С указателями unique_ptr прекрасно работает.
Re[4]: RAII для дескрипторов типа int.
От: fin_81  
Дата: 07.04.14 11:14
Оценка:
Здравствуйте, Erop, Вы писали:

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


_>>Думаю так нельзя, потому что неизвестно как надо реализовать operator bool для unique_ptr для не указателя.


E>Почему, для FILE* известно, а для int неизвестно?


Потому что "умные владельцы" почему-то спроектированы так, что логика владения сильно связана с самим объектом. Если у объекта нет специально значения для "несуществующего объекта" (NULL, nullptr и тп), то получается что владеть этим объектом невозможно. Похоже на то, что застряли между C и C++
Re[5]: RAII для дескрипторов типа int.
От: Erop Россия  
Дата: 07.04.14 12:55
Оценка:
Здравствуйте, antonio_banderas, Вы писали:

_>Ну вот КО мне подсказывает, потому, что FILE* это указатель.

_>С указателями unique_ptr прекрасно работает.

Ну вот мне КО подсказывает, что это потому, что в комитете опять протупили, а не потому, что "не известно"
Единственная беда с числами, в качестве хендлов -- неизвестно какое значение является валидным пустым. Ну так могли сделать параметром шаблона или трита...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.