|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
ancora classi e DLL :P
allora, vi espongo quello che dovrei fare: ho sempre la solita serie di classi implementate in una DLL, tra cui ce n'è una che la logica suggerirebbe di implementare parzialmente nella DLL e parzialmente nell'eseguibile. questa classe si chiama CResource; ecco quella che per ora ne è la dichiarazione:
Codice:
class CResource {
public:
virtual ~CResource() = 0;
virtual void LockRead() = 0;
virtual void UnlockRead() = 0;
virtual void LockWrite() = 0;
virtual void UnlockWrite() = 0;
virtual COUNTER GetCounter(unsigned int uCode) = 0;
virtual void SetCounter(unsigned int uCode, COUNTER value) = 0;
};
come forse avrete capito, i primi 4 metodi servono ad effettuare la mutua esclusione della risorsa; a dire il vero non è proprio mutua: nel server ci sono numerosi thread che possono lavorarci o in lettura o in scrittura; quando ci lavorano in lettura devono usare LockRead/UnlockRead, quando in scrittura LockWrite/UnlockWrite. In tal modo è possibile che più thread possano leggere contemporaneamente la risorsa, ma uno solo può scriverla, e se un thread la sta scrivendo nessun altro può leggerla (dicono che fosse un tipico problema di concorrenza; io ci ho sbattuto parecchio la testa... attualmente il design che ho applicato sarebbe questo: i metodi devono essere implementati tutti quanti dalla DLL, però ho anche esportato dall'exe delle implementazioni predefinite dei metodi Lock/Unlock che la DLL è formalmente obbligata a chiamare. ora però il problema è che per realizzare le implementazioni predefinite ho bisogno di due mutex per ogni risorsa, 8 bytes associati ad ogni oggetto CResource... come faccio a fare in modo che la DLL istanzi anche questi 8 bytes negli oggetti CResource? devo metterli come variabili membro? si può fare? grazie a chiunque risponda ^^' |
|
|
|
|
|
#2 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
dimenticavo: poi questi 8 bytes dovrebbero anche essere inizializzati...
e il problema è che l'oggetto viene costruito dalla DLL, non dall'exe... quantomeno dovrebbero essere inizializzati a 0, ma così il design inizierebbe ad essere un po' debole... come posso risolvere? si accettano anche idee per altri designs thx ^^ |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
L'unico modo che mi viene in mente è farli static... Non c'è altro modo a meno di instanziare la classe nelal DLL...cosa che non puoi fare perchè è astratta...
Ultima modifica di cionci : 30-07-2005 alle 09:35. |
|
|
|
|
|
#4 | |
|
Senior Member
Iscritto dal: Jul 2004
Città: Napoli
Messaggi: 2029
|
Quote:
te non puoi instanziare una classe astratta pura |
|
|
|
|
|
|
#5 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
ma io (come dissi nell'altro thread) non devo mai istanziare CResource: devo istanziare le sue implementazioni fornite dalla DLL, ovvero classi derivate da CResource; l'eseguibile non sa neanche quali siano queste classi, che sono interne alla DLL, usa solo CResource come interfaccia comune.
cmq cos'è che dovrei fare static? le variabili membro o i metodi Lock/Unlock? |
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Oct 2002
Città: San Jose, California
Messaggi: 11794
|
Quote:
In genere e' buona norma dare ad una classe una e una sola responsabilita', altrimenti sorgono problemi come il tuo. Prova a separare i quattro metodi di lock in una classe (Lock, ad esempio) e vedi se ne esci cosi'. Vado a occhio: Codice:
class Lock
{
virtual void Lock...
static Create(...); // Factory method (se ti serve)
};
class Resouce
{
virtual void AssignLock(Lock* lock);
virtual COUNTER Get...
virtual void Set...
};
__________________
"We in the game industry are lucky enough to be able to create our visions" @ NVIDIA Ultima modifica di fek : 30-07-2005 alle 10:36. |
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Sia le variabili membro che i metodi che accedono ai membri statici...
Per l'inzializzazzione basta fare all'interno della DLL: CResource::membro = 0; |
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: May 2000
Messaggi: 1459
|
Domanda stupida: ma xkè nn può usare i due mutex come membri dato della classe? Li dichiari come membri dato, e fai 1 funzione InitMutexes(HANDLE h1,HANDLE h2) che deve essere chiamato a carico dell'eseguibile. Tutto IMHO ovviamente...
Quote:
ciauz
|
|
|
|
|
|
|
#9 | ||
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
Quote:
dici che viene troppo incasinato se CResource derivasse da CLock, considerando che CLock viene implementata dall'eseguibile e CResource dalla DLL?
|
||
|
|
|
|
|
#10 | |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
|
|
|
|
|
|
|
#11 | |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
|
|
|
|
|
|
|
#12 | |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
|
|
|
|
|
|
|
#13 | ||
|
Senior Member
Iscritto dal: Oct 2002
Città: San Jose, California
Messaggi: 11794
|
Quote:
Quote:
Non puoi derivare l'una dall'altra, devi ragionare in termini di interfacce e composizione qui. Mi sembra che la Composizione si adatti meglio all'Ereditarieta' nel tuo problema. Ho bisogno di sapere: - Chi crea gli oggetti CLock e CResource - Chi implementa le interfacce - Il ciclo di vita dei due oggetti E poi risolviamo il problema di assegnare un CLock ad un CResource e chi deve farlo. Male che vada puoi avere un factory method di CResource che assegna sempre il Clock e non puoi dimenticarlo; io di solito risolvo questo tipo di problemi cosi'.
__________________
"We in the game industry are lucky enough to be able to create our visions" @ NVIDIA |
||
|
|
|
|
|
#14 |
|
Senior Member
Iscritto dal: May 2000
Messaggi: 1459
|
Qui credo nn ci sia problema: I mutex servono a tutte le classi derivate da CResource, x cui basta dichiararli (mutex e funzione) nella classe astratta e definire il metodo CreateMutexes(...) come metodo concreto public, accessibile anke quindi da tutte le classi derivate. Più che altro nn so se si può creare qualke casino con gli HANDLE dei mutex tra DLL/eseguibile, ma nn credo cmq...
|
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quello che mi sto domandando è: ma esisteranno diverse istanze della mutex o solo una... Nel senso: tutti i tuoi utilizzatori useranno una sola mutex o hai bisogno di una istanza per ogni produttore/consumatore ?
|
|
|
|
|
|
#16 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
Comunque mi ero dimenticato il tipo: tipo CResource::membro_static = 0; Questa è considerata a tutti gli effetti una inizializzazione... |
|
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: May 2000
Messaggi: 1459
|
ogni risorsa dovrebbe avere i suoi mutex. Ai thread passi un puntatore alla risorsa, x cui tutti i thread condividerebbero lo stesso oggetto (mi sono appena alzato, quindi se dico qualke cretinata nn mi linciate
ciauz |
|
|
|
|
|
#18 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
|
|
|
|
|
|
|
#19 |
|
Senior Member
Iscritto dal: May 2000
Messaggi: 1459
|
si, scusa,avevo frainteso il tuo post
|
|
|
|
|
|
#20 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
servono due mutex per ciascun oggetto, e ora mi sono anche ricordato che oltre agli handle dei mutex servono pure un intero e un flag (diciamo altri 8 bytes); qui sotto vi riporto la versione Java della classe CResource: prima di fare la versione C++ di questo programma avevo iniziato la versione Java, poi sono cambiate le direttive provenienti dall'alto (
Codice:
import java.lang.*;
import java.io.*;
public class Resource extends Object implements Serializable {
public int nID;
private static int nNextID = 1;
public Counters counters = null;
private int nReaders = 0;
private boolean fLocked = false;
private Object lock1 = new Object(), lock2 = new Object();
private static int getNewID() {
return nNextID++;
}
public Resource() {
nID = getNewID();
counters = new Counters();
}
public Resource(Counters counters) {
nID = getNewID();
try {
this.counters = (Counters)counters.clone();
}
catch (CloneNotSupportedException e) {
this.counters = counters;
}
}
// lock for read when a resource must be consistent during a read process
public void lockRead() {
synchronized (lock1) {
synchronized (lock2) {
nReaders++;
while (fLocked);
}
}
}
public void unlockRead() {
synchronized (lock1) {
if (nReaders > 0) {
nReaders--;
}
}
}
// lock for write when the consistency of a resource might change during a
// write process
public void lockWrite() {
synchronized (lock2) {
while (fLocked);
fLocked = true;
while (0 != nReaders);
}
}
public void unlockWrite() {
fLocked = false;
}
}
PS: ma ancora non capisco: queste variabili membro, cioè i due handles, l'intero e il flag, potrebbero essere messe direttamente come mebri di CResource, che è una classe astratta? se no, perché? volevo sapere il vostro parere su questo punto prima di sperimentare direttamente... |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 01:20.











ciauz








