Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / элегантный scope deleter c++

элегантный scope deleter c++

Страницы: 1 2 Следующая »
fsmokeПостоялецwww1 июня 201813:25#0
Есть ли в бусте или в новом стд, какой нибудь механизм для создания скопед переменных которые на деструкторе  выполняли бы какой либо мой код..
Сейчас гуглил - опять не нашел.

Меня просто достало писать велосипеды аля:

struct shm_remove
{
        shm_remove(std::string const & channel_name_hashed) : 
          _channel_name_hashed(channel_name_hashed)
        {  }
        ~shm_remove() { bi::shared_memory_object::remove(_channel_name_hashed.c_str()); }
      private:
        std::string const & _channel_name_hashed;
} remover(channel_name_hashed);

или такие (это вообще кстати неправильно, т.к. указатель 1 может быть невалидным на каких либо платформах, а с nullptr - deleter не вызовется)

auto server_flock_unlock_proc = [&server_flock](void *) { server_flock.unlock(); };
std::unique_ptr<void, decltype(server_flock_unlock_proc)> server_flock_unlock(
    (void*)1, server_flock_unlock_proc);

или есть велосипедные темплейтные штуки - ща искать их влом

блин в очередной раз хочется узнать - можт всё же есть что нибудь подобное уже готовое?

Sbtrn. DevilПостоялецwww1 июня 201816:37#2
fsmoke
> Есть ли в бусте или в новом стд, какой нибудь механизм для создания скопед
> переменных которые на деструкторе выполняли бы какой либо мой код..
Есть #define.
fsmokeПостоялецwww1 июня 201818:26#3
return [](){};
> https://github.com/facebook/folly/blob/master/folly/ScopeGuard.h

дык это сторонняя

return [](){};

> https://www.boost.org/doc/libs/1_67_0/libs/scope_exit/doc/html/index.html

макросы - ну уж нет...

Sbtrn. Devil

опять макросы!!

Ды вы чё господа - как можно o_O, когда в языке есть лямбды, вариадики, структур биндинги и т.д. скатываться в сраные макросы.

ЗЫ
Короче я понял - всё ещё очень печально

DelfigamerПостоялецwww1 июня 201818:32#4
fsmoke
> дык это сторонняя
Копируешь - и больше не сторонняя. :3
KartonagnickЗабаненwww1 июня 201818:34#5
Delfigamer
> Копируешь - и больше не сторонняя. :3

+1

gammakerПостоялецwww1 июня 201823:44#6
fsmoke
В моей библиотеке есть Finally.
Юзается так:
auto remover = Intra::Finally([&](){
  bi::shared_memory_object::remove(_channel_name_hashed.c_str());
});
С макросами так:
INTRA_FINALLY(bi::shared_memory_object::remove(_channel_name_hashed.c_str()));

Но скопипастить без правок не получится, потому что там даже std::forward аналог свой.

Sbtrn. DevilПостоялецwww2 июня 20180:29#7
fsmoke
> Ды вы чё господа - как можно o_O, когда в языке есть лямбды, вариадики,
> структур биндинги и т.д. скатываться в сраные макросы.
Когда задача всем своим существом вопиёт, что решается через макросы - вот так и можно.
+ А снобы-пуристы, которые воротят нос на макросы и goto, должны страдать. Это справедливо и правильно.

*Lain*Пользовательwww2 июня 201811:13#8
https://www.codeproject.com/Articles/18453/Automatic-resource-cle… ght-scope-gua
http://loki-lib.sourceforge.net/html/a00667.html
макросы юзать не обязательно, но вариант с ними есть

Правка: 2 июня 2018 11:16

*Lain*Пользовательwww2 июня 201811:18#9
gammaker
Intra::Finally remover([&](){
  bi::shared_memory_object::remove(_channel_name_hashed.c_str());
});
Intra::Finally remover(std::bind(bi::shared_memory_object::remove, _channel_name_hashed.c_str()));

Правка: 2 июня 2018 11:19

Sbtrn. DevilПостоялецwww2 июня 201816:07#10
*Lain*
> remover
Только придётся для каждого ремувера придумывать имя, а в макросах есть __LINE__/__COUNTER__ и вопрос можно автоматизировать. Но ненавистники макросов будут страдать. :P
gammakerПостоялецwww2 июня 201820:10#11
*Lain*
Неоптимально, потому что внутри придётся сделать std::function или что-то типа него, основанное на стирании типов. А в моём варианте тип статический и всё хорошо заинлайнится компилятором.
И, кстати, твой второй вариант небезопасен. Если строка channel_name_hashed к выходу из скоупа поменяется, прибинженный аргумент может указывать на уже освобождённую память.
fsmokeПостоялецwww4 июня 201813:26#12
Sbtrn. Devil
>должны страдать
дык вот страдаю :)

> Только придётся для каждого ремувера придумывать имя
вот это как раз я считаю более нормальным, чем юзать макросы - а вообще нужно в стандарт добавлять конструкцию имхо

gammaker
Здарова старина - давно не слышал тебя - надо будет скачать твою либу, посмотреть..  не сдался ещё :)  - это радует

Короч написал я говнокод - прям бездумно - хз - подумаю позже, а пока нагажу тут :)

//concept
  struct basic_guard_t
  {
    basic_guard_t(const basic_guard_t &) = delete;
    basic_guard_t & operator=(const basic_guard_t &) = delete;

    virtual void lock() = 0;
    virtual void unlock() = 0;

  protected:

    basic_guard_t() = default;
  };

  template <class Lock, class Unlock>
  struct basic_guard : protected basic_guard_t
  {
    basic_guard(Lock l, Unlock u) :
      _l(l), _u(u) {}

    void lock()  override { _l(); }

    void unlock() override { _u(); }

  private:

    Lock _l;
    Unlock _u;
  };

  template <class Unlock>
  struct basic_guard<nullptr_t, Unlock> : protected basic_guard_t
  {
    basic_guard(nullptr_t , Unlock u) :
      _u(u) {}

    void lock() override {}

    void unlock() override { _u(); }

  private:

    Unlock _u;
  };

  template <class Lock>
  struct basic_guard<Lock, nullptr_t> : protected basic_guard_t
  {
    basic_guard(Lock l, nullptr_t) :
      _l(l) {}

    void lock() override { _l(); }

    void unlock() override { }

  private:

    Lock _l;
  };

  template <class Lock, class Unlock, class RollBack>
  struct guard : public basic_guard<Lock, Unlock>
  {
    using base = basic_guard<Lock, Unlock>;

    guard(Lock l, Unlock u, RollBack r) : base(l, u), _r(r)  {}

    void unlock() override final
    {
      if (_committed)
        base::unlock();
      else
        _r(); 
    }

    inline void commit()
    {
      committed = true;
    }

  private :

    RollBack _r;

    bool _committed = false;
  };

  //similar to basic_guard exept commit 
  template <class Lock, class Unlock>
  struct guard<Lock, Unlock, nullptr_t> : public basic_guard<Lock, Unlock>
  {
    using base = basic_guard<Lock, Unlock>;

    guard(Lock l, Unlock u, nullptr_t) : base(l, u) {}

    void unlock() final
    {
      if (_committed)
        base::unlock(); 
    }

    inline void commit()
    {
      committed = true;
    }

  private:

    bool _committed = false;
  };

  template <class Lock, class Unlock, class RollBack>
  inline guard<Lock, Unlock, RollBack> make_guard(Lock l, Unlock u, RollBack r)
  {
    return guard<Lock, Unlock, RollBack>(l, u, r);
  }

  //some sugar for basic guards
  template <class Lock, class Unlock>
  inline basic_guard<Lock, Unlock> make_guard(Lock l, Unlock u)
  {
    return basic_guard<Lock, Unlock>(l, u);
  }

  template <class Unlock>
  inline basic_guard<nullptr_t, Unlock> make_guard_unlock(Unlock u)
  {
    return basic_guard<nullptr_t, Unlock>(nullptr, u);
  }

Usage

int i = 0;
auto g = make_guard(
  [&i]{
    i = 1;
  }, 
  [&i]{
    i = 2;
  }, 
  [&i] {
    i = 3;
  });

std::lock_guard lock_g(g);

//g.commit();

ЗЫ
Мож где накосепорил, кстати изначально взята концепция Александрески, ну и намешано моего гамна. Единственно для std::lock_guard придется mutex подключить - это кстати ещё одна подстава стандарта - реализовать обобщенную lockable концепцию и один хрен включить её в mutex хедер - бред имхо.

Правка: 4 июня 2018 13:49

fsmokeПостоялецwww4 июня 201813:39#13
Добавил:
Естественно здесь не предусмотрена ситуация с исключениями - думаю имеет смысл вставить noexcept хотя бы в unlock
Sbtrn. DevilПостоялецwww4 июня 201816:19#14
fsmoke
> дык вот страдаю :)
Дык не надо страдать. :) Если от макросов совсем уж страдания, можно ограничиться упрятыванием под макрос названия типа и сгенерённого имени. Чтоб там вроде:
ON_UNWIND = [] { printf("First deinitialization\n"); };
ON_UNWIND = [] { printf("Second deinitialization\n"); };
Страницы: 1 2 Следующая »

/ Форум / Программирование игр / Общее

2001—2018 © GameDev.ru — Разработка игр