C ++ kiinteäkokoinen jono täysi / tyhjä signalointi

Harkitsen sovellusta, jossa on usein kirjoitettava suuri data tiedostoon. Haluaisin käyttää jono ja tuottaja ja kuluttaja toimivat eri säikeillä. Lisäksi haluaisin kiinteän kokoisen jonon, koska datan koko voi olla hyvin suuri. Olen toteuttanut yksinkertaisen testin boost :: lockfree :: jono boostilla :: condition_variable ilmoittaa jonon tilan. Haluaisin välttää mykistyksen, mutta lukuun ottamatta tapauksia, joissa jono on täynnä (tuottaja) tai tyhjä (estä kuluttaja)

Haluaisin tietää (jos mielipiteiden riski on ..) jos ” m käyttää ehdollisia oikein tai jos suorituskykyongelmia on – verrattuna muihin menetelmiin. Tässä on, mitä olen tähän mennessä tehnyt (pieni data)

#include <iostream> #include <boost/thread/thread.hpp> #include <boost/lockfree/queue.hpp> #define N 6 #define QN 3 struct testdata { int a; int b; }; boost::lockfree::queue<testdata, boost::lockfree::fixed_size<true>> que(QN); boost::condition_variable que_has_data, que_has_room; boost::mutex que_mtx_hd, que_mtx_hr; void producer(void) { testdata td; int i = 0; boost::mutex::scoped_lock lock(que_mtx_hr); boost::this_thread::sleep(boost::posix_time::seconds(1)); for (;;) { td.a = i; td.b = i + 1; if (!que.push(td)) { std::cout << "producer waiting" << std::endl; que_has_room.wait(lock); } else { std::cout << "pushed " << td.a << std::endl; i += 1; que.has_data_notify_one(); } if (i > N) break; } } void consumer(void) { testdata td; boost::mutex::scoped_lock lock(que_mtx_hd); for (;;) { if (que.pop(td)) { std::cout << "popped " << td.a << std::endl; if (td.a == N) break; que_has_room.notify_one(); } else { std::cout << "consumer waiting" << std::endl; que_has_data.wait(lock); } } boost::this_thread::sleep(boost::posix_time::seconds(1)); } int main(void) { boost::thread t1(&producer); boost::thread t2(&consumer); t1.join(); t2.join(); return 0; } 

Tämä toimii (tulos):

consumer waiting pushed 0 pushed 1 pushed 2 producer waiting popped 0 pushed 3 producer waiting popped 1 pushed 4 producer waiting popped 2 pushed 5 producer waiting popped 3 pushed 6 popped 4 popped 5 popped 6 

Odotan, että suurimmaksi osaksi tietoja on melkein aina saatavilla, mutta haluan estää ruuhkat ( kirjoitus, verkko jne.). Kiinnostus kiinteään kokoon on huoli massiivisista tietojoukoista ja dynaamisesta allokoinnista jonossa –

(Tämä on enemmän kokeilu siitä, mitä voidaan tehdä. Todellisuudessa tietoni päivitetään enintään noin 20 Hz Joten vain lukon ottaminen vakio :: jonoon, jonka hallitsen koon, toimii myös hyvin.)

Vastaa

Käytä semaforia saadaksesi tuottajat nukkumaan jonon ollessa täynnä, ja toisen semaforin avulla kuluttajat nukkumaan jonon ollessa tyhjä. kun jono ei ole täynnä eikä tyhjä, sem_post- ja sem_wait-operaatiot ovat estämättömiä (uudemmissa ytimissä)

#include <semaphore.h> template<typename lock_free_container> class blocking_lock_free { public: lock_free_queue_semaphore(size_t n) : container(n) { sem_init(&pop_semaphore, 0, 0); sem_init(&push_semaphore, 0, n); } ~lock_free_queue_semaphore() { sem_destroy(&pop_semaphore); sem_destroy(&push_semaphore); } bool push(const lock_free_container::value_type& v) { sem_wait(&push_semaphore); bool ret = container::bounded_push(v); ASSERT(ret); if (ret) sem_post(&pop_semaphore); else sem_post(&push_semaphore); // shouldn"t happen return ret; } bool pop(lock_free_container::value_type& v) { sem_wait(&pop_semaphore); bool ret = container::pop(v); ASSERT(ret); if (ret) sem_post(&push_semaphore); else sem_post(&pop_semaphore); // shouldn"t happen return ret; } private: lock_free_container container; sem_t pop_semaphore; sem_t push_semaphore; }; 

Vastaa

Olisin hyvin skeptinen koodissa, joka sisältää lukittoman säilön, kaksi muteketta ja ehdollisen muuttujan langanvälisen estojonon toteuttamiseksi. Edes katsomatta pidemmälle.

Aloitan luultavasti alla olevasta prototyypistä (ehkä ensin tarkistan, onko boost :: interprocessilla mitään, mitä voisin käyttää heti):

  1. wrap boost::circular_buffer osaksi facebook/Folly/Synchronized, mutta mukautetulla kaapilla, joka tekee try_lock(), pyörii sitten vielä 41 kertaa try_lock() ja estää sitten lock() -kohdan, laskemalla kaikkien kolmen skenaarion esiintymät ja ilmoituksen / odotuksen päällä
  2. Haluaisin vapauttaa sen tuotantoon pilottitilassa ja tarkistaa, tarvitseeko minun todella vaivautua lukittoman kontin kanssa.

Kommentit

  • En ’ en seuraa pseudokoodiasi kovin hyvin, mutta ymmärrän huolesi. Olin luullut, että scoped_lock-toiminnon käyttäminen tekisi tämän ok ja että kukin vaatii sitä ’ s-mykistystä ehdolliseen odottamiseen.

Vastaus

Boost tarjoaa yhden tuottajan yhden kuluttajan jonon, joka on lukitsematon. Luuletteko, tiedätkö siitä? Mielestäni se sopii juuri sinun käyttötapaukseesi.

http://www.boost.org/doc/libs/1_61_0/doc/html/boost/lockfree/spsc_queue.html

Voit käyttää kiinteää kokoa ja olet estänyt kuluttajan, ellei tietoja ole käytettävissä jne. Ilman, että otat sitä itse käyttöön.

Kommentit

  • Tein huomaa tämän, mutta koneeltani (ei verkkoyhteydellä) näytti puuttuvan tästä. Uskon, että pop ja push toimivat samalla tavalla, estämättä palaavaa boolia, onnistuiko se vai ei.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *