🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.os.linux.programowanie
Article #72706

Re: Przełączanie kontekstu

#72706
From: Borneq
Date: Thu, 21 Aug 2014 18:48
147 lines
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-mail
References: <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