сопрограммы
От: jyuyjiyuijyu  
Дата: 16.03.12 00:08
Оценка:
Всем привет

есть такая реализация сопрограмм

#define _WIN32_WINNT 0x400

#include <windows.h>

#include <stdio.h>

////////////////////////////////////////////////////////////////////////////////

// занимается превращением потока в нить и 
// гарантирует, что это будет сделано один раз
class GenBase
{
public:
  static volatile LONG tls_;

  GenBase()
  {
    DWORD newtls = ::TlsAlloc();
    DWORD oldtls = ::InterlockedCompareExchange(&tls_, newtls, 0);
    if (oldtls) ::TlsFree(newtls);

    if (::TlsGetValue(tls_)==0)
    {
      ::TlsSetValue(tls_, (LPVOID)1);
      base_fiber_=::ConvertThreadToFiber(0);
    } else
    {
      base_fiber_=::GetCurrentFiber();
    }
  }

protected:
  LPVOID base_fiber_;
};

////////////////////////////////////////////////////////////////////////////////

// где-то в cpp файле

volatile LONG GenBase::tls_ = 0;


////////////////////////////////////////////////////////////////////////////////

// собственно генератор

template<typename Result>
class Generator : public GenBase
{
public:
  Generator()
  : terminated_(false)
  {
    child_fiber_=::CreateFiber(0, 
      FiberStartProc,
      reinterpret_cast<LPVOID>(this));
  }

  ~Generator()
  {
    DeleteFiber(child_fiber_);
  }

protected:

  void yield(Result res)
  {
    result_ = res;
    SwitchToFiber(base_fiber_);
  }

private:
  static void CALLBACK FiberStartProc(LPVOID context)
  {
    reinterpret_cast<Generator*>(context)->start_fiber();
  }

  virtual void proceed() {}
  void start_fiber()
  {
    proceed();    

    terminated_=true;
    SwitchToFiber(base_fiber_);
  }

public:

  Result operator()()
  {
    // завершение функии нити фатально
    if (terminated_) 
      throw "error";

    ::SwitchToFiber(child_fiber_);
    return result_;
  }


private:
  LPVOID child_fiber_;

  Result result_;
  bool terminated_;
};


class Multi : public Generator<int>
{
public:
  void proceed()
  {
    // функция должна быть вечной
    // если она завершиться это приведет
    // к остановке всего потока
    for(unsigned index=0;; index+=2)
      yield(index);    
  }  
};


int main()
{

  Multi gen;
  Multi gen2;
  for(unsigned index=0; index<100; ++index)
  {
    int a = gen();
    int b = gen2();
    printf("index = %d result = %d %d \n", index, a, b);
  }

  return 0;
}


тут подробнее: http://www.rsdn.ru/forum/cpp/1687242.flat.aspx
Автор: Cyberax
Дата: 18.02.06


есть ли примеры удачного применения из реальной жизни ?
интересно было бы посмотреть или хотя бы интересные мысли..
по удачному применению услышать
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.