Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Singleton, Static o privada

Iniciado por bnl, 29 de Agosto de 2007, 11:00:05 PM

« anterior - próximo »

Vicente

Cita de: "ethernet"La razón es que no creo que ganes en tiempo de ejecución y sí en claridad. Habría que ver como funciona el tema del multihread (ya sabemos lo escabroso que son los threads y los singletones).

Lo de que ganas en claridad es relativo. Puedo entender que ganes en claridad para alguien que sea programador de C++ o Java y cuando mire el código C# se diga: y esto del readonly ein? Pero para alguien de C# no se aplica (además que si buscas singleton c# esa es la forma recomendada en toooooooodos los lados).

Y segundo que sin el readonly y poniendo los ifs te toca hacer un lock (el ejemplo 2 del singleton del link que puso Vincent). Y los locks son caros...

No sé, que valor le ves a no hacerlo así además del "artístico" (que ya te digo que me parece discutible por eso, porque es algo de estilo).

Un saludo!

Vicente

vincent

Duda que me ha surgido leyendo todo esto: que diferencia hay entre instanciar una variable en la declaración y hacerla en el constructor?

Lo digo también por el comentario de las clases estáticas que ha hecho Vicente...

Gracias!
Desarrollo en .Net y metodologías http://devnettips.blogspot.com

ethernet

dos puntos:

1.- he dicho que prefiero mil veces lo implícito a lo explícito siempre y cuando la funcionalidad sea la misma y el trabajo sea razonablemente el mismo. Si vas a tener que hacer doble lock y usar 50 volatiles es mejor usar lo que te aporte C#

2.- SI quieres leer un buen paper de singleton en un lenguaje para hombres lo mejor es leerte este :
http://erdani.org/publications/DDJ_Jul_Aug_2004_revised.pdf

bnl

No conocia esa implementación para C#, es interesante.

Vicente en tu ejemplo no seria instanciacion no perezosa. Por lo que he entendido la variable se instancia al inicio, antes de que se puedan lanzar los hilos. Perezosa seria el ejemplo que puso Strat ¿no?
Mi web: http://www.brausoft.com/
No sabían que era imposible, así que lo hicieron.

Vicente

Vamos a ver un poco como va la cosa en detalle, el código es este:


public sealed class Singleton
{

  private static readonly Singleton singleton =
     new Singleton();  // eager

  static Singleton() {}

  private Singleton() {}

  public static Singleton GetInstance()
  {
     return singleton;
  }
}


Ahora nos vamos a las especificaciones de C# y tenemos estas cosas:

Citar
ECMA 334, 17.11:
The static constructor for a class executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain:

-An instance of the class is created.
-Any of the static members of the class are referenced.

Esto significa que el constructor estático (Type Initializer) es thread-safe porque solo puede ejecutarse 1 vez.

Citar
ECMA 335, 8.9.5:
1- A type may have a type-initializer method, or not.
2- A type may be specified as having a relaxed semantic for its type-initializer method (for convenience below, we call this relaxed semantic BeforeFieldInit)
3- If marked BeforeFieldInit then the type's initializer method is executed at, or sometime before, first access to any static field defined for that type
4- If not marked BeforeFieldInit then that type's initializer method is executed at (i.e., is triggered by):
- first access to any static or instance field of that type, or
- rst invocation of any static, instance or virtual method of that type

Los tipos que tienen un constructor estático explícito no se marcan como BeforeFieldInit, con lo cual el Type Initializer solo se dispara cuando se accede a una campo estático o de instancia o se invoca un método (el punto 4).

Ahora, si una clase tiene inicializadores en variables estáticas y un constructor estático explícito al ejecutar el Type Initializer se insertan las llamadas a las variables en el orden que están declaradas en la clase al comienzo del constructor (con lo que nuestro new queda protegido por el Type Initializer).

Sin el constructor estático explícito el código podría ser más o menos lazy. Por un lado, sin el constructor el Type Initializer se puede invocar antes de hacer cualquier acceso, con lo cual incluso se podría invocar y que no se use el singleton para nada (en este caso sería más lazy con el constructor porque solo se invoca si se usa).

Pero por otro lado con el constructor estático y el new en la variable si el singleton tuviera más variables o métodos y alguien accediera a ellos se dispararía la construcción del singleton (mientras que si lo metemos en el GetInstance no), con lo cual sería menos lazy (pero con el GetInstance nos toca hacer el lock a nosotros).

Ale, un saludo!

Vicente

Vicente

Por cierto la MSDN te deja una frase muy buena ethernet :p

Citar
One of the reasons Design Patterns [Gamma95] avoided static initialization is because the C++ specification left some ambiguity around the initialization order of static variables. Fortunately, the .NET Framework resolves this ambiguity through its handling of variable initialization.

Un saludo!

Vicente

ethernet

Cita de: "Vicente"Por cierto la MSDN te deja una frase muy buena ethernet :p

Citar
One of the reasons Design Patterns [Gamma95] avoided static initialization is because the C++ specification left some ambiguity around the initialization order of static variables. Fortunately, the .NET Framework resolves this ambiguity through its handling of variable initialization.

Un saludo!

Vicente

Y qué va a decir Microsoft? traducción libre: "hasta ahora teníamos al pobre C++ que está mal definido, menos mal que ha llegado .NET para hacernos ver la luz".

Aparte, como te digo, prefiero tener lo sigueinte:


       SplineManager::manager->Init();
MeshManager::meshManager->Init();
TextureManager::textureManager->Init();
GLTextureManager::manager ->Init();
ShaderManager::shaderManager->Init();
ProgramManager::programManager->Init();
MaterialManager::manager->Init();
CameraManager::manager ->Init();
ObjectManager::objectManager->Init();
PassManager::manager->Init();


que en el fondo son "singletones" y se ve clarísimamente lo que está haciendo y en qué orden lo estás iniciando, sepas C++, C, C#, java o lo que sea a tener 10 ficheros con 10 cosas donde no tienes una visión de lo que pasa en la aplicación o donde necesites saber una característica propia de un lenguaje para ""adivinar"" el funcionamiento.

No es precisamente el uso de singletones lo que hace a la gente dejar de usar C++ para pasarse a otros lenguajes de más alto nivel (lease java, C#, python, etc)

Vicente

Cita de: "ethernet"
Y qué va a decir Microsoft? traducción libre: "hasta ahora teníamos al pobre C++ que está mal definido, menos mal que ha llegado .NET para hacernos ver la luz".

Joder que mal pensado eres tio. Yo la frase entiendo de otra forma, más o menos como: "si en C++ la inicialización de variables estáticas estuviera clara el patrón singleton sería como el que hemos hecho en C# en vez de esa cosa con los ifs".

Traduciendo: para el autor usar static es superior a usar ifs, pero no dice que C++ es una basura, simplemente que en C++ no se puede hacer así...

Y yo me pregunto: si en C++ se pudiera hacer con el static (teniendo en cuenta la ventaja que nos da en el tema del lock) ¿tienes alguna razón técnica para elegir los ifs que no sea "me gusta más esta forma de hacerlo porque yo lo veo más claro así"?

(estaría bien que si alguien tiene el libro que citan vea si hablan de esto en el singleton)

Cita de: "ethernet"
Aparte, como te digo, prefiero tener lo sigueinte:


       SplineManager::manager->Init();
MeshManager::meshManager->Init();
TextureManager::textureManager->Init();
GLTextureManager::manager ->Init();
ShaderManager::shaderManager->Init();
ProgramManager::programManager->Init();
MaterialManager::manager->Init();
CameraManager::manager ->Init();
ObjectManager::objectManager->Init();
PassManager::manager->Init();


que en el fondo son "singletones" y se ve clarísimamente lo que está haciendo y en qué orden lo estás iniciando, sepas C++, C, C#, java o lo que sea a tener 10 ficheros con 10 cosas donde no tienes una visión de lo que pasa en la aplicación o donde necesites saber una característica propia de un lenguaje para ""adivinar"" el funcionamiento.

No es precisamente el uso de singletones lo que hace a la gente dejar de usar C++ para pasarse a otros lenguajes de más alto nivel (lease java, C#, python, etc)

Ese método Init es totalmente diferente a lo que estamos hablando en este post. Lo que estábamos viendo es que Tipo.Instancia inicializa el objeto singleton pero que ese proceso internamente se puede hacer de diferentes maneras. Que tu quieres que para inicializar el singleton haya que usar un método llamado Init pues muy bien, pero no aporta nada al tema.

Un saludo!

Vicente

ethernet

@vicente: lo de la frase era una coña.

Citar
Ese método Init es totalmente diferente a lo que estamos hablando en este post. Lo que estábamos viendo es que Tipo.Instancia inicializa el objeto singleton pero que ese proceso internamente se puede hacer de diferentes maneras. Que tu quieres que para inicializar el singleton haya que usar un método llamado Init pues muy bien, pero no aporta nada al tema.

Lo que llevo diciendo todo el post: yo no hablo de si C# es muy super chulo por tener 14 formas de iniciar una variable, yo digo que perdiendote en caracterísitcas propias de un lenguaje no ganas nada. De ahí el último ejemplo que hace referencia a la frase de microsoft. Ellos dicen que C++ el control de los contrcutores de los static es ambiguo, bien, pero es que si necesitas control sobre eso no se lo voy a dejar a una caracterísitca del lenguaje, prefiero hacerlo explícito.

Vicente

Cita de: "ethernet"@vicente: lo de la frase era una coña.

Mejor que lo aclararas ;)

Cita de: "ethernet"
Lo que llevo diciendo todo el post: yo no hablo de si C# es muy super chulo por tener 14 formas de iniciar una variable, yo digo que perdiendote en caracterísitcas propias de un lenguaje no ganas nada. De ahí el último ejemplo que hace referencia a la frase de microsoft. Ellos dicen que C++ el control de los contrcutores de los static es ambiguo, bien, pero es que si necesitas control sobre eso no se lo voy a dejar a una caracterísitca del lenguaje, prefiero hacerlo explícito.

Ganas un lock respecto a las otras implementaciones clásicas de C# y dos respecto a la de C++ (según me dijiste tú por el IRC, que yo no tengo ni idea de como implementáis singletones en C++).

Esto es muy sencillo: tu escribes el mejor singleton que tu lenguaje es capaz de ofrecerte y yo hago lo mismo. Escribir una cosa peor (porque es peor, ya te digo que cuentes locks) para que la entienda alguien que ni siquiera trabaja con C# es una razón de peso negativo.

Cuando escribes código lo haces basándote en parte en como funciona el lenguaje, en sus normas, sus virtudes y sus defectos. Si C++ no te especifica como funcionan las static pues lógicamente lo especificas tú, pero C# si que lo hace y no entiendo porque tendría que limitarme a la visión del C++ si programo en C# (y porque aplicar semejante "favoritismo" a este caso y no a todos). C# no es un subconjunto ni un superconjunto de C++ y el que se parezcan mucho no me parece razón para justificar la vaguería de no molestarse en aprender como funciona y usarlo lo mejor posible.

Pero vamos, que eso es cosa de gustos. Lo que no es cosa de gustos es que te ahorras los locks y a eso sigues sin responder :p

Un saludo!

Vicente

ethernet

Con respecto al tema de los locks: ni puta idea de los locks que hace C# (ya dije hace unos cuantos post que en el tema de threads no entraba). Para implementar un singleton MT en C++ ya puse el paper ese y si lo lees al final te dice que es un putiferio y que pilles la instancia al singleton solo una vez al comienzo del thread para evitar locks innecesarios.

En cualquier caso siendo C# un lenguaje de alto nivel, que en teoría simplica las cosas, no pondría la mano en el fuego por las cosas que hace internamente para dar esa simplicidad. Solo espero que lo haga un poco mejor que java.

Vicente

Tio, te he copiado la especificación entera del tema tres posts más arriba, y el resultado es que para ser un singleton MT-safe en C# hacen falta CERO LOCKS :p

Cero patatero y 4 líneas de código, más fácil es complicado hacer las cosas... Un saludo!

Vicente

ethernet

Cita de: "Vicente"Tio, te he copiado la especificación entera del tema tres posts más arriba, y el resultado es que para ser un singleton MT-safe en C# hacen falta CERO LOCKS :p

Cero patatero y 4 líneas de código, más fácil es complicado hacer las cosas... Un saludo!

Vicente

CERO locks Explícitos !!

Prompt

Joder como os rayais con los singletons :D hahahaha pobrecito el bnl.

Mirad yo opino que usar el patrón singleton es un hack tipo patron para no hacer algo estatico pero que cumple la misma función.

Yo te digo bnl que no uses ni singleton ni static, si tienes un diseño bueno no te hará falta ningún hack patrón ni nada estático.

Haz un buen diseño. De todas formas, explicame para que quieres que "EngineRender" sea un singleton ? porque yo lo veo inncesario. Que pasaría si quisieras tener 2 viewport con configuraciones diferentes? gestionarias toda esa logica con el singleton engorronandolo al infinito? :)

No hacks señores! No hacks! :P y dejad de discutir y criticar al probre señor singleton! es un tramposo.

Vicente

A ver ethernet: si ese lock implícito por la llamada al Type Initializer que comentas existe, existe SIEMPRE, da igual como escriba yo mi singleton o que la clase sea en realidad un singleton o una clase normal y corriente.

Partiendo de que tienes razón y ese lock implícito existe, ¿que gano haciendo yo otro lock más de regalo que no vale para nada? ¿Hacer las cosas mal para quedar bien con los programadores de Java y C++?

Esto es como si en C++ como hay destructores me dedico a llamar yo a mano a los destructores de C#. Pues no: hay un Garbage Collector y en C# se encarga él de destruir los objetos, aunque en C++ las cosas no funcionen igual. Y aquí lo mismo: los inicializadores estáticos son thread-safe y si no lo quieres aprovechar tu mismo, pero no tiene sentido no hacerlo porque otro lenguaje no lo hace...

Un saludo!

Vicente

P.D.: ya te confirmaré si ese lock existe, estoy investigando.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.