Welcome

This is the generic homepage (aka Aggregate Blog) for a Subtext community website. It aggregates posts from every blog installed in this server. To modify this page, edit the default.aspx page in your Subtext installation.

To learn more about the application, check out the Subtext Project Website.

Powered By:

Blog Stats

  • Blogs - 2
  • Posts - 13
  • Articles - 0
  • Comments - 721
  • Trackbacks - 0

Bloggers (posts, last update)

Latest Posts

[OT] Vi presento Alberto Melato

Ieri mattina 14 febbraio alle ore 8.56, a distanza di esattamente 2 anni dalla sorellina Claudia è nato Alberto, che, come la sorellina, pesa esattamente 3300g!

Alberto Melato

Un enorme grazie a mia moglie Erika che è riuscita nella titanica impresa di cullare nel pancione questo bambolotto per 9 mesi e nello stesso a tempo tenere a bada e a non far mai mancare una coccola e una carezza al mio diavoletto:

Claudia Melato

Auguro a tutti voi le mie stesse soddisfazioni.


Technorati Tags: ,

posted @ 2/15/2010 5:59 PM by Lorenzo Melato

Horn Web live!!!

E’ di qualche ora fa l’annuncio di Paul Cowan che la versione “live” di horn è online:

http://www.hornget.net/packages/

Se avete letto il mio post di qualche giorno fa sapete che horn è un software che permette di scaricare e installare in maniera totalmente automatizzata una svagonata di librerie e framework open source tra i più usati nel mondo .net.

Ora gli autori hanno fatto di più. Hanno messo a disposizione un sito che una volta al giorno si scarica tutti i sorgenti aggiornati dei pacchetti, li compila, e ce li mette a disposizione sotto forma di binari belli e pronti.

Complimenti a Paul e a tutti quelli che hanno collaborato a questa magia.

Technorati Tags:

posted @ 11/1/2009 10:54 PM by Lorenzo Melato

Rhino commons e il giardinaggio

Chi di voi utilizza in qualche progetto l’ottimo framework Rhino commons sa bene che il progetto è fermo da un po’ di mesi e che Rhino commons fa (faceva) parte dell’ottima suite di strumenti Rhino tools sviluppati nel corso degli anni dall’iperproduttivo Ayende.

Qualcuno probabilmente si sarà accorto scaricando il trunk di Rhino tools che allo stato attuale non è possibile compilare Rhino Commons perchè Ayende, da qualche settimana, sta rimettendo a posto la solution estrapolando tutti i vari progetti e spostandoli su github. Qui trovate l’elenco completo:

http://github.com/ayende

Fatto sta che a me Rhino Commons mi serve per un progetto e mi serve che giri con il trunk di Castle e con NHibernate 2.1ga.

Così, d’accordo con Paul Cowan, leader del progetto horn, di cui vi ho già parlato qui, ho deciso di fare un po’ di giardinaggio alla solution di Rhino Commons: l’ho estrapolato dalla gigantesca solution di Rhino tools, ho sostituito le dipendenze dai progetti con dipendenze ai binari e ho sostituito lo script di build originale di nant con un nuovo script di build basato su psake, come ha già fatto Ayende per tutti gli altri progetti di Rhino tools.

Il risultato lo trovate qui:

http://github.com/lorenzomelato/rhino-commons

il progetto compila e i test passano tutti quanti.

Attualmente il codice è quello della revisione r2200 del repository svn originale, ma conto sul mio poco tempo disponibile e sull’aiuto della community per sistemarlo in modo da farlo girare con il trunk di Castle e NHibernate 2.1.

Paul Cowan promette che a breve sarà possibile installare il “nuovo” Rhino Commons anche da Horn.

Technorati Tags: ,

posted @ 11/1/2009 10:45 PM by Lorenzo Melato

Training kit per VS2010 e .NET framework 4

Se a qualcuno fosse sfuggito, vi segnalo che qui potete scaricare il training kit per VS2010 e .NET framework 4.

Sono una serie di Hand-on-labs, presentazioni e demo su questi argomenti:

C# 4.0
Visual Basic 10
F#
Parallel Extensions
Windows Communication Foundation
Windows Workflow
Windows Presentation Foundation
ASP.NET 4
Windows 7
Entity Framework
ADO.NET Data Services
Managed Extensibility Framework
Visual Studio Team System

Ho visto che c’è qualcosa anche su ASP.NET MVC 2.

Technorati Tag: ,,

posted @ 10/21/2009 4:28 PM by Lorenzo Melato

Segnalazione di un nuovo, interessante blog

Finalmente il mio collega, nonchè caro amico, Roberto Penzo si è deciso ad aprire un blog dove esprimere le sue illuminate e romantiche idee sul “vivere il lavoro”.

L’abstract:

“Lavorare. Come passare questo tempo? Quali occasioni per viverlo bene? Pensieri su ciò che concentra tante attese e impegna così tanta vita. Luce su aspetti belli e a volte entusiasmanti di questa esperienza solitamente definita grigia.”

e il link:

http://thedrop-lagoccia.blogspot.com

Technorati Tags:

posted @ 10/16/2009 9:38 PM by Lorenzo Melato

[OT] Avere un buco nero in tasca

No, non è la condizione tipica di qualche amico particolarmente spendaccione…

Un gruppo di ricercatori di una università cinese è riuscito a creare un dischetto delle dimensioni di 8 pollici e mezzo in grado di assorbire tutte le radiazioni elettromagnetiche nel suo intorno.

Sembra che uno dei possibili scenari applicativi possa essere la costruzione di nuove celle solari particolarmente efficienti.

Speriamo che sia un passetto in avanti verso l’indipendenza dall’ oro nero.

Fonte: http://www.popsci.com/technology/article/2009-10/black-hole-fits-your-pocket

posted @ 10/16/2009 10:22 AM by Lorenzo Melato

Il mio primo sito web

Era il lontano 2000 quando insieme a Diego e agli amici di Padus realizzai il sito del ViaVai, un opuscolo/giornaletto settimanale con gli eventi/spettacoli/cinema della provincia di Rovigo.

image


Classic ASP e Access. Tutto qua.
Semplice e spartano fin che vuoi, ma pur sempre un cms completo di gestione dei banner pubblicitari era.

E dopo 9 anni è ancora li, a servire i suoi affezionati… ehhhh, son soddisfazioni!

E voi? qual’è stato il vostro primo sito web?

Technorati Tags: ,

posted @ 10/7/2009 10:28 PM by Lorenzo Melato

Horn: finirà l'incubo delle interdipendenze?


Qualcuno di voi si è mai trovato nella necessità di utilizzare nello stesso progetto Castle, NHibernate, Fluent NHibernate, Rhino tools, MVCContrib, ecc.?

Chiunque (e credo siano molti) si sia mai trovato in una situazione del genere sa bene a cosa il titolo del post si riferisce.
Tutti questi raffinati e fantastici strumenti hanno una serie di interdipendenze tali da rendere veramente difficile e tedioso l'aggiornarmento dei binari ad una nuova versione quando si ha la necessità di lavorare con l'intero stack di framework ALT.NET in un unico progetto.

L'obiettivo di Horn è di rendere estremamente semplici le operazioni di scaricamento e build dei framework open source di cui abbiamo bisogno nel nostro progetto. Si, ma semplici quanto?

Semplici quanto aprire la command line e digitare il comando seguente:

horn -install:nhibernate

questo(apparentemente) innoquo comando scatena una serie di operazioni tali che alla fine del processo ci si ritrova con una cartella da qualche parte con la build più recente (buildata dal trunk) di NHibernate completa anche delle librerie interdipendenti (anch'esse buildate dal proprio trunk).
Potrò, a questo punto, prendere i binari e copiarli nel mio progetto sicuro di non avere conflitti di versione tra le varie dipendenze.

Ma come funziona questa magia?


Horn introduce il concetto di build descriptor che altro non è che un file DSL scritto in boo che descrive da dove un determinato pacchetto deve essere scaricato (sono supportati svn e git), come il pacchetto deve essere buildato e quali sono le sue dipendenze.
Le dipendenze descritte puntano a loro volta al proprio build descriptor e possono quindi essere scaricate e buildate a loro volta.
In questo modo è possibile ottenere la build dell'intero albero di dipendenze del pacchetto desiderato.

Horn, di default, ha al suo interno una cartella package_tree che contiene i build descriptor della maggior parte (se non di tutti) dei framework e delle librerie più diffuse nella comunità .net. Ma è possibile costruire i propri build descriptor in maniera abbastanza semplice o contribuire al progetto inviando i build descriptor di librerie non ancora presenti nel package_tree.

image 

Come ottenere Horn?

Horn è hostato su google code qui: http://code.google.com/p/hornget/

E' possibile scaricare Horn con svn o TortoiseSVN da qui: http://hornget.googlecode.com/svn/trunk/

Una volta ottenuto il sorgente è possibile buildare horn in maniera molto semplice lanciando il comando hornbuild.bat nella cartella src.
Completato il build sarà possibile lanciare horn dalla cartella:

src\build\net-3.5\debug

e iniziare finalmente a buildare i nostri framework preferiti!

Horn è un progetto iniziato dal gruppo Scotland ALT.Net. Il progetto è tutt'altro che maturo (credo non sia ancora entrato nella sua fase beta) e la direzione di sviluppo futura è ancora incerta. Da questo post del suo autore sembra (speriamo) che horn sia destinato a diventare un bellissimo sito web in cui ogni build descriptor del package_tree diventa una pagina web dalla quale è possibile scaricare uno zip con i binari dell'ultima build disponibile. Certo, sarebbe un bel boost per la nostra produttività…

L'autore, nel suo ultimo post datato 17 Settembre 2009 chiede aiuto alla community per la manutenzione e lo sviluppo del progetto, lamentando la recente tendenza di molti project leader di cambiare scm passando da svn a git o altro. Infatti, ad oggi, molti build descriptor di horn non sono aggiornati ai recenti cambiamenti di scm, rendendo di fatto inutilizzabili gli stessi (per esempio rhino, mvccontrib, sharparchitecture passati di recente su github.com).

Vogliamo contribuire allo sviluppo di questo meraviglioso progetto?

Qualche link sparso sull'argomento:

http://jasondentler.com/blog/2009/08/first-impression-horn/
http://thesoftwaresimpleton.blogspot.com/2009/07/breaching-castle-walls.html
http://thesoftwaresimpleton.blogspot.com/2009/04/horn-package-manager-introduction.html


Technorati Tags: ,

posted @ 10/6/2009 9:59 PM by Lorenzo Melato

Problema in debug con Step Into e breakpoint in Visual Studio 2008 SP1

In questi giorni, per saziare la mia patologica curiosità, sto studiando i sorgenti di Castle, in particolar modo della parte di Ioc (Castle.Windsor e Castle.Microkernel).

Ho creato una piccola applicazione Web con ASP.NET MVC, ho preparato alcuni componenti di prova, ho preparato i file di configurazione, ecc… solite cose.

Poi ho scaricato una build di debug dell’intero stack di Castle e ho iniziato ad analizzarne i sorgenti e a colpi di debugger e Step into…

Tutto bene fino ad un certo punto del sorgente (sempre lo stesso), quando il debugger ha iniziato a dare di matto e il comando Step into e alcuni breakpoint hanno iniziato a non funzionare:

Metto il breakpoint, F5(Go), il debugger lo becca, F11(Step into) e niente… Step into mi salta a piè pari alcuni pezzi di sorgente e si ferma un po’ più avanti. Oltre a questo capita che alcuni breakpoint non vengano neanche considerati dal debugger.

Penso: “Non è che per caso i file binari non sono allineati con i file PDB o roba del genere?”. Riscarico tutto e riprovo. Stessa cosa.

Penso: “Non è che inavvertitamente (mmha…) ho cambiato qualche impostazione del debugger?”. Verifico e niente, tutto a posto.

Inizio a Googlare… e finalmente, dopo una mezzoretta trovo questo post nel forum di MSDN:

Visual Studio 2008 SP1 Stepping and Breakpoint Issues

che parla proprio di questo problema. In sostanza di tratterebbe di un bug che esce solo in situazioni molto particolari quando si lavora con codice multithread su macchine multi-core.

Prima di installare la patch indicata provo il workaround manuale. OK. Funziona.
Installo la patch indicata poco sotto tra i commenti:

http://code.msdn.microsoft.com/KB957912/Release/ProjectReleases.aspx?ReleaseId=1796

Posso continuare a studiare Castle.

Technorati Tags: ,,,

posted @ 9/6/2009 2:42 PM by Lorenzo Melato

File batch e sostituzione dei parametri


Ho pochissima esperienza con i vecchi batch file del dos ma mi rendo conto che sono spesso utilissimi per automatizzare piccoli (e grandi) task.

E’ possibile passare parametri a riga di comando ad un file batch come a qualsiasi altro eseguibile.

Il file batch può accedere ai parametri passati a riga di comando attraverso la sintassi:

%n

dove n è un numero che indica la posizione del parametro sulla riga di comando.

%0 si riferisce al comando batch stesso, da %1 in poi ci si riferisce ai suoi parametri.

E’ possibile applicare particolari “trasformazioni” ai parametri passati dette “sostituzioni”.
E’ possibile ottenere l’elenco delle sostituzioni con il comando:

call /?

Di seguito un riassunto delle sostituzioni possibili:

%~1 sostituisce il parametro %1 rimuovendo le virgolette;
%~f1 sostituisce il parametro %1 con il percorso completo;
%~d1 sostituisce il parametro %1 con la lettera di unità;
%~p1 sostituisce il parametro %1 con il solo percorso;
%~n1 sostituisce il parametro %1 con il nome del file;
%~x1 sostituisce il parametro %1 con la sola estensione del file;
%~s1 sostituisce il parametro %1 con i nomi brevi;
%~a1 sostituisce il parametro %1 con gli attributi del file;
%~t1 sostituisce il parametro %1 con la data e ora del file;
%~z1 sostituisce il parametro %1 con la dimensione del file;


E’ possibile combinare i modificatori per ottenere risultati composti, qualche esempio:

%~dp0 sostituisce il comando con la sua lettera di unità e il suo percorso;
%~dp1 sostituisce il primo parametro con la sua lettera di unità e il suo percorso;
%~nx0 estrae il nome del comando batch completo di estensione;
%~snx1 sostituisce il primo parametro con il nome nel formato breve;

Potete scaricare da qui un file batch di esempio che riassume le varie sostituzioni possibili.

Fonte: http://www.sgart.it/Page/default.asp?id=30&e=207

 

Technorati Tag: ,

posted @ 5/21/2009 8:57 PM by Lorenzo Melato

Il punto sul pattern Singleton


Proprio in questi giorni mi è capitato di leggere un interessante articolo sull'integrazione di NHibernate con ASP.NET (che trovate qui). Analizzando il codice allegato all'articolo in questione mi è caduto l'occhio su una particolare implementazione del pattern Singleton in C#. Tra i commenti, l'autore citava un link ad un articolo che avevo già letto di sfuggita un po' di tempo fa al quale solo ora sono riuscito a dare il peso che merita.

Ricalco di seguito qualche concetto e qualche riga di approfondimento, giusto a pro-memoria e per reference in italiano.

In sostanza un Singleton è una classe che permette la creazione di una singola istanza di se stessa (requisito di resource management [1]) e fornisce un unico, semplice accesso pubblico a detta istanza (requisito di accessibilità [1]).

Obiettivo del Singleton è spostare la responsabilità dell'esistenza di una ed una sola istanza di una determinata classe dallo sviluppatore alla classe stessa.

Un tipico requisito di un Singleton è che l'istanza non sia creata finché non ce ne sia reale necessità, che sia cioè "lazy-created".

Tutte le implementazioni del Singleton condividono alcune caratteristiche:

  • Un unico costruttore, privato e senza parametri. Per non permettere ad altre classi di instanziarlo direttamente e per non permetterne l'uso come classe base in una gerarchia di ereditarietà. Tipicamente il Singleton è sealed, anche se non servirebbe, per il motivo che abbiamo appena citato, ma sembra che segnare la classe sealed aiuti il compilatore a ottimizzare meglio [2];
  • Un campo statico che mantiene un riferimento alla singola istanza del Singleton;
  • Un metodo o una proprietà pubblici per ottenere il riferimento all'istanza del Singleton ed eventualmente crearla, se non ancora creata;

Vediamo di seguito qualche implementazione del pattern Singleton con un occhio di riguardo alla "thread-safety" e alla "lazyness", come consigliato in [2].

L’implementazione classica, non thread-safe:

   1: public sealed class Singleton1
   2: {
   3:     private static Singleton1 _instance = null;
   4:  
   5:     private Singleton1() { }
   6:  
   7:     public static Singleton1 Instance
   8:     {
   9:         get
  10:         {
  11:             if (_instance == null)
  12:             {
  13:                 _instance = new Singleton1();
  14:             }
  15:  
  16:             return _instance;
  17:         }
  18:     }
  19: }


L'implementazione proposta è la classica descritta in [3], semplicemente tradotta da C++ a C#.

La proprietà Instance alla riga 7 garantisce il requisito di accessibilità, è infatti l'unico punto di accesso pubblico all'istanza. Il codice all'interno della proprietà garantisce il requisito di resource management definito e cioè che esista una sola istanza della classe, il getter controlla infatti la preventiva esistenza dell'istanza e la crea solo ed esclusivamente se non è già stata creata, altrimenti restituisce l'istanza già esistente.

In uno scenario single-thread il codice in questione funziona ed è perfettamente legale. In scenari multi-thread iniziano i problemi... questa implementazione non è thread-safe, due o più thread potrebbero contemporaneamente valutare il test alla riga 11 come vero e creare più istanze della classe, violando il requisito di resource management.

Rigirando la frittata, anche se a mio parere non ci sono forti motivazioni (ad esempio straordinari aumenti di performance) per un approccio del genere, nel tipico caso di Singleton immutabile e nel caso in cui la costruzione del Singleton sia poco onerosa, è possibile chiudere un occhio riguardo la violazione del requisito di resource management, lasciando al garbage collector l'onore e l'onere di eliminare una eventuale "altra istanza" lasciata orfana di riferimento dalla fortuita costruzione di una seconda istanza e utilizzare, quindi, questa implementazione.

Un passo avanti, garantiamo la thread-safety

   1: public sealed class Singleton2
   2: {
   3:     private static Singleton2 _instance = null;
   4:  
   5:     private static readonly Object syncObject = new Object();
   6:     private Singleton2() { }
   7:  
   8:     public static Singleton2 Instance
   9:     {
  10:         get
  11:         {
  12:             lock (syncObject) 
  13:             {
  14:                 if (_instance == null)
  15:                 {
  16:                      _instance = new Singleton2();
  17:                 }
  18:  
  19:                 return _instance;
  20:             }
  21:         }
  22:     }
  23: }


L'implementazione è effettivamente thread-safe, due o più thread non possono accedere contemporaneamente alla sezione critica protetta dal lock, quindi solo il primo thread che entrerà nel lock potrà creare l'istanza del singleton.

Il codice soffre però un problema di performance, è infatti richiesto un lock per ogni richiesta dell'istanza, anche nel caso in cui l'istanza sia già stata creata.

Thread safety, lock, performance, volatile e MemoryBarrier()

   1: public sealed class Singleton3
   2: {
   3:     private static volatile Singleton3 _instance = null;
   4:     private static readonly Object syncObject = new Object();
   5:  
   6:     private Singleton3() { }
   7:  
   8:     public static Singleton3 Instance
   9:     {
  10:         get
  11:         {
  12:             if (_instance == null)
  13:             {
  14:                 lock (syncObject)
  15:                 {
  16:                     if (_instance == null)
  17:                     {
  18:                         _instance = new Singleton3();
  19:                     }
  20:                 }
  21:             }
  22:  
  23:             return _instance;
  24:         }
  25:     }
  26: }
  27:  

A differenza dell'esempio precedente, il lock viene eseguito solo la prima volta che viene richiesta l'istanza. Infatti l'if più esterno (alla riga 12) serve proprio a verificare che l'istanza sia già stata creata nel qual caso l'ingresso nel lock introdurrebbe solo un inutile overhead. Questa semplice modifica rispetto all'esempio precendente ha un chiaro impatto sulle performance, l'utilizzo di lock è utile in effetti solo nella fase iniziale in cui l'istanza non è ancora stata creata, quando cioè è indispensabile la sincronizzazione, e di conseguenza è un inutile spreco di tempo per tutto il resto del ciclo di vita del singleton in cui viene semplicemente restituita l'istanza già creata.

Merita particolare attenzione in questa implementazione l'utilizzo di volatile nella dichiarazione di _instance (riga 3)... ma prima di entrare nel merito forse vale la pena di ricordare le 3 regole fondamentali a cui i modelli di memoria (anche quello del .NET Framework) devono sottostare:

  • Una lettura o una scrittura da un determinato thread ad una determinata locazione di memoria non può essere spostata temporalmente più avanti di una scrittura dallo stesso thread alla stessa locazione;
  • Le letture non possono essere spostate temporalmente più indietro dell'acquisizione di un lock;
  • Le scritture non possono essere spostate temporalmente più avanti del rilascio di un lock;

Il modello di memoria del .NET Framework, oltre alle 3 regole citate, suddivide le tipologie di accesso alla memoria in "accessi ordinari" e "accessi volatile". Per gli accessi volatile sono definite le due regole seguenti:

  • Letture e scritture non possono essere spostate temporalmente più indietro di una lettura volatile;
  • Letture e scritture non possono essere spostate temporalmente più avanti di una scrittura volatile.

Conseguenza di queste regole è, di fatto, l'inibizione del riordino degli accessi alla memoria, una particolare ottimizzazione applicata dai compilatori e dalle CPU non x86 per ottimizzare l'esecuzione del codice.
Altra conseguenza è che viene forzato l'aggiornamento della variabile dichiarata volatile al valore più recente prima che questa venga applicata all'interno di un particolare contesto.

Ora... cosa sarebbe potuto succedere se _instance non fosse stata dichiarata volatile?

Dal punto di vista del rispetto dei requisiti di accessibilità e di resource management assolutamente niente. Infatti, il requisito di resource management è garantito dalla presenza del secondo check su _instance (riga 16) e dal rispetto da parte del memory model della seconda regola fondamentale. Si supponga di avere 2 thread:

  • Il thread 1 passa il primo if (riga 12), l'esecuzione viene interrotta e passa al thread 2;
  • Il thread 2 passa il primo if, entra nel lock, passa il secondo if e crea l'istanza;
  • Il thread 1 riprende l'esecuzione ed entra nel lock. La seconda regola fondamentale dei modelli di memoria dice che: "le letture non possono essere spostate temporalmente più indietro dell'acquisizione di un lock" e di conseguenza che _instance avrà sicuramente, a questo punto, l'ultimo valore pubblicato dal thread 2 prima di rilasciare il lock. L'if alla riga 16 verificherà che _instance è diverso da null e il thread 1 proseguirà l'esecuzione restituendo l'istanza precedentemente creata da thread 2.

In realtà, un problema subdolo si nasconde nel corpo dell'if alla riga 16 e precisamente nel codice che va a creare l'istanza di Singleton3... ed è proprio in questo caso che volatile ci viene in aiuto. Si supponga di avere il codice seguente:

   1: public sealed class Singleton3
   2: {
   3:     private static volatile Singleton3 _instance = null;
   4:     private static readonly Object syncObject = new Object();
   5:     private string _message;
   6:  
   7:     private Singleton3() { _message = "Hello World!"; }
   8:  
   9:     public static Singleton3 Instance
  10:     {
  11:         get
  12:         {
  13:             if (_instance == null)
  14:             {
  15:                 lock (syncObject)
  16:                 {
  17:                     if (_instance == null)
  18:                     {
  19:                         _instance = new Singleton3();
  20:                     }
  21:                 }
  22:             }
  23:             
  24:             return _instance;
  25:         }
  26:     }
  27: }


Su architetture IA64, che permettono il riordino delle scritture in memoria, potrebbe accadere che, all'interno del corpo dell'if alla riga 19, le scritture vengano riordinate in maniera tale che la scrittura di _message all'interno del costruttore possa essere spostata temporalmente più avanti della scrittura di _instance. La lettura di _instance (alla riga 13) non è protetta da lock, potrebbe quindi accadere che un secondo thread possa accedere all'istanza di Singleton3 prima che il costruttore abbia concluso l'inizializzazione.
L'utilizzo di volatile su _instance ci mette al riparo da questo problema in virtù della regola introdotta dal memory model del .NET Framework che dice: "Letture e scritture non possono essere spostate temporalmente più avanti di una scrittura volatile", garantendo, di conseguenza, la sequenzialità delle scritture nel blocco di costruzione dell'istanza, viene garantita la corretta inizializzazione di Singleton3 anche in scenari multi-thread.

L'implementazione precedente è thread-safe, è lazy-load ed è performante... ma possiamo fare ancora un pochino di più!

Quello che possiamo fare è rimuovere il modificatore volatile dalla dichiarazione di _instance e utilizzare una MemoryBarrier esplicita subito prima della pubblicazione dell'istanza di Singleton3 come nell'esempio seguente:

   1: public sealed class Singleton3
   2: {
   3:     private static Singleton3 _instance = null;
   4:     private static readonly Object syncObject = new Object();
   5:     private String _message;
   6:  
   7:     private Singleton3() { _message = "Hello World!"; }
   8:  
   9:     public static Singleton3 Instance
  10:     {
  11:         get
  12:         {
  13:             if (_instance == null)
  14:             {
  15:                 lock (syncObject)
  16:                 {
  17:                     if (_instance == null)
  18:                     {
  19:                         Singleton3 newValue = new Singleton3();
  20:                         System.Threading.Thread.MemoryBarrier();
  21:                         _instance = newValue;
  22:                     }
  23:                 }
  24:             }
  25:             
  26:             return _instance;
  27:         }
  28:     }
  29: }


Questo approccio è molto più efficiente dell'utilizzo del modificatore volatile perchè, in realtà, ogni scrittura o lettura volatile è una memory barrier! anche dove non ne abbiamo bisogno!
Nel nostro caso l'obiettivo è soltanto avere la sicurezza che le scritture all'interno del costruttore vengano eseguite prima della pubblicazione dell'istanza agli altri thread (e processori). MemoryBarrier() ci assicura che "nessuna scrittura possa essere spostata temporalmente più avanti della chiamata a MemoryBarrier()" e ci permette quindi di garantire la consistenza dell'istanza risparmiando la dichiazione volatile di _instance.


E se utilizziamo il .NET Framework 2.0?

Con l'introduzione del .NET Framework 2.0 il modello di memoria è stato riveduto e corretto al fine si supportare gli sviluppatori nel passaggio alle nuove architetture IA64. Rimangono buone tutte le precedenti regole e alcune di nuove sono state introdotte tra cui una in particolare:

  • Le scritture non possono essere spostate temporalmente più avanti di altre scritture dallo stesso thread.

Questa regola ci permette di evitare sia la dichiarazione volatile di _instance sia la chamata a MemoryBarrier(), risolvendo a livello di memory model la corretta serializzazione delle scritture del costruttore rispetto alla pubblicazione dell'istanza.

Thread safe senza lock. Lazyness (con riserva)

   1: public sealed class Singleton4
   2: {
   3:     private static readonly Singleton4 _instance = new Singleton4();
   4:     
   5:     private static Singleton4() { }
   6:     
   7:     private Singleton4() { }
   8:     
   9:     public static Singleton4 Instance
  10:     {
  11:         get
  12:         {
  13:             return _instance;
  14:         }
  15:     }
  16: }


Il singleton dell'esempio qui sopra è thread-safe e lazy-created (con riserva).

La lazyness è supportata da una funzionalità del CLR che garantisce che il type initializer venga eseguito "prima" dell'accesso ad un qualsiasi membro statico della classe. Nel nostro caso, subito prima del primo accesso alla proprietà statica Instance, il type initializer verrà eseguito e il campo statico _instance verrà inizializzato con una istanza di Singleton4. Il type initializer verrà eseguito però anche nel caso si acceda ad un qualsiasi altro campo o proprietà statica denifito nella classe violando (da qui la riserva), di fatto, la lazyness di Instance... Attenzione! potrebbe non essere il comportamento desiderato in fase di design.

Altra importante questione riguardante la lazyness di Singleton4 è la presenza del costruttore statico (riga 5, costruttore esplicito). La presenza del costruttore esplicito garantisce che la classe non venga decorata con il flag beforefieldinit in fase di compilazione. Il flag beforefiledinit abilita il runtime ad ottimizzare l'esecuzione del type initializer scegliendo autonomamente il momento migliore per eseguirlo, garantendone comunque l'esecuzione prima dell'accesso ad un qualunque campo statico della classe. Noi non abbiamo quindi modo di determinare precisamente il momento in cui il type initializer viene eseguito, di conseguenza la lazyness è violata. Senza il flag beforefieldinit il runtime DEVE eseguire il type initializer immediatamente prima dell'accesso ad un qualunque campo statico della classe [6].

La thread safety è supportata da una specifica del CLR che garantisce il fatto che il type initializer venga eseguito una ed una sola volta, anche in ambienti multithreaded. Il runtime, infatti, acquisisce un lock PRIMA di eseguire il type initializer, rendendo l'inizializzazione di _instance sincronizzata [6].

Thread safe senza lock. Lazy-created (garantito)

   1: class Singleton5
   2: {
   3:     private Singleton5() { }
   4:     
   5:     public static Singleton5 Instance
   6:     {
   7:         get
   8:         {
   9:             return Nested._instance;
  10:         }
  11:     }
  12:  
  13:     class Nested
  14:     {
  15:         static Nested() { }
  16:         
  17:         internal static readonly Singleton5 _instance = new Singleton5();
  18:     }
  19: }


Il singleton dell'esempio qui sopra è thread-safe (vedi le stesse motivazioni del precedente esempio) e lazy-created in ogni circostanza.

La lazyness è infatti garantita dal fatto che il type initializer di _instance viene eseguito solo ed esclusivamente prima del primo accesso ai membri statici della classe Nested (che può essere fatto solo dallo stesso Singleton5), costruita solo per questo scopo e invisibile all'esterno di Singleton5. L'accesso ad una qualsiasi altro membro statico di Singleton5 non influenza l'inizializzazione di _instance.

Note

Nel caso di decida di utilizzare l'implementazione Singleton4 o Singleton5 bisogna fare particolarmente attenzione alla particolare gestione delle eccezioni dei type initializer statici:

  • Qualsiasi eccezione sollevata all'interno del costruttore statico viene automaticamente wrappata da una eccezione di tipo TypeInitializationException, l'eccezione originale è comunque disponibile attraverso la proprietà InnerException di TypeInitializationException;
  • Il runtime, nel caso venga sollevata una eccezione nel costruttore statico, non tenterà di invocare una seconda volta il costruttore statico, rendendo, probabilmente, la stessa eccezione fatale per l'intera applicazione [6].

Potete scaricare i sorgenti d'esempio del post qui.

Bibliografia

[1] Adrian Florea - L'individuazione via reflection delle classi singleton all'interno del Framework .NET
[2] Jon Skeet - Implementing the Singleton Pattern in C#
[3] Gamma, Helm, Johnson, Vlissides - Design Patters, Elementi per il riuso di software a oggetti
[4] Alessandro Marotta Rizzo - Implementare Singleton con Volatile
[5] Eric Gunnerson - A programmer's introduction to C# 2.0
[6] K. Scott Allen -  Get a Charge From Statics with Seven Essential Programming Tips
[7] Microsoft -  ECMA C# and Common Language Infrastructure Standards
[8] Vance Morrison -  Understand the Impact of Low-Lock Techniques in Multithreaded Apps

 

posted @ 5/9/2009 4:52 PM by Lorenzo Melato

Visualizzare linee guida nell’editor di testo di Visual Studio

 

Interessante funzionalità di Visual Studio, presente fin dalla versione 2002, della quale non ero a conoscenza, ma molto molto comoda... E' possibile visualizzare una o più guideline nell'editor di testo di Visual Studio aggiungendo una semplice stringa ad una chiave di registro, chissà poi perchè non l'hanno messa tra le opzioni dell'editor...

Aprite regedit e navigate alla chiave seguente:

[HKEY_CURRENT_USER]\Software\Microsoft\VisualStudio\9.0\Text Editor

create ora una nuova stringa REG_SZ e chiamatela Guides, doppio click sulla stringa appena creata e aggiungete:

RGB(230,230,230) 80, 120

con RGB(...) si sceglie il colore della o delle linee. 80 e 120 aggiungono 2 guidelines rispettivamente alla colonna 80 e 120 dell'editor di testo.

Un consiglio, scegliete un colore molto chiaro (se lo sfondo è bianco) o comunque un colore poco aggressivo.

 

Technorati Tag:

posted @ 5/9/2009 3:34 PM by Lorenzo Melato

Guardare al passato per capire il presente e il futuro

 

Qualche tempo fa un collega mi ha passato questo link che con piacere pubblico:

http://www.cs.rit.edu/~ats/books/ooc.pdf

Si tratta di un libro rilasciato gratuitamente dall'autore che nei diversi capitoli spiega come simulare i costrutti tipici della OOP in ANSI C.

Molte delle tecniche descritte sono secondo me molto difficili da contestualizzare in un progetto reale, a meno che non si sviluppi firmware su microcontrollori comunque "ben dotati", o forse driver a bassissimo livello.

Da un altro punto di vista la lettura di questo libro può risultare secondo me molto utile a chi sta studiano l'OOP e vuole approfondire "cosa sono" a basso livello classi, ereditrietà, polimorfismo e tutto quello che ormai i moderni linguaggi ci nascondono (per fortuna) sempre di più.

Forse dare uno sguardo a come sono fatte le cose "sui transistor" ci potrebbe anche aiutare a sviluppare meglio il nostro software a oggetti? o no?

 

Technorati Tag: ,

posted @ 5/9/2009 3:27 PM by Lorenzo Melato

Latest Images