Найти - Пользователи
Полная версия: как сделать перенос yield из python в с++ под nix?
Начало » Python для новичков » как сделать перенос yield из python в с++ под nix?
1
doza_and
Иногда позникает потребность перенести критические по быстродействию куски кода в код на c++.
Но питон язык богатый - как просто перенести конструкции - генераторов? Они напрямую в c++ не поддреживаются.

Сейчас пользуюсь велосипедом в windows (см ниже). Вопрос как это можно разумно воспроизвести в nix? (конечно не совсем питоновский вопрос)

Т.е. можно конечно просто тредами реализовать, но будут большие накладные на переключение и синхронизацию тредов. Под виндами сделано через фиберы - затраты на переключение туда обратно порядка 50-100 машинных тактов т е довольно быстро получается. А как посоветуете сделать под nix ?


Пример использования:
#include <iostream>
#include "yieldable.h"

using namespace std;

class Ta:public Tyieldable
{
public:
int beg[3],end[3];
int y,x;
virtual void body()
{
for(y=0;y<3;++y)
{
for(x=beg[y];x<end[y];++x)
{
yield();
}
}
}
};

int main()
{
Ta a;
a.beg[0]=0;a.end[0]=2;
a.beg[1]=2;a.end[1]=15;
a.beg[2]=1;a.end[2]=8;
for(a.begin();!a.done();++a)
{
cout<<a.y<<" "<<a.x<<endl;
}
return 0;
}
Велосипед:
#ifndef yieldable_h
#define yieldable_h

class Tyieldable
{
friend void _stdcall yeldFiberProc(void* lpParameter);
unsigned long dwStackSize;
void* thisFiber;
void* parentFiber;
void CreateFiber();
void DeleteFiber();
bool isRuning;
public:
Tyieldable(unsigned long dwStackSize=0);
virtual ~Tyieldable();
void yield();
void begin();
bool end()
{
if(!isRuning)
{
DeleteFiber();
return true;
}
else
{
return false;
}
}
void operator++();
virtual void body();
};
#endif

#include <include/yieldable.h>

#ifdef __BORLANDC__
#pragma options -tWM -tW -tWR
#define __MT__
#pragma comment(lib,"cw32mt.lib")
#endif

#include <windows.h>
#include <assert.h>



void CALLBACK yeldFiberProc(void* lpParameter)
{
Tyieldable* p=(Tyieldable*)lpParameter;
p->body();
p->isRuning=false;
SwitchToFiber(p->parentFiber);
}
bool IsInvalidFiber(void* f)
{
long l=(long)f;
return (l&0xff)==0;
}

Tyieldable::Tyieldable(unsigned long dwStackSize_):
dwStackSize(dwStackSize_),
thisFiber(NULL),
parentFiber(NULL),
isRuning(false)
{
parentFiber=(void*)GetCurrentFiber();
if(IsInvalidFiber(parentFiber))//!!!! не знаю как проверить что это плохой вызов
{
parentFiber=(void*)ConvertThreadToFiber(this);
if(parentFiber==NULL)
{
throw "can not create parent fiber";
}
}
}
Tyieldable::~Tyieldable()
{
DeleteFiber();
}

void Tyieldable::CreateFiber()
{
DeleteFiber();
thisFiber=::CreateFiber(dwStackSize,&yeldFiberProc,this);
if(thisFiber==NULL)
{
throw "can not create new fiber";
}
}
void Tyieldable::DeleteFiber()
{
if(thisFiber!=NULL)
{
::DeleteFiber(thisFiber);
thisFiber=NULL;
isRuning=false;
}
}

void Tyieldable::yield()
{
SwitchToFiber(parentFiber);
}

void Tyieldable::operator++()
{
if(isRuning)
{
SwitchToFiber(thisFiber);
}
}
void Tyieldable::begin()
{
CreateFiber();
assert(thisFiber!=NULL);
isRuning=true;
SwitchToFiber(thisFiber);
}

void Tyieldable::body()
{
int i=0;
i++;
}
Андрей Светлов
http://ru.wikipedia.org/wiki/Setcontext
doza_and
Спасибо, может сделаю.
А может надо подождать
http://www.crystalclearsoftware.com/soc/coroutine/
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB