2013-01-18 17 views
5

Jestem nowym użytkownikiem D i piszę prosty serwer wielowątkowy do ćwiczeń. Wspólnym paradygmatem do uruchamiania wątków obsługi klienta w C jest przekazanie deskryptora pliku gniazda new-accept() ed do pthread_create(), ale D's std.concurrency.spawn() nie pozwoli mi przekazać gniazda, ponieważ jest zmienne i dostępne przez dwa wątki.Aliasy do zmiennych lokalnych danych wątków niedozwolone

Oczywiście nie potrzebuję niezmiennego gniazda (dlatego tak naprawdę nie chcę go przesyłać w głównym wątku, chyba że muszę) - chcę przekazać zmienną i mieć ją wykracza poza zakres w głównym wątku. Jak bym to zrobił? Powinien (/ może) używać tid.send(s), aby wątek używał gniazda? Z jakiegoś powodu wydaje mi się to bardzo nieostrożne.

Mój kod teraz:

void main() { 
    Socket listener = new TcpSocket; 
    ... 
    for (;;) { 
     Socket s = listener.accept(); 
     scope(exit) s.close(); 

     auto tid = spawn(&clientHandler, s); 
    } 
} 

void clientHandler(Socket s) { 
    ... 
} 

która produkuje: Błąd: „Aliasy statyczne dochodzić do modyfikowalnych danych gwintów lokalnego niedozwolone.” ... utworzony stąd: spawn! (Socket)

Odpowiedz

6

trzeba rzucać gniazdo na wspólne iz powrotem w ClientHandler

auto tid = spawn(&clientHandler, cast(shared) s); 

void clientHandler(shared Socket s) { 
    Socket sock = cast(Socket)s; 
    scope(exit)sock.close(); 
} 

powodem tego jest to, że wszystkie zmienne lokalne są niejawnie wątku lokalny o ile nie podano shared, a jedynie odnośniki do wspólnego lub niezmiennej puszki zostać przekazany jako argument do spawn (lub send), podczas gdy rzeczy przekazywane przez wartość (kodowanym bez odniesień i prymitywów) jest w porządku

również należy umieścić blisko int obsługi jak z bieżącej realizacji gniazdo zostanie prawdopodobnie zamknięta przed newl y spawned wątek ma szansę uruchomić

+0

Działa doskonale, a dzięki za dodatkowe informacje! Czy to jest idiomatyczny sposób na zrobienie czegoś takiego, czy jest jakiś lepszy sposób? Casting in D wydaje się zdecydowanie, że robię coś złego (tj. W przeciwieństwie do C). – Dan

+0

@Dan ostatnio sprawdziłem (rok temu) semantyka "shared", gdzie nie jest dobrze zdefiniowana, nie wiem czy to się zmieniło od tego czasu –

+1

Nic się nie zmieniło w związku z tym. Ale cała społeczność D czeka, aż "wspólny" stanie się dobrze zdefiniowany. – DejanLekic

1

Problemem tutaj nie jest gniazdo, które jest zmienną lokalną. Jest to clientHandler, którego deklaracja nie została pokazana, ale wyraźnie jest to wątek-lokalny, jak mówi w komunikacie o błędzie, kiedy powinien być nowy na każdym zaakceptowanym gnieździe. Wskazówką jest słowo "alias", które odnosi się do operatora &.

+0

Przykro mi, wyjaśniłem pytanie, dodając deklarację 'clientHandler()'. Jest to funkcja zadeklarowana w globalnym zasięgu, więc być może jestem bardziej zdezorientowany, niż początkowo sądziłem, ale wątpię, czy jest to lokalne dane wątku. – Dan

+0

@ Dan Ok, więc co to jest? Nie gniazdo, chyba że scope() ma na to jakiś wpływ, cokolwiek to robi: nie jestem ekspertem. – EJP

+0

'scope (exit)' zapewnia, że ​​'s.close()' zostanie wywołane na końcu tego zakresu, podobnie jak słowo kluczowe "finally" w Javie. Prawdą jest, że nie ma sensu, gdzie go dodałem, ale usunięcie go lub umieszczenie go w innym miejscu nie ma wpływu na błąd kompilacji. Czytałem, że [zmienne globalne] (http://dlang.org/migrate-to-shared.html) są automatycznie konwertowane na locale wątków, ale to nie powinno mieć zastosowania do funkcji, w każdym razie zastępując alias funkcji (lokalne, myślę) wyrażenie lambda powoduje również ten sam błąd. – Dan