Как Вы реализуете Сопрограммы в C++

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

63
задан Atifm 6 January 2017 в 16:45
поделиться

8 ответов

Да это может быть сделано без проблемы. Все, в чем Вы нуждаетесь, является небольшим ассемблерным кодом для перемещения стека вызовов в недавно выделенный стек на "куче".

я был бы смотреть эти повышение:: библиотека сопрограммы .

одной вещью, которую необходимо не упустить, является переполнение стека. В большинстве операционных систем, переполняющих стека, вызовет segfault, потому что страница виртуальной памяти не отображается. Однако при выделении стека на "куче", Вы не получаете гарантии. Просто имейте это в виду.

89
ответ дан Nayuki 24 November 2019 в 16:09
поделиться

WvCont является частью WvStreams, который реализует так называемые полусопрограммы. Их немного легче обработать, чем настоящие сопрограммы: Вы звоните в него, и это уступает назад человеку, который назвал его.

Это реализовало использование более гибкого WvTask, который поддерживает настоящие сопрограммы; можно найти его в той же библиотеке.

Работы над win32 и Linux, по крайней мере, и вероятно любой другой системой Unix.

0
ответ дан apenwarr 24 November 2019 в 16:09
поделиться

Необходимо всегда рассматривать использование потоков вместо этого; особенно в современных аппаратных средствах. Если у Вас есть работа, которая может быть логически разделена в Сопрограммах, использование потоков означает, что работа могла бы на самом деле быть сделана одновременно отдельными модулями выполнения (ядра процессора).

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

, Если Вы работаете в рамках Windows, необходимо смотреть на волокна . Волокна дадут Вам подобную сопрограмме платформу при поддержке ОС.

я не знаком с другой ОС для рекомендации альтернатив там.

0
ответ дан Euro Micelli 24 November 2019 в 16:09
поделиться

СОПРОГРАММА портативная библиотека C++ для сопрограммы, упорядочивающей точка Вы в правильном направлении? Это походит на изящное решение, которое продлилось испытание временем....., этому 9 лет!

В папке DOC PDF бумаги Портативная Библиотека C++ для Упорядочивания Сопрограммы Keld Helsgaun, который описывает библиотеку и обеспечивает короткие примеры с помощью нее.

[обновление] я на самом деле делаю успешное использование из него сам. Любопытство взяло верх надо мной, таким образом, я изучил это решение и нашел, что это было подходящим вариантом для проблемы, я продолжал работать в течение некоторого времени!

5
ответ дан Richard Chambers 24 November 2019 в 16:09
поделиться

Я не думаю, что в C++ существует много полноценных, чистых реализаций. Одна попытка, которую я люблю, protothread библиотека Adam Dunkels .

См. также Protothreads: упрощение событийно-ориентированного программирования ограниченных памятью встроенных систем в Цифровой библиотеке ACM и обсуждении в теме Википедии Protothread,

5
ответ дан Richard Chambers 24 November 2019 в 16:09
поделиться

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

Это могло бы сделать вещи более удобными в сопровождении. Другой разработчик C++ не мог бы сразу понять сопрограмму, тогда как они могли бы быть более знакомы с итератором.

7
ответ дан pts 24 November 2019 в 16:09
поделиться

На POSIX можно использовать makecontext ()/swapcontext () стандартные программы для портативного переключения контекстов выполнения. В Windows можно использовать оптоволоконный API. Иначе все, в чем Вы нуждаетесь, является небольшим количеством ассемблерного кода связующего звена, который переключает контекст машины. Я реализовал сопрограммы оба с ASM (для AMD64) и с swapcontext (); ни один не очень тверд.

18
ответ дан zvrba 24 November 2019 в 16:09
поделиться

На основе макросов также (Устройство вареного пудинга, полностью портативное, видят http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html ) и вдохновленный ссылкой, отправленной Mark, следующее эмулирует, совместно обрабатывает события использования сотрудничества как механизм синхронизации (немного отличающаяся модель, чем традиционный стиль co-routines/generator)

// Coprocess.h
#pragma once
#include <vector>

class Coprocess {
  public:
    Coprocess() : line_(0) {}
    void start() { line_ =  0; run(); }
    void end()   { line_ = -1; on_end(); }
    virtual void run() = 0;
    virtual void on_end() {}; 
  protected:
    int line_;
};

class Event {
  public:
    Event() : curr_(0) {}

    void wait(Coprocess* p) { waiters_[curr_].push_back(p); }

    void notify() {
        Waiters& old = waiters_[curr_];
        curr_ = 1 - curr_; // move to next ping/pong set of waiters
        waiters_[curr_].clear();
        for (Waiters::const_iterator I=old.begin(), E=old.end(); I != E; ++I)
            (*I)->run();
    }   
  private:
    typedef std::vector<Coprocess*> Waiters;
    int curr_;
    Waiters waiters_[2];
};

#define corun()   run() { switch(line_) { case 0:
#define cowait(e) line_=__LINE__; e.wait(this); return; case __LINE__:
#define coend     default:; }} void on_end()

пример использования:

// main.cpp
#include "Coprocess.h"
#include <iostream>

Event e;
long sum=0;

struct Fa : public Coprocess {
    int n, i;
    Fa(int x=1) : n(x) {}
    void corun() {
        std::cout << i << " starts\n";
        for (i=0; ; i+=n) {
            cowait(e);
            sum += i;
        }
    } coend {
        std::cout << n << " ended " << i << std::endl;
    }   
};

int main() {
    // create 2 collaborating processes
    Fa f1(5);
    Fa f2(10);

    // start them
    f1.start();
    f2.start();
    for (int k=0; k<=100; k++) { 
        e.notify();
    }   
    // optional (only if need to restart them)
    f1.end();
    f2.end();

    f1.start(); // coprocesses can be restarted
    std::cout << "sum " << sum << "\n";
    return 0;
}
1
ответ дан 24 November 2019 в 16:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: