Article View: pl.comp.os.linux.programowanie
Article #72706Re: Przełączanie kontekstu
From: Borneq
Date: Thu, 21 Aug 2014 18:48
Date: Thu, 21 Aug 2014 18:48
147 lines
3962 bytes
3962 bytes
W dniu 2014-08-21 o 00:14, Borneq pisze:
> czy konteksty mają własne stosy, które mogą niezależnie rosnąć?
Czy jest coś takiego jak zwalnianie kontekstu? Nigdzie nie znalazłem
czegoś takiego jak FreeContext. Czy też zwalniany jest gdy główna
funkcja się kończy?
Ale należy pamiętać, że w kontekście przydzielamy bajty dla stosu, które
w destruktorze zwalniam.
Chcę napisać klasę obsługująca konteksty, na razie mam:
#include <ucontext.h>
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
struct fiber_t
{
ucontext_t fib;
jmp_buf jmp;
};
struct fiber_ctx_t
{
void(* fnc)(void*);
void* ctx;
jmp_buf* cur;
ucontext_t* prv;
};
class Coroutine{
private:
fiber_t fib;
public:
virtual void execute() =0;
void yield(Coroutine *next=NULL);
void attach();
Coroutine(long stackSize);
virtual ~Coroutine();
};
static void fiber_start_fnc(void* p)
{
fiber_ctx_t* ctx = (fiber_ctx_t*)p;
void* uctx = ctx->ctx;
if (_setjmp(*ctx->cur) == 0)
{
ucontext_t tmp;
swapcontext(&tmp, ctx->prv);
}
Coroutine *coroutine = (Coroutine *)uctx;
coroutine->execute();
}
inline void create_fiber(fiber_t* fib, void* uctx)
{
getcontext(&fib->fib);
size_t const stack_size = 64*1024;
fib->fib.uc_stack.ss_sp = (::malloc)(stack_size);
fib->fib.uc_stack.ss_size = stack_size;
fib->fib.uc_link = 0;
ucontext_t tmp;
fiber_ctx_t ctx = {NULL, uctx, &fib->jmp, &tmp};
makecontext(&fib->fib, (void(*)())fiber_start_fnc, 1, &ctx);
swapcontext(&tmp, &fib->fib);
}
inline void switch_to_fiber(fiber_t& fiber, fiber_t& prevfiber)
{
if (_setjmp(prevfiber.jmp) == 0)
_longjmp(fiber.jmp, 1);
}
__thread fiber_t fibmain;
__thread bool initialized_fibmain = false;
void Coroutine::yield(Coroutine *next)
{
if (next==NULL)
switch_to_fiber(fibmain, fib);
else
switch_to_fiber(next->fib, fib);
}
void Coroutine::attach()
{
switch_to_fiber(fib, fibmain);
}
Coroutine::Coroutine(long stackSize)
{
if (!initialized_fibmain)
{
create_fiber(&fibmain, NULL);
initialized_fibmain = true;
}
create_fiber(&fib, this);
}
Coroutine::~Coroutine()
{
free(fib.fib.uc_stack.ss_sp);
}
Coroutine *A,*B;
class CoroutineA : public Coroutine{
public:
CoroutineA(): Coroutine(8*1024){};
void execute()
{
printf("CoroutineA\n");
for (int i=0; i<100; i++)
{
printf("i=%d\n",i);
yield(B);
}
printf("after yield CoroutineA\n");
}
};
class CoroutineB : public Coroutine{
public:
CoroutineB(): Coroutine(8*1024){};
void execute()
{
printf("CoroutineB\n");
for (int i=0; i<100; i++)
{
printf("i=%d\n",i);
yield(A);
}
printf("after yield CoroutineB\n");
}
};
int main()
{
A = new CoroutineA();
B = new CoroutineB();
A->attach();
delete A;
delete B;
return 0;
}
Technical Details
Message-ID:
<lt5eut$gf$1@node1.news.atman.pl>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!agh.edu.pl!news.agh.edu.pl!newsfeed2.atman.pl!newsfeed.atman.pl!.POSTED!not-for-mailReferences:
<lt36l4$dg4$1@node1.news.atman.pl>Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!agh.edu.pl!news.agh.edu.pl!newsfeed2.atman.pl!newsfeed.atman.pl!.POSTED!not-for-mail From: Borneq <borneq@antyspam.hidden.pl> Newsgroups: pl.comp.os.linux.programowanie Subject: Re: Przełączanie kontekstu Date: Thu, 21 Aug 2014 20:48:46 +0200 Organization: ATMAN - ATM S.A. Lines: 148 Message-ID: <lt5eut$gf$1@node1.news.atman.pl> References: <lt36l4$dg4$1@node1.news.atman.pl> NNTP-Posting-Host: 91.239.205.62 Mime-Version: 1.0 X-Trace: node1.news.atman.pl 1408646941 527 91.239.205.62 (21 Aug 2014 18:49:01 GMT) X-Complaints-To: usenet@atman.pl NNTP-Posting-Date: Thu, 21 Aug 2014 18:49:01 +0000 (UTC) User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.0 In-Reply-To: <lt36l4$dg4$1@node1.news.atman.pl> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit