Приостановить и возобновить функцию C ++

Я сталкиваюсь с проблемой в программировании, когда я не нашел удобных и быстрых решений для выполнения.

Я пытаюсь реализовать какой-то конечный автомат: взять один байт в записи, обработать его, изменить состояние, цикл и т. Д. Цель состоит в том, чтобы обрабатывать поток байтов, не требуя буфера памяти (обработка байта на байт).

Класс должен выглядеть так:

class Decoder {
void next() {
int i = 0;
std::cout << i << "\n";
i++;
yield(); // pseudo code => should stop the function and save the current state (or simply not freeing allocated variables)
std::cout << i << "\n";
}
};

Decoder decoder = Decoder();
decoder.next(); // print 1
std::cout << "1.5" << "\n"; // print 1.5
decoder.next(); // print 2

Решением может быть создание step свойство, чтобы сохранить шаг, а затем возобновить с переключателем, но производительность будет сильно затронута. Я хотел бы знать, если есть способ выйти из выполнения функции, а затем возобновить его позже?

Чтобы было ясно, я не хочу останавливать всю программу, только функцию. Приостановка такой функции вернет вызывающую программу и продолжит выполнение программы до следующего next называется.

Кроме того, я хотел бы избежать как потока, так и стандартного ввода (я предпочитаю весь код среды). Наконец, если у вас есть другие альтернативы моей проблеме: эффективно обрабатывайте поток байтов для памяти, я открыт для ваших предложений.

Спасибо за вашу помощь.

0

Решение

Я считаю, что вы могли бы достичь этого, используя эти два способа:

Вариант 1: государство-член

Разделите объект конечного автомата на отдельный объект и преобразуйте все свои локальные переменные в члены.

Для каждого шага сохраните State член, обозначающий, где вы сейчас находитесь на протяжении всего выполнения вашей программы.

Каждый раз, когда вы вводите next() проверьте свое состояние с помощью переключателя и вызовите назначенный внутренний метод для этого шага.

Каждый такой метод шага имитирует выполнение кода между последовательными yields,

struct Decoder {
void next() {
switch (_step) {
case s1:
step1();
_step = s2;
return;

case s2:
step2();
_step = s1;
return;

default:
return; // handle error...
}
}

private:
enum Step { s1, s2 };

Step _step = s1;
int _i = 1;

void step1() {
std::cout << _i << "\n";
_i++;
}

void step2() {
std::cout << _i << "\n";
}
};

int main() {
Decoder decoder = Decoder();
decoder.next(); // print 1
std::cout << "1.5" << "\n"; // print 1.5
decoder.next(); // print 2
}

Вариант 2: нить и сигнализация

Используйте поток, который вы, конечно, можете запускать с использованием нативных API (например, pthread_create на платформах POSIX).

Внутри вашей темы, каждый раз, когда вы хотите yieldдождитесь условной переменной, например:

struct Decoder {
Decoder() {
_thread = std::thread { &Decoder::worker, this };
}

~Decoder() {
_thread.join();
}

void next() {
std::lock_guard<std::mutex> lock(_mutex);
_work = true;
}

private:
void wait() {
std::unique_lock<std::mutex> lock(_mutex);
_cond.wait(lock, [this](){return _work;});
}

void worker() {
wait();

int i = 0;
std::cout << i << "\n";
i++;

wait();

std::cout << i << "\n";
}

std::thread _thread;
std::mutex _mutex;
std::condition_variable _cond;
bool _work = false;
};

int main() {
Decoder decoder;
decoder.next(); // print 1
std::cout << "1.5" << "\n"; // print 1.5
decoder.next(); // print 2
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]