2009-08-26 30 views
9

Dla implementacji new_handler specyficznej dla klasy, natknąłem się na następujący przykład w książce "effective C++". Ten problem wygląda w środowisku wielowątkowym, moje pytanie brzmi: jak osiągnąć new_handler specyficzny dla klasy w środowisku wielowątkowym?przy użyciu klasy specyficznej set_new_handler

void * X::operator new(size_t size) 
{ 
    new_handler globalHandler =    // install X's 
    std::set_new_handler(currentHandler); // handler 
    void *memory; 
    try {          // attempt 
     memory = ::operator new(size);   // allocation 
    } 
    catch (std::bad_alloc&) {     // restore 
     std::set_new_handler(globalHandler);  // handler; 
     throw;         // propagate 
    }           // exception 
    std::set_new_handler(globalHandler);  // restore 
               // handler 
    return memory; 
} 

Odpowiedz

4

Masz rację. Prawdopodobnie nie jest to bezpieczne dla wątków. Może warto rozważyć alternatywne podejście jak przy użyciu nothrow version of new zamiast:

void* X::operator new(std::size_t sz) { 
    void *p; 
    while ((p = ::operator new(sz, std::nothrow) == NULL) { 
    X::new_handler(); 
    } 
    return p; 
} 

Spowoduje to Twoja klasa obsługi specyficznych nazywać gdy alokacja pamięci zakończy się niepowodzeniem. Nie zrobiłbym tego, dopóki naprawdę nie zrozumiesz wszystkich bólów głowy związanych z przeciążaniem się: operator new. W szczególności przeczytaj artykuł dwuczęściowy autorstwa Olivera Suttera: To New, Perchance To Throw, Part 1 oraz Part 2. Co ciekawe, mówi, aby uniknąć wersji nothrow ... hmmm.

0

C++ nie (jeszcze) wie, jakie są wątki. Musisz przejść do podręczników do biblioteki standardowej/biblioteki systemu operacyjnego/biblioteki wątków w C++, aby ustalić bezpieczny sposób na wątek lub nawet jeśli jest to możliwe. Sugerowałbym, aby nowy program obsługi prawdopodobnie był taki sam w całej aplikacji. Nie jest to bardzo elastyczny mechanizm, być może twoje potrzeby będą lepiej obsłużone przy użyciu alokatora lub fabryki (funkcji)? Co chcesz zrobić w niestandardowym nowym programie obsługi?

0

Być może patrzysz na to w niewłaściwy sposób. Nie sądzę, że istnieje jakikolwiek sposób ograniczenia całej aplikacji do przydzielania pamięci (ponieważ duża część alokacji pamięci może znajdować się poza twoim kodem), więc najlepszym sposobem na zrobienie tego byłoby kontrolowanie tego, co możesz - tj. Implementacja obsługi.

Skonfiguruj program obsługi wywołujący instancję klasy "OutOfMemoryHandler" (wywołaj to, co chcesz) na początku programu i zachowaj ją domyślnie, aby wywoływać istniejący moduł obsługi. Aby dodać obsługę specyficzną dla klasy, dodaj zachowanie do OutOfMemoryHandler, używając ulubionych technik C++ do dynamicznego zachowania.

To rozwiązanie powinno działać dobrze w środowisku jednowątkowym, ale zawiedzie w środowisku wielowątkowym. Aby działał w środowisku wielowątkowym, musisz wywoływać powiadomienie obiektu obsługi, że działa on w określonym wątku; przekazanie identyfikatora wątku z klasą byłoby dobrym sposobem na zrobienie tego. Jeśli wywoływana jest procedura obsługi, to sprawdza identyfikator wątku i określa zachowanie do wykonania na podstawie powiązanej klasy. Kiedy wywołanie new() zostanie zakończone, po prostu wyrejestruj identyfikator wątku, aby zapewnić prawidłowe domyślne zachowanie (podobnie jak w przypadku resetowania domyślnej procedury obsługi).

Powiązane problemy