Re[20]: Generators in C++, (a.k.a. foreach & iteartors)
От: remark Россия http://www.1024cores.net/
Дата: 28.05.08 13:30
Оценка: +2 :)
Здравствуйте, Erop, Вы писали:

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


R>>А ну да. i и inner надо вынести в переменные класса


E>Ну вот это-то мне тут и не нравится..

E>Но дальше миссер, дальше...
E>
class CPlusPlusPorno {
E>    CPlusPlusPorno inner;
E>};
точно не скомпилируется...



Ну ладно-ладно, туплю. Нужен auto_ptr, как ты сказал.



1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Generators in C++, (a.k.a. foreach & iteartors)
От: gear nuke  
Дата: 28.05.08 15:31
Оценка:
Здравствуйте, remark, Вы писали:

R>Ну так там именно "воробьи" и есть. Поэтому и препроцессор.


Для воробъев слишком жирные, постоянное копирование контекста даром не обходится, да и кеши всякие...

Файбер же выделяет стек страницами, и даже если он 1Mb то коммитится пара страниц... Если очень нужно, можно попробовать сделать заточенную под задачу реализацию (SwitchToFiber — 32 команды x86) с малым стеком... например вызывать жрущие стек АПИ подменяя стек на большой (тут подойдёт Call wrapper )
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[12]: Generators in C++, (a.k.a. foreach & iteartors)
От: c-smile Канада http://terrainformatica.com
Дата: 28.05.08 15:53
Оценка: 18 (1)
Здравствуйте, remark, Вы писали:

R>>Это на основе немного пропатченой версии — сейчас я её запосчу.


R>http://gzip.rsdn.ru/forum/message/2967473.1.aspx
Автор: remark
Дата: 28.05.08


А вот моя обновлённая версия.
Решает проблему stop значения.

  //++ coroutine, generator, continuation for C++

  struct _generator
  {
    int _line;
    _generator():_line(-1) {}
  };

  #define $generator(NAME) struct NAME : public _generator

  #define $emit(T) bool operator()(T& _rv) { \
                      if(_line < 0) { _line=0;}\
                      switch(_line) { case 0:;

  #define $stop  } _line = 0; return false; }

  #define $yield(V)     \
          do {\
              _line=__LINE__;\
              _rv = (V); return true; case __LINE__:;\
          } while (0)

  //-- coroutine, generator, continuation for C++


Генератор описывается как:

$generator(sample_gen)
{
  int n;
  $emit(int) 
    for(n = 10; n >= 0; --n)   
      $yield(n);
  $stop
};


Использование такое же как и в JS — for(var i in seq)

int main(int argc, char* argv[])
{
  sample_gen gen;
  
  for(int n;gen(n);)
      printf("got number = %d\n",n);
    return 0;
}
Re[21]: Generators in C++, (a.k.a. foreach & iteartors)
От: c-smile Канада http://terrainformatica.com
Дата: 28.05.08 16:20
Оценка:
Здравствуйте, remark, Вы писали:

R>Ну ладно-ладно, туплю. Нужен auto_ptr, как ты сказал.


В общем случае нужен stack on the heap.

Для C++ по всей видимости вполне себе будет достаточно объявления _generator как CRTP
структуры/шаблона плюс поле _generatror<NAME>* _stack.

Это точно будет работать — т.е. можно и рекурсивные вызовы делать (но только себя самого)

bool operator()(T& _rv)
{
  do { 
     ....    

  } while(_pop());
}

bool _pop()
{
  if(!_stack) return false;
  _generatror<NAME>* t = _stack;
  *this = *_stack;
  delete t;
}
Re[22]: Generators in C++, (a.k.a. foreach & iteartors)
От: remark Россия http://www.1024cores.net/
Дата: 28.05.08 16:31
Оценка:
Здравствуйте, c-smile, Вы писали:

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


R>>Ну ладно-ладно, туплю. Нужен auto_ptr, как ты сказал.


CS>В общем случае нужен stack on the heap.


CS>Для C++ по всей видимости вполне себе будет достаточно объявления _generator как CRTP

CS>структуры/шаблона плюс поле _generatror<NAME>* _stack.

CS>Это точно будет работать — т.е. можно и рекурсивные вызовы делать (но только себя самого)



А можешь привести полную реализацию с примером использования. А то пока это всё не складывается в единое целое...



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Generators in C++, (a.k.a. foreach & iteartors)
От: remark Россия http://www.1024cores.net/
Дата: 28.05.08 16:37
Оценка:
Здравствуйте, gear nuke, Вы писали:

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


R>>Ну так там именно "воробьи" и есть. Поэтому и препроцессор.


GN>Для воробъев слишком жирные, постоянное копирование контекста даром не обходится, да и кеши всякие...


GN>Файбер же выделяет стек страницами, и даже если он 1Mb то коммитится пара страниц... Если очень нужно, можно попробовать сделать заточенную под задачу реализацию (SwitchToFiber — 32 команды x86) с малым стеком... например вызывать жрущие стек АПИ подменяя стек на большой (тут подойдёт Call wrapper )



Это уже Сapriccio Thread, это тупиковый вариант
http://gzip.rsdn.ru/forum/message/2965307.1.aspx
Автор: remark
Дата: 27.05.08



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[13]: Generators in C++, (a.k.a. foreach & iteartors)
От: remark Россия http://www.1024cores.net/
Дата: 28.05.08 16:43
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>А вот моя обновлённая версия.

CS>Решает проблему stop значения.

... но return в середине писать всё равно нельзя.
Без него сложные генераторы становятся... ещё сложнее



CS>Использование такое же как и в JS — for(var i in seq)

CS>
CS>int main(int argc, char* argv[])
CS>{
CS>  sample_gen gen;
  
CS>  for(int n;gen(n);)
CS>      printf("got number = %d\n",n);
CS>    return 0;
CS>}
CS>



Раз уж тут и так всё из макросов, можно накрутить, что бы вот так писать:
$foreach(int i, some_gen(10))
  printf("got number = %d\n",n);




1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[23]: Generators in C++, (a.k.a. foreach & iteartors)
От: c-smile Канада http://terrainformatica.com
Дата: 28.05.08 23:08
Оценка:
Здравствуйте, remark, Вы писали:

CS>>В общем случае нужен stack on the heap.


CS>>Для C++ по всей видимости вполне себе будет достаточно объявления _generator как CRTP

CS>>структуры/шаблона плюс поле _generatror<NAME>* _stack.

CS>>Это точно будет работать — т.е. можно и рекурсивные вызовы делать (но только себя самого)


R>А можешь привести полную реализацию с примером использования. А то пока это всё не складывается в единое целое...


Постараюсь на неделе соорудить. Сейчас со временем — швах.
Re[14]: Generators in C++, (a.k.a. foreach & iteartors)
От: c-smile Канада http://terrainformatica.com
Дата: 28.05.08 23:12
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, c-smile, Вы писали:


CS>>А вот моя обновлённая версия.

CS>>Решает проблему stop значения.

R>... но return в середине писать всё равно нельзя.

R>Без него сложные генераторы становятся... ещё сложнее

break по смыслу я понимаю. А return-то зачем?

R>Раз уж тут и так всё из макросов, можно накрутить, что бы вот так писать:

R>
R>$foreach(int i, some_gen(10))
R>  printf("got number = %d\n",n);
R>


Да вроде и с for(v;gen(v) нормально. Или я чего не понял?
Re[13]: Generators in C++, (a.k.a. foreach & iteartors)
От: siv Украина  
Дата: 29.05.08 09:22
Оценка:
CS>А вот моя обновлённая версия.
CS>Решает проблему stop значения.

Теперь ещё изящнее.
Жаль, что в теле генератора нельзя yield во внутреннем switch использовать.
Увы, не хватает "динамического goto" какого-нибудь:
#define $emit(T)    bool operator()(T& _rv) { \
                      if(_line < 0) { _line=0;}\
                      goto label(_line) // <- иди туда, куда _line укажет или... exception or UB

#define $yield(V)     \
          do {\
              _line=__LINE__;\
              _rv = (V); \
               return true; \
               label(__LINE__):;\ // <- сегануть сюда бы, да без помощи свича!
          } while (0)


Думаю, что _asm тут бы помого, но было бы непортабельно и еще более извращеннее.
Re[14]: Generators in C++, (a.k.a. foreach & iteartors)
От: Erop Россия  
Дата: 29.05.08 10:07
Оценка:
Здравствуйте, siv, Вы писали:

siv>
siv>               label(__LINE__):;\ // <- сегануть сюда бы, да без помощи свича!
siv>


siv>Думаю, что _asm тут бы помого, но было бы непортабельно и еще более извращеннее.


А думаешь нельзя?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[15]: Generators in C++, (a.k.a. foreach & iteartors)
От: siv Украина  
Дата: 29.05.08 10:19
Оценка:
Здравствуйте, Erop, Вы писали:

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


siv>>
siv>>               label(__LINE__):;\ // <- сегануть сюда бы, да без помощи свича!
siv>>


siv>>Думаю, что _asm тут бы помог, но было бы непортабельно и еще более извращеннее.


E>А думаешь нельзя?

Что нельзя?
Реализовать? На asm — думаю вполне можно.
Извращаться? Зависит от политики...
Забить на портабильность? Сделать под каждую платфорсу вариант? Можно, но зависит от...
Re[2]: Generators in C++, (a.k.a. foreach & iteartors)
От: yumi  
Дата: 29.05.08 14:04
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Решено: щас всё брошу, пойду изучать, как делаются континюэйшены в лиспе.


Если не шутишь, то можешь посмотреть как это делает Слава здесь.
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org
Re[8]: Generators in C++, (a.k.a. foreach & iteartors)
От: gear nuke  
Дата: 29.05.08 14:09
Оценка:
Здравствуйте, remark, Вы писали:

R>Это уже Сapriccio Thread, это тупиковый вариант


Не смотрел даже испугали слова "нереальный анализ потребления стека функциями". ИМХО не надо искать серебрянную пулю (некоторые автоматы вообще руками писать не стоит) а под конкретные задачи размер стека можно прикинуть... Я лишь хотел сказать что контекст копировать — это всё равно что
volatile int global;

int main()
{
  int i;
  global = 2;
  i = global;
}
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[9]: Generators in C++, (a.k.a. foreach & iteartors)
От: remark Россия http://www.1024cores.net/
Дата: 29.05.08 14:32
Оценка: 7 (1) :)
Здравствуйте, gear nuke, Вы писали:

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


R>>Это уже Сapriccio Thread, это тупиковый вариант


GN>Не смотрел даже испугали слова "нереальный анализ потребления стека функциями".


Там что-то типа такого, что пользовательский код анализируется специальным компилятором на потребление стека.
На стандартные библиотечные функции они рассчитывают, что будут специальные аннотации по поводу максимального потребления стека.
А для известного кода используются специальные большие стеки, которые динамически подцепляются и отцепляются.
Ну и плюс с рекурсией там своё веселье.
Ну и общий подход такой, что в рантайме на специальных сгенерированных чекпоинтах проверяется, дотянет ли поток до следующего чекпоинта на текущем стеке. Если нет — то подцепляется новый кусочек.

Ну в общем, ты понял. Если ты не академик, и есть хоть какие-то мысли чем заняться полезным, то не стОит смотреть в эту сторону


GN>ИМХО не надо искать серебрянную пулю (некоторые автоматы вообще руками писать не стоит) а под конкретные задачи размер стека можно прикинуть... Я лишь хотел сказать что контекст копировать — это всё равно что

GN>
GN>volatile int global;

GN>int main()
GN>{
GN>  int i;
GN>  global = 2;
GN>  i = global;
GN>}
GN>





1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[12]: Generators in C++, (a.k.a. foreach & iteartors)
От: anonim_44ax  
Дата: 29.05.08 14:52
Оценка:
К сожалению даже так можно:
#include <vector>

struct SomeType
{
      std::vector< SomeType > vec;
};

int main()
{
      SomeType variable;
      variable.vec.push_back( variable );
      return 0;
}



При этом, сей код под MS VS 7.1.3 не только компиллируется, но и успешно работает.
Re[13]: Generators in C++, (a.k.a. foreach & iteartors)
От: remark Россия http://www.1024cores.net/
Дата: 29.05.08 15:00
Оценка: +2
Здравствуйте, anonim_44ax, Вы писали:

_>К сожалению даже так можно:


_>

_>При этом, сей код под MS VS 7.1.3 не только компиллируется, но и успешно работает.


То, что это работает, это я проверил. Вопрос — насколько это соотв. стандарту. Ну или хотя бы будет работать на других компиляторах?

Т.к. достаточно, что бы в определении vector было что-то типа такого, что бы это перестало компилироваться:
template<typename T>
class vector
{
  char buf [sizeof(T)];
  ...
};



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[13]: Generators in C++, (a.k.a. foreach & iteartors)
От: Erop Россия  
Дата: 29.05.08 15:04
Оценка:
Здравствуйте, anonim_44ax, Вы писали:

_>К сожалению даже так можно:

Почему "к сожалению"?

_>

_>При этом, сей код под MS VS 7.1.3 не только компиллируется, но и успешно работает.
Вопрос не в том, "может ли это скомпилироваться", а несколько в обратном "может ли это НЕ скомпилироваться"
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[15]: Generators in C++, (a.k.a. foreach & iteartors)
От: siv Украина  
Дата: 29.05.08 16:30
Оценка:
siv>>Думаю, что _asm тут бы помого, но было бы непортабельно и еще более извращеннее.
E>А думаешь нельзя?

Вот, на скорую руку сваял ещё одно "извращение" just for fun.
Можно внутри генераторов обойтись без Duff's device извращений и заработает switch.
VC8. Под g++ такое не осилю в данный момент.

#ifndef __generator_h_
#define __generator_h_

#include <boost/preprocessor/cat.hpp>

class _generator
{
protected:
    int _addr;
    _generator():_addr(-1) {}
};

//..................................................................
#define $generator(NAME) class NAME : public _generator

#define  GOTO_LABEL         \
  if ( _addr!=-1 )          \
  {                         \
    int addr = _addr;       \
    __asm                   \
    {                       \
      __asm mov eax, addr   \
      __asm jmp eax         \
    }                       \
  }

#define $emit(T)    bool operator()(T& _rv)     \
                    {                           \
                      GOTO_LABEL                \
                      {
//.......

#define $stop         }                       \
                     _addr = -1;              \
                     return false;            \
                   }

#define $yield(V)                             \
          do {                                \
            _rv = (V);                        \
                                              \
            int * iPtr = &_addr;              \
            __asm mov ecx, dword ptr [iPtr]   \
            __asm                             \
            {                                 \
              __asm mov eax, OFFSET BOOST_PP_CAT(label,__LINE__) \
              __asm mov dword ptr [ecx], eax  \
            }                                 \
                                              \
            return true;                      \
            BOOST_PP_CAT(label,__LINE__)##:;  \
          } while (0);

#endif // __generator_h_

//=============================================================================
#include <stdio.h>

$generator(desc)
{
  int m_i;

public:
  desc( int start=-1 ) : m_i(start) {}

  $emit(int) 
  {
    for(; m_i >= 0; --m_i)
    {
// doesn't it work ?
      switch ( m_i )
      {
        case 9 : case 7 :
          $yield( m_i + 100 );
        break;

        case 5:
          $yield( m_i + 100000 );
        break;
      
        default:
          $yield( m_i );
      }
    }
  }
  $stop  
};


int main(int argc, char* argv[])
{
  desc gen( 11 );
  int i;
  while(gen(i))
  {    
    printf("got number %d\n", i);
    //gen.m_i = 10;
  }
}


Пришлось выкрутасы делать из-за странностей VC, например
int * iPtr = &_addr;              \
__asm mov ecx, dword ptr [iPtr]   \
Re[14]: Generators in C++, (a.k.a. foreach & iteartors)
От: c-smile Канада http://terrainformatica.com
Дата: 29.05.08 16:34
Оценка: 1 (1)
Здравствуйте, siv, Вы писали:

siv>Увы, не хватает "динамического goto" какого-нибудь:


В GCC кстати такой goto есть. И там можно все это построить без наворотов со switch.
Там можно взять адрес label и по нему перейти — goto *label.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.