<commit_before>#include "ext.hpp"
#include "fiber.hpp"

using namespace std;

class FiberExt : public Fiber {
    thread pthread;
    mutex resumeSign, yieldSign;
    bool end;

    struct Worker {
        Runnable r;
        void *arg;
        FiberExt *self;

        Worker(Runnable r, void *arg, FiberExt *self)
            : r(r), arg(arg), self(self) {}

        void operator ()() {
            self->resumeSign.lock();
            LOG << "fiber " << self->pthread.get_id() << " start";
            r(arg);
            self->end = true;
            Fiber::yield();
            LOG << "fiber " << self->pthread.get_id() << " terminated";
        }
    } worker;
public:
    static FiberExt *current;

    FiberExt(Runnable r, void *arg) : end(false), worker(r, arg, this)  {
        resumeSign.lock();
        yieldSign.lock();
        pthread = thread(worker);
    }

    ~FiberExt() {
        resumeSign.unlock();
        yieldSign.unlock();
        pthread.join();
    }

    bool resume() {
        CHECK(!end) << "call to a terminated fiber!";
        FiberExt *last = current;
        current = this;
        resumeSign.unlock();
        yieldSign.lock();
        LOG << "fiber " << pthread.get_id() << " yield";
        current = last;
        return end;
    }

    static void yield() {
        FiberExt *last = current;
        CHECK_NQ(last, NULL) << "yield from main thread!";
        last->yieldSign.unlock();
        last->resumeSign.lock();
        LOG << "fiber " << last->pthread.get_id() << " resume from another";
    }<commit_msg>solve a bug of fiber<commit_after>#include "ext.hpp"
#include "fiber.hpp"

using namespace std;

class FiberExt : public Fiber {
    thread pthread;
    mutex resumeSign, yieldSign;
    bool end;

    class FiberTerminatedException : public exception {};

    struct Worker {
        Runnable r;
        void *arg;
        FiberExt *self;

        Worker(Runnable r, void *arg, FiberExt *self)
            : r(r), arg(arg), self(self) {}

        void operator ()() {
            try {
                self->resumeSign.lock();
                LOG << "fiber " << self->pthread.get_id() << " start";
                r(arg);
                self->end = true;
                Fiber::yield();
            } catch (FiberTerminatedException &e) {
                LOG << "fiber " << self->pthread.get_id() << " terminated!";
                return;
            }
        }
    } worker;
public:
    static FiberExt *current;

    FiberExt(Runnable r, void *arg) : end(false), worker(r, arg, this)  {
        resumeSign.lock();
        yieldSign.lock();
        pthread = thread(worker);
    }

    ~FiberExt() {
        end = true;
        resumeSign.unlock();
        yieldSign.unlock();
        pthread.join();
    }

    bool resume() {
        CHECK(!end) << "call to a terminated fiber!";
        FiberExt *last = current;
        current = this;
        resumeSign.unlock();
        yieldSign.lock();
        LOG << "fiber " << pthread.get_id() << " yield";
        current = last;
        return end;
    }

    static void yield() {
        FiberExt *last = current;
        CHECK_NQ(last, NULL) << "yield from main thread!";
        last->yieldSign.unlock();
        last->resumeSign.lock();
        LOG << "fiber " << last->pthread.get_id() << " resume from another";
        if (last->end) throw FiberTerminatedException();
    }
{'fraction_non_alphanumeric': 0.14344746162927982, 'fraction_numerical': 0.0, 'mean_word_length': 1.8502943650126156, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '290437', 'n_tokens_mistral': 1057, 'n_tokens_neox': 1013, 'n_words': 247}