2010-04-03 20 views
5

Ho scritto una DLL multi-thread per l'accesso al database utilizzando ADO/ODBC per l'utilizzo con un'applicazione legacy. Ho bisogno di mantenere più connessioni al database per ogni thread, quindi ho messo gli oggetti ADO per ogni connessione in un oggetto e sto pensando di mantenerne una matrice all'interno di un oggetto threadInfo personalizzato. Ovviamente un vettore servirebbe meglio qui - ho bisogno di cancellare/riorganizzare gli oggetti in movimento e un vettore lo semplificherebbe. Il problema è che sto allocando un heap per ogni thread per evitare conflitti e problemi di heap e allocare tutta la mia memoria da lì.Inserimento di un vettore C++ come membro in una classe che utilizza un pool di memoria

Quindi la mia domanda è: come faccio ad allocare il vettore dall'heap specifico del thread? (O saprebbe internamente di allocare memoria dallo stesso heap della sua classe di wrapper - sembra improbabile, ma io non sono un ragazzo C++) Ho cercato un po 'su google e sembra che potrei aver bisogno di scrivere un allocatore o qualcosa del genere - che sembra così tanto lavoro che non voglio C'è un altro modo? Ho sentito che il vettore usa il posizionamento - nuovo per tutte le sue cose all'interno, quindi può essere utilizzato da un operatore di overloading?

La mia scarsa conoscenza degli interni di C++ non aiuta, visto che sono principalmente un programmatore C (anche quello - relativamente). È molto probabile che mi manchi qualcosa di elementare da qualche parte. Se non succede nulla di più semplice - potrei semplicemente andare a fare la cosa dell'array, ma spero che non arriverà a quello.

Sto usando MS-VC++ 6.0 (ehi, è scortese ridere! :-P).

Qualsiasi/tutto l'aiuto sarà molto apprezzato.

risposta

3

Come si assegna il vettore dall'heap specifico del thread?

Si passa (in fase di compilazione) un allocatore appropriato. Here è un classico su come farlo. Se segui il consiglio di quell'articolo (o anche solo copia il codice e adattalo dove necessario), per un programmatore C scrivere un allocatore potrebbe essere più facile che ottenere la semantica della copia di una classe con una matrice allocata dinamicamente.

Si noti che, se si inseriscono oggetti nel vettore (o nel proprio array, FTM), che utilizzano essi stessi l'heap (stringhe, ad esempio), è necessario considerare che utilizzino anche l'heap speciale. Per i contenitori della libreria standard (std::basic_string<> è un contenitore di questo tipo) è facile dato che è possibile passare anche l'allocatore. Per i tuoi stessi tipi devi renderlo sicuro.

E cercare di allontanarsi da VC6 il più velocemente possibile. È velenoso.

+0

Sì, ci avrei pensato prima. Francamente hanno iniziato con "non usare questo per sovraccaricare nuovo [] ... non c'è motivo di usare un allocatore in un normale codice" e questo mi ha messo fuori gioco. Controllandolo di nuovo, ora. Gli oggetti nel vettore utilizzeranno l'heap specifico, sì. Mi sono già assicurato di questo. Non conoscevo il template di basic_string, quindi grazie! (Anche se a parte il vettore sono stato attento a mantenere tutti i membri come primitivi.) Nel frattempo, in attesa di vedere se arriva un'altra risposta! –

+0

@ Deep-B: Immagino che dover mettere un oggetto su un heap speciale non contenga più il "codice normale", quindi non è un argomento nel tuo caso. ':)' Come per le stringhe in C++: C'è una stringa typedef basic_string (all'interno di namspace 'std', o course) nell'intestazione' 'della libreria standard. 'std :: basic_string' ha altri due parametri di modello che sono predefiniti a' std :: char_traits 'e' std :: allocator '. Se si 'typedef std :: basic_string , my_allocator > my_string_type' si ha qualcosa di simile a' std :: string', ma si utilizza il proprio heap. – sbi

0

Consulti __declspec

Il codice seguente dichiara una variabile locale filettatura intera e inizializza con un valore:

__declspec(thread) int tls_i = 1; 

In un'altra nota. Non è una buona idea mantenere aperte le connessioni ADO per un lungo periodo. Avrai molti problemi con la connettività db. Appariranno aperti all'applicazione. Tuttavia, bombarderanno con un messaggio "Errore di rete generale" quando invii una query.

È preferibile chiudere la connessione il prima possibile tramite l'app e fare affidamento sul pool di connessioni gestito dal sistema operativo.

Inoltre, a seconda del numero di client che si connettono al db, è possibile che venga raggiunto il numero massimo di socket aperti sul lato server. Questo è dalla memoria.Una volta che una connessione viene chiusa sul lato client, la connessione sul server entra in uno stato TIME_WAIT. Per impostazione predefinita, il socket del server impiega circa 4 minuti per chiudersi, quindi non è disponibile per altri client durante tale periodo. La linea di fondo è che c'è un numero limitato di socket disponibili sul server. Mantenere troppe connessioni aperte può creare un problema.

Scusa, ho avuto modo di parlarvi.

+0

Spiacente, non posso usare che - __declspec è: 1> rotto per OS prima di Vista (Vista effettivamente FISSO qualcosa? !!!!); 2> non riesce (UB, penso) se si richiamano le funzioni dll tramite LoadLibrary(). Ho già deciso di utilizzare gli indici TLS dopo alcune ricerche su questo. ... E non sono sicuro di come questa risposta sia pertinente, visto che sto parlando di un oggetto ... ma grazie comunque. –

+0

Mi spiace, intendevo __declspec (thread), non __declspec. Ovviamente. : P –

+0

Hm, purtroppo quella (la durata della connessione) non è nelle mie mani. La dll fornisce all'interfaccia legacy un'interfaccia per l'attivazione di query su database che non ha altro modo di contattare. Potrei mettere il tuo consiglio nelle FAQ di utilizzo - per i ragazzi che in realtà stanno andando a codificare i programmi del chiamante. Grazie per le informazioni sui tempi. Sembra che ho bisogno di fare qualche ricerca in più ... così come testare la DLL sotto un carico davvero pesante una volta finito ... –

Problemi correlati