Старое криведко ([info]bacek) wrote,
@ 2008-01-24 17:47:00
Previous Entry  Add to memories!  Tell a Friend  Next Entry
Entry tags:c, rulez, sux, tech

ииик...
http://en.wikipedia.org/wiki/Setcontext



#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>

/* This is the iterator function. It is entered on the first call to
 * swapcontext, and loops from 0 to 9. Each value is saved in i_from_iterator,
 * and then swapcontext used to return to the main loop.  The main loop prints
 * the value and calls swapcontext to swap back into the function. When the end
 * of the loop is reached, the function exits, and execution switches to the
 * context pointed to by main_context1. */
void loop(ucontext_t *loop_context, ucontext_t *other_context, int *i_from_iterator)
{
    int i;
    
    for (i=0; i < 10; ++i) {
        /* Write the loop counter into the iterator return location. */
        *i_from_iterator = i;
        
        /* Save the loop context (this point in the code) into loop_context,
         * and switch to other_context. */
        swapcontext(loop_context, other_context);
    }
    
    /* The function falls through to the calling context with an implicit
     * setcontext(&loop_context->uc_link); */
}

int main(void)
{
    /* The three contexts:
     *    (1) main_context1 : The point in main to which loop will return.
     *    (2) main_context2 : The point in main to which control from loop will
     *                        flow by switching contexts.
     *    (3) loop_context  : The point in loop to which control from main will
     *                        flow by switching contexts. */
    ucontext_t main_context1, main_context2, loop_context;
    
    /* The stack for the iterator function. */
    char iterator_stack[SIGSTKSZ];

    /* Flag indicating that the iterator has completed. */
    volatile int iterator_finished;
  
    /* The iterator return value. */
    volatile int i_from_iterator;
  
    /* Initialise the iterator context. uc_link points to main_context1, the
     * point to return to when the iterator finishes. */
    loop_context.uc_link          = &main_context1;
    loop_context.uc_stack.ss_sp   = iterator_stack;
    loop_context.uc_stack.ss_size = sizeof(iterator_stack);
    getcontext(&loop_context);
    
    /* Fill in loop_context so that it makes swapcontext start loop. The
     * (void (*)(void)) typecast is to avoid a compiler warning but it is
     * not relevant to the behaviour of the function. */
    makecontext(&loop_context, (void (*)(void)) loop,
        3, &loop_context, &main_context2, &i_from_iterator);
  
    /* Clear the finished flag. */      
    iterator_finished = 0;

    /* Save the current context into main_context1. When loop is finished,
     * control flow will return to this point. */
    getcontext(&main_context1);
  
    if (!iterator_finished) {
        /* Set iterator_finished so that when the previous getcontext is
         * returned to via uc_link, the above if condition is false and the
         * iterator is not restarted. */
        iterator_finished = 1;
      
        while (1) {
            /* Save this point into main_context2 and switch into the iterator.
             * The first call will begin loop.  Subsequent calls will switch to
             * the swapcontext in loop. */
            swapcontext(&main_context2, &loop_context);
            printf("%d\n", i_from_iterator);
        }
    }
  
    return 0;
}


Я в шоке... Call/cc в pure-C это за гранью добра и зла...



(28 comments) - (Post a new comment)


[info]cdplayer
2008-01-24 07:11 am UTC (link)
Мммм, падкат?

(Reply to this) (Thread)


[info]bacek
2008-01-24 07:17 am UTC (link)
Дяденька, дяденька, только ногами не бейте!!! Я больше не буду!!!

Был на столько в шоке, что забыл кат поставить...

(Reply to this) (Parent)


[info]highlander_spb
2008-01-24 07:42 am UTC (link)
Отсыпь, а? Так и не вкурил, что ЭТОТ код делает...

(Reply to this) (Thread)


[info]bacek
2008-01-24 08:50 am UTC (link)
Читай в педивикии про Continuations. Там всё более менее расписано.

(Reply to this) (Parent)(Thread)


[info]highlander_spb
2008-01-24 10:23 am UTC (link)
Все равно это черная магия какая-то :)

(Reply to this) (Parent)(Thread)


[info]bacek
2008-01-25 12:17 am UTC (link)
http://bacek.livejournal.com/255976.html

(Reply to this) (Parent)(Thread)


[info]highlander_spb
2008-01-25 12:19 am UTC (link)
А для идиотов объяснение есть?

(Reply to this) (Parent)


[info]highlander_spb
2008-01-25 12:20 am UTC (link)
Ибо в то, что я думаю про этот код, разум отказывается верить...

(Reply to this) (Parent)(Thread)


[info]bacek
2008-01-25 12:32 am UTC (link)
http://community.schemewiki.org/?call-with-current-continuation-for-c-programmers

(Reply to this) (Parent)(Thread)


[info]highlander_spb
2008-01-25 12:50 am UTC (link)
Мля.. Догнал.. кажется...

Ужос... Кажется, я даже знаю, где я бы ЭТО применил, если бы знал тога..

(Reply to this) (Parent)


[info]bacek
2008-01-25 12:33 am UTC (link)
И да. Я не Люцифер, я только учусь :)

(Reply to this) (Parent)(Thread)


[info]highlander_spb
2008-01-25 12:43 am UTC (link)
Но на чернокнижника точно тянешь :)

(Reply to this) (Parent)


[info]motto
2008-01-24 08:56 am UTC (link)
интересно, чувакам слабо то же самое для макроассемблера сработать?

(Reply to this) (Thread)


[info]bacek
2008-01-24 09:01 am UTC (link)
Так C и есть макроассемблер.

(Reply to this) (Parent)


[info]ivan_ghandhi
2008-01-24 04:16 pm UTC (link)
Миленькая вещь; жаль только, что в си всё через жопу вилкой. Поэтому как языковая конструкция это вызывает у рядового читателя полное остолбенение.

(Reply to this) (Thread)


[info]bacek
2008-01-24 10:33 pm UTC (link)
У нерядового тоже… Я минут 5 втыкал, пытаясь понять, что происходит…

(Reply to this) (Parent)


[info]smalgin
2008-01-24 05:01 pm UTC (link)
Век живи, век учись.

(Reply to this)


[info]smalgin
2008-01-24 05:27 pm UTC (link)
Нашел интересное
http://blogs.msdn.com/larryosterman/archive/2005/01/05/347314.aspx

Но это только к виндам относится. Интересно было бы найти похожую статью про юниксовые fibers.

(Reply to this) (Thread)


[info]bacek
2008-01-24 10:37 pm UTC (link)
Не осилил, многа букв. Но на вскидку очень похоже на green threads.

(Reply to this) (Parent)


[info]pg
2008-01-24 05:28 pm UTC (link)
Ха. У нас корутины/продолжения давно используются в production :)))

http://pg.livejournal.com/12769.html

На этой технологии очень удобно делать scatter/gather io.

(Reply to this) (Thread)


[info]pg
2008-01-24 05:30 pm UTC (link)
И, кстати, генераторы на продолжениях местами тоже используем(в С++) - например, у меня есть HeapGenerator(похоже на HeapIterator, только генератор :))

(Reply to this) (Parent)(Thread)


[info]bacek
2008-01-24 10:35 pm UTC (link)
А зачем??? Чем там просто итераторы не подходят?

(Reply to this) (Parent)(Thread)


[info]pg
2008-01-25 11:09 am UTC (link)
Представь себе, есть код вида:
while (i = Get()) {
Push(i);
}

Причем известно, что все по i отсортировано. А теперь представь, что в программу надо по быстрому добавить генерацию выходного отсортированного потока по нескольким таким циклам :)

(Reply to this) (Parent)(Thread)


[info]bacek
2008-01-25 11:33 am UTC (link)
Ээээ... Merge-join или я что-то не допонимаю?

(Reply to this) (Parent)(Thread)


[info]pg
2008-01-25 11:40 am UTC (link)
Блииин. Тут вопрос в организации кода - представь, у тебя есть n потоков выполнения, каждый из которых выполняет этот цикл. В результате нужно получить смерженный поток выполнения. Это и есть генератор в чистом виде.

(Reply to this) (Parent)


[info]bacek
2008-01-24 10:35 pm UTC (link)
Ну обычно корутины на сях реализуются ручками через жопу. Во всяком случае лет несколько так назад и было. А тут уже практически всё готово.

(Reply to this) (Parent)(Thread)


[info]pg
2008-01-25 11:07 am UTC (link)
Посмотри в нашем утиле ycoroutine.h :)))

(Reply to this) (Parent)(Thread)


[info]bacek
2008-01-25 11:33 am UTC (link)
Мне до вашего утиля добираться через жопу... Посмотрю, как-нибудь.

(Reply to this) (Parent)


(28 comments) - (Post a new comment)

Create an Account
Forgot your login or password?
Login w/ OpenID
English • Español • Deutsch • Русский…