ott 11

Il C++ e il Multithreading (C++0X – C++11)

Un’altra funzionalità molto interessante introdotta nel C++0X oltre le lambda descritte nell’articolo precedente è il supporto nativo al multithreading.

Esistevano già librerie che si occupavano di multithreading in cpp ma adesso è integrato nel linguaggio e nella sua libreria standard anche se il backend che effettivamente alloca i thread è l’onnipresente libreria pthread.
Cominciamo allora :) do per scontato che abbiate un minimo di familiarità con la programmazione concorrente e come al solito i particolari per la compilazione ( che stavolta potrebbe essere più complicata del solito) sono alla fine dell’articolo

Allochiamo il nostro primo thread

Un thread è un qualcosa che viene eseguito in parallelo, e quindi si crea attraverso una funzione che è quello che deve fare, non è necessario creare una classe intorno al thread come si farebbe in java, basta passare al costruttore di thread la funzione che deve eseguire il thread costruito o qualcosa di equivalente

#include <iostream>
#include <thread>
#include <cstdlib>

using namespace std;

void cosadafare(){
 cout<<"Sono una procedura!"<<endl;
}

class Dummy
{
public :
 void operator()()
 {
 for(int a=0;a<5;a++){
 cout<<"Sono un oggetto, e quindi più figo di una procedura! "<< a <<endl;
 usleep( 1000 * ( rand() % 900 + 100 ));
 }
 }
};

void uccidimi(){
 for(int a=0;a<50;a++){
 cout<<"Io parlo troppo "<< a <<endl;
 usleep( 1000 * ( rand() % 900 + 100 ));
 }
}

int main()
{
 Dummy w;
 std::thread t1(w);
 std::thread t2(cosadafare);
 std::thread t3(uccidimi);

 t1.join();
 t2.join();
 t3.detach();
};

Cpp è un linguaggio marcatamente OOP e infatti non è necessario passargli una procedura, basta qualunque ogetto supporti l’operatore (), possiamo anche creare una classe che definisce questo operatore e passarne un istanza.

E’ interessante notare che quando si chiama un thread su un oggetto, come nel caso di std::thread t1(w), non gli viene passato il vero oggetto ma una sua copia, ma di questo ne parliamo dopo.

Le join servono ad aspettare che i thread finiscono prima di terminare il programma, infatti i thread sono concettualmente ‘figli’ del processo padre ( il fatto che lo siano veramente dipende dall’implementazione) e se terminasse il processo padre i figli verrebbero terminati di conseguenza facendo generare a linux un allarmante messaggio di warning, per terminare un thread prima che abbia finito il suo lavoro si usa detach

Thread e condivisione dei dati

Uno dei vantaggi dei thread rispetto ai processi è che condividono lo spazio di memoria tra di loro, tutto quello che è nello spazio di indirizzamento del processo padre può essere passato ai figli.

Quindi risulta molto conveniente piazzare dentro un oggetto la procedura del thread e i dati in cui dovrà lavorare ma c’è un inconveniente: come dicevamo sopra
quando si chiama un thread su un oggetto, come nel caso di std::thread t1(w), non gli viene passato il vero oggetto ma una sua copia , questo è irrilevante nel caso di oggetti che wrappano solo una procedura ma può essere una fonte di bug subdoli nel caso essi contengano dati infatti modificando l’oggetto non modifichiamo niente all’interno del thread perché sono oggetti diversi

se vogliamo evitare questo comportamento dobbiamo forzare un passaggio via reference e non abbiamo modo di farlo col linguaggio, dobbiamo affidarci alla magia nera delle stl,la soluzione è: std::thread t1(std::ref(dw));

Vediamo un esempio

#include <iostream>
#include <thread>
#include <cstdlib>
#include <string>

using namespace std;

class Dummy
{
public :

 string testo;
 string nome;
 void operator()()
 {
 for(int a=0;a<15;a++){
 cout<<nome << " dice: " << testo<< " " << a <<endl;
 usleep( 1000 * ( rand() % 900 + 100 ));
 }
 }
};

int main()
{
 Dummy w,w2;
 w.testo="ammaccabanane";
 w.nome="thread1";
 w2=w;
 w2.nome="thread2";
 std::thread t1(w);
 std::thread t2(std::ref(w2));
 sleep(2);
 w.testo="Yikes!";
 w2.testo="Yikes!";
 t1.join();
 t2.join();
};

Eseguendolo noterete che il comportamento del primo thread resta invariato, mentre possiamo agire sul secondo modificando i suoi dati dall’esterno.

E se volessi passare parametri alla procedura e magari non usare un oggetto?

Malgrado la soluzione di un oggetto di wrapper può tornare utile il passare dei parametri alla procedura chiamante, il che ci permette anche di non usare completamente un oggetto e di passare tutti i dati su cui deve lavorare il thread alla funzione che ne costituisce il main, vediamo come funziona

#include <iostream>
#include <thread>
#include <cstdlib>
#include <string>

using namespace std;

void stampa(string cosa, string altracosa){
 for(int a=0;a<10;a++){
 cout<< cosa << altracosa << endl;
 sleep(1);
 }
}

int main()
{
 std::thread t1(stampa, "bla bla bla", " yada yada yada");
 t1.join();
};

semplicemente accodiamo i parametri da passare alla funzione e ci affidiamo alle stl per la determinazione corretta del tipo ( la sintassi per gli argomenti multipli esisteva già, ma è stata migliorata, se siete curiosi leggete qui )

e per concludere passiamo alle questioni pratiche

L’ambiente utilizzato

Per l’ambiente utilizzato valgono le considerazioni fatte nel post precedente più qualcos’altro:
le funzioni lambda del C++0X sono incluse nei compilatori GNU a partire dalla 4.5 mentre la maggior parte dei sistemi linux attualmente in circolazione usa la 4.3, questa volta però non possiamo aggirare il problema installandocci  MinGW da windows, infatti sorgono altri problemi, i phread.
La libreria dei thread appena destritta usa pthread per creare e gestire i thread, e l’implementazione della libreria per windows non include pthread, quindi questa volta ci serve una vera Linux con un vero gcc ( oppure un implementazione commerciale per windows tipo questa che però non ho verificato, se qualcuno lo fa può scrivere sui commenti come funziona e se funziona e se ne vale la pena)

  • Anche lavorando con la 4.5 di default il compilatore non accetta la nuova sintassi, bisogna specificare come flag al g++ -std=c++0x
  • Inoltre bisogna aggiungere -lpthread per usare la lib dei pthread
  • se continua a non funzionare bisogna installare verificate che sia installato anche gcc-multilib
  • se ancora continua a non funzionare e vi da errori del tipo fatal error: asm/errno.h allora l’installatore non ha fatto il suo dovere e dovete correggere a mano il nome di una cartella:

andate su /usr/include/ e controllate che esista la cartella asm-generic, se esiste fatene un link software su /usr/include/asm (NON rinominatela, non si sa mai che può succedere con un aggiornamento di pacchetti ) se non esiste e non avete ancora risolto… mi dispiace ma non so che dirvi, non sono partito da un sistema vergine e quindi non ho verificato tutte le necessità del programma… scrivetemi nei commenti e cerchiamo una soluzione.

E per questo articolo è tutto, continuerò la prossima volta parlando della gestione delle risorse condivise e degli strumenti di sincronizzazione, la parte più divertente deve ancora arrivare :)
Leggi il resto »

Share Button

giu 14

Una classe Java per effettuare il backup di un database Mysql (v 2.0)

Quando si sviluppa un applicazione che permette di interagire e modificare un database può essere utile prevedere una funzione che permetta di effettuare velocemente e con un solo click il backup completo dell’intero database (dati, struttura, trigger e stored procedure).

Questa classe fa esattamente questo, e a differenza dei molti snippet che si trovano sul web è completa e autosufficente e documentata con javadoc, necessita soltanto della presenza nel sistema del comando “mysqldump” (presenza che viene verificata dalla classe stessa).

La classe avvia un istanza di mysqldump e permette di salvarne l’output in dei file di testo ,in un unico file zip o eventualmente in una stringa

A differenza della versione precedente ( descritta qui )  questa versione permette di importare/esportare anche tabelle che hanno vincoli di integrità relazionale.
Per fare questo disabilita il check delle Costraint , esegue l’intera importazione all’interno di una transazione, e poi le riattiva.
Questo comportamento può essere attivato con checkConstraint=false
Il comportamento di default è identico alla versione precedente

il file può essere scaricato da QUI

vediamo un esempio di utilizzo:

package cavia;

import darshan.util.MysqlBackup;
public class Main {

 public static void main(String[] args) {
 MysqlBackup b= new MysqlBackup("127.0.0.1", "3306", "root", "root", "darshan");
 b.checkConstraint=false;
 b.all_to_zip("/home/darshan/Scrivania/post/dump.zip");
 System.out.println("Done");
 }

la classe viene istanziata con MysqlBackup(ip, porta, user, password, database) , poi con b.checkConstraint=false; disabilito il check delle costraint e con all_to_zip eseguo il dump in un file zip, per le altre funzioni affidatevi al javadoc che trovate anche qui
Leggi il resto »

Share Button

apr 27

Tutoraggio per le 6 discipline scoglio di Ingegneria (unipa)

EDIT 21/05/11:

Il senato accademico non si è ancora riunito, i corsi slitteranno a settembre

Vagando per le segreterie, cercando di risolvere una cosa che non sono poi riuscito a risolvere mi sono ritrovato al cuc e ho chiesto dei corsi di tutoraggio, mi hanno indicato questo interessante foglio appeso al muro:

AVVISO DISCIPLINE SCOGLIO:

In seguito ad una indagine – eseguita dal COT – sono state individuate le sei discipline “scoglio” della nostra facoltà. Le materie maggiormente soggette al problema del mancato superamento sono le seguenti:

  • Elettrotecnica
  • Scienze delle costruzioni
  • Calcolo II
  • Fisica II
  • Controlli Automatici
  • Geotecnica.

Saranno, dunque, organizzati sei corsi di recupero – uno per ogni materia – con una durata che dovrebbe definirsi tra le 40 e le 60 ore. Tali corsi dovrebbero svolgersi prima dell’estate dell’anno corrente e – probabilmente – ripetersi all’inizio del prossimo a.a.

E’ una cosa di cui si vociferava da tempo, dei corsi tenuti da dei tutor che fanno sia il corso che l’esame esautorando di fatto quei professori la cui stronz… ehm… il cui eccessivo rigore è stato comprovato statisticamente.

Le materie sono uniche per tutta ingegneria e molte sono comuni a più corsi ( Calcolo2 ~= Analisi2 ) . I corsi sono riservati ai fuoricorso

Il manifesto non aveva un aria particolarmente ufficiale quindi invito chi sapesse qualcosa di più preciso di scriverla come commento all’articolo.

Noterete tralaltro la parola “probabilmente” che rende tutto più simile a un amnistia o al gioco d’azzardo… direi che è un’occasione che va sfruttata

Share Button

mar 28

Non perdete troppo tempo a fare la tesi…

Una catasta di tesi vista alla facoltà di lettere di Palermo durante una laurea… è stato illuminante

Share Button

mar 24

il C++ e le lambda ( C++0X – C++11)

Un interessante funzione introdotta nello standard C++0X sono le lambda

Le funzioni lambda sono tipiche dei linguaggi che applicano il paradigma della programmazione funzionale ( completamente o in maniera ibrida) e permettono di trattare le funzioni come se fossero oggetti, potendole quindi definire in qualunque punto del codice e assegnare a una variabile.

Vediamo un esempio di come questo approccio sia stato implementato nel cpp ( se non riesci a compilare il codice vai alla fine dell’articolo)

Il caso più semplice, le funzioni void

#include <iostream>

using namespace std;

auto lambda=[](){
    cout << "Questa e' una lambda" << endl;
};

int main()
{
    auto lambda2=[](){
        cout << "Una lambda puo' essere definita
anche dentro un altra funzione" << endl;
    };

    cout << "Hello world!" << endl;
    lambda();
    lambda2();
    return 0;
}

come si vede dal codice abbiamo definito due funzioni lambda assegnandole a variabili, adesso vediamo come comportarsi per definire funzioni che usano o producono valori (queste qui erano void->void)

Le funzioni che usano e restituiscono parametri

int main()
{
    auto somma=[](int a, int b) {
        return (a+b);
    };

    auto prodotto=[](int a, int b) -> int {
        return (a+b);
    };

    cout << " 2+2 fa " << somma(2,2) << endl;
    cout << " 2*2 fa " << prodotto(2,2) << endl;

    return 0;
}

la lista dei parametri in entrata viene dichiarata tra le parentesi tonde, il tipo del parametro in uscita può essere definito esplicitamente con -> come nel caso di prodotto o lasciato implicito come nel caso di somma e in questo caso viene dedotto dal compilatore

A questo punto vi starete chiedendo a che servano le parentesi quadre suppongo

Le funzioni lambda e la visibilità

La programmazione a oggetti ci ha abituato al concetto di visibilità di una variabile, per esempio una funzione definita dentro una classe accede agli oggetti della classe, ma una lambda che può essere definita in qualunque punto del codice a cosa può accedere? la risposta è: assolutamente a nulla se si vuole fare in modo che qualcosa venga visto dall’interno di una lambda bisogna passare il suo reference tra le quadre, vediamo un esempio

int main()
{
int c;
auto somma=[](int a, int b) {
c=a+b;
};

...

la compilazione del pezzo di codice precedente ci darà un error: ‘c’ is not captured per renderlo visibile dobbiamo fare questo

int main()
{
    int c;
    auto somma=[&c](int a, int b) {
        c=a+b;
    };

    somma(2,2);
    cout << " 2+2 fa " << c << endl;

    return 0;
}

quindi passando un puntatore a this a una lambda rendiamo visibile l’intero oggetto.

è addirittura possibile passare l’intero contesto usando [&] e [=] dove la prima passa per reference e la seconda per valore

Funzioni che ricevono funzioni e funzioni anonime

Una caratteristica fondamentale della programmazione funzionale è la possibilità di passare funzioni ad altre funzioni, in questo caso però la sintassi del cpp è un po sporca e siamo costretti ad usare la libreria functional perché non è interamente possibile farlo direttamente usando solo il linguaggio e le sue keyword, ci servirà la classe generica function<tipouscita (tipiingresso)>

#include <iostream>
#include <fstream>
#include <functional>

using namespace std;

int main()
{
    int c;
    char* filename="dati.txt";
    auto scrivisomma=[&](int a, int b, const function<void (int)>& writer) {
        c=a+b;
        writer(c);
    };

    auto scrittore=[=](int x){
        ofstream myfile;
        myfile.open (filename);
        myfile << x << " \n";
        myfile.close();
    };

    scrivisomma(2,2,scrittore);
    scrivisomma(2,2,[](int x){cout << x << endl;});

    return 0;
}

nell’esempio possiamo notare che è anche possibile definire una funzione e passarla senza assegnarla a una variabile, la funzione resta quindi anonima

Possiamo inoltre vedere come sia possibile modificare il comportamento di una fuzione dal suo esterno passandogli un altra funzione, infatti nel primo caso scrivisomma scrive sullo stdout mentre nel secondo su file

Qualche esempio funzionale ( che funziona)

Adesso cerchiamo di inventarci qualcosa che sia comodo da realizzare con la programmazione funzionale e scomodo con quella procedurale…
Abbiamo visto il caso precedente di una funzione che si aspetta un’altra funzione da utilizzare per scrivere i dati. Un altro uso molto diffuso delle lambda ci permette di modificare il comportamento di un algoritmo passandogli un altro algoritmo, un semplice esempio è una generica funzione di ordinamento a cui passiamo una funzione di confronto, questo ci permette sia di ordinare ogetti di tipi non conosciuti dalla funzione e non ordinabili a priori sia di modificare le relazioni di ordine

#include <iostream>
#include <fstream>
#include <functional>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

using namespace std;

void insertion_sort(void* x[], int n, const function<int (void*,void*)>& comparator) {
  int i, j;
  void* app;

  for (i=1; i<n; i++) {
    app = x[i];
    j = i-1;
    while (j>=0 && comparator(x[j],app)>0) {
      x[j+1] = x[j];
      j--;
    }
    x[j+1] = app;
  }
  return;
}

int main()
{
    srand ( time(0) );
    int c;
    char* cosi[]={"pollo di gomma","ammaccabanane","coso","cannuccia sbirula"};

    auto ordinastr=[](void *a, void *b)->int {
        return strlen((const char*)a)-strlen((const char*)b);
        };

    auto disordinastr=[](void *a, void *b)->int {return rand()%6-3;};

    insertion_sort((void**)cosi,4,ordinastr);
    for(int n=0;n<4;n++)cout << cosi[n] << endl;

    cout<<endl<<endl;

    insertion_sort((void**)cosi,4,disordinastr);
    for(int n=0;n<4;n++)cout << cosi[n] << endl;

    return 0;
}

la prima ordina in base alla lunghezza, la seconda disordina.

(un esempio più interessante sarebbe un thread generico che permetta di eseguire in background una funzione che passiamo come paramentro, ma dei thread ne voglio parlare separatamente)

e per concludere passiamo alle questioni pratiche

L’ambiente utilizzato

le funzioni lambda del C++0X sono incluse nei compilatori GNU a partire dalla 4.5 mentre la maggior parte dei sistemi linux attualmente in circolazione usa la 4.3, per evitare di incasinare il mio linux che è uno di questi ho deciso di installarmi la 4.5 sotto windows con MinGW

Anche lavorando con la 4.5 di default il compilatore non accetta la nuova sintassi, bisogna specificare come flag al g++ -std=c++0x

E per questo articolo è tutto, continuerò la prossima volta parlando del supporto ai thread
Leggi il resto »

Share Button

feb 24

Il C++ non è ancora morto ( C++11 )

Uno dei linguaggi che ho visto più maltrattare all’Università e di conseguenza poi da molti (sedicenti e/o futuri) ingegneri del software che hanno fatto il grave errore di accettare acriticamente le illazioni dei professori è il C++ (un mio professore ne aveva quasi terrore… )

Michele Sciabarrà anni fa scrisse in un suo post veramente geniale:

C++

Livello di complessità: ESAGERATO. Per impararlo ci metti metà della tua vita. E poi impieghi l’altra metà a convincere gli altri a impararlo, perché devi giustificare a te stesso PERCHE’ hai perduto metà della tua vita.

Credi di fare una cosa, e invece ne fai un’altra. La stessa cosa, in un caso significa una cosa e in un altro significa un’altra. Senza contare che la stessa cosa per un compilatore significa una cosa, per un altro c’è un bug che la fa diventare un’altra, e in un altro ancora non è supportata. E non abbiamo ancora considerato i template.

Ora, Sciabarrà scherzava ma cpp si dicono molte cose cattive…la maggior parte delle quali secondo me derivano da un confronto inappropriato e stupido con Java, si dice prima di tutto che

Il C++ è troppo complicato! nessuno lo conosce per intero!

Il cpp non è complicato, è vasto. L’idea che un linguaggio vada imparato e usato per intero è tipica dei linguaggi di nuova generazione come il Java, ma non è assolutamente una cosa necessaria in genere. Il cpp parte dal principio che se è possibile fare una cosa il linguaggio deve permetterlo, se poi i 4 tipi di cast o l’ereditarietà multipla ti fanno orrore o paura… non usarli!
Resta il fatto che siano utili e comodi per fare workaround, e i workaround servono ( nel mondo reale almeno) e anche fare cose orribili come modificare le variabili dichiarate costanti può tornare utile.

un altra idea ancora più stupida ma comunque abbastanza in voga e che:

La libreria del C++ è scarna!

Confondere la libreria di un linguaggio con il linguaggio è veramente stupido! anche dare per assunto che un linguaggio necessiti di una libreria intrinseca lo è. e comunque le stl e la libreria standard offrono un set di funzionalità che copre tutte le necessità di base, e per il resto se ne trovano a palate di librerie pronte.

E adesso veniamo al vero motivo per cui sto scrivendo

Lo standard C++0X

Dicevo che c++ non è morto e si continua ad evolvere, il suo ultimo standard non è quello del 1998 che tutti conoscono ( o dicono di conoscere), nel 2008 è stato sviluppato una nuova versione del linguaggio  che è attualmente in corso di approvazione da parte dell ISO e dovrebbe diventare uno standard entro quest’anno.

La nuova versione introduce molte nuove funzionalità, sia nel linguaggio che nella sua libreria standard tra cui le più importanti sono il supporto alla programmazione funzionale ( delegate e lambda function) e al multithreading con l’inclusione nelle stl di un interfaccia completa ai pthread ( e chi abbia mai lavorato con quei cosi sa quanto sia prolissa attualmente la loro gestione). per i particolari rimando alla pagina di wikipedia e ai link ai documenti ufficiali alla fine

Leggi il resto »

Share Button

feb 22

Decadenza studenti fuoricorso all’università di Palermo

EDIT 04/02/2012

Buone notizie: il consiglio di stato ha dichiarato illegale un decreto molto simile a questo, si tratta dell’università di Cagliari ma un precedente e un precedente, con un ricorso al tar si potrebbe far bocciare anche questa follia palermitana, con buona pace di La Galla e il suo progetto di far abbassare il numero dei fuoricorso costringendoli ad abbandonare o a reiscriversi. ma in ogni caso ancora non si sa nulla di certo invito gli eventuali visitatori di questa pagina a seguire gli eventi su vivereingegneria, io non sono più direttamente interessato alla cosa, sono tra quelli che si sono reiscritti in un altra facoltà
http://www.vivereingegneria.com/blog/?p=2687

Segue l’articolo originale:

Un interessante peggiorativo dello scoprire di essere fottuti è il fatto che te lo dicano sorridendo, salutandoti con “Caro studente” e dicendoti infine che è tutto per il tuo bene, fatto “al solo fine di adottare tutte le iniziative rivolte ad agevolare la conclusione dei percorsi formativi antecedenti la riforma del 2004″

Quando poi, chiaramente, di agevolazione non c’è nulla. Si tratta solo di produrre nuove matricole per avere nuovi fondi andando a colpire i fuoricorso che già pagano un sacco di soldi per non seguire le lezioni e fare solo gli esami ( dove peraltro da quest’anno devo pure portarmi la carta da casa perché non hanno i soldi per comprarla)

Riepilogando dovrei laurearmi entro un anno ( impossibile) oppure reimmatricolarmi al nuovo corso perdendo sicuramente alcune materie ma non figurando più come fuoricorso… mmm, mi aiuta tantissimo, migliora la mia posizione, la mia motivazione… bravi, geniale!

teste di cazzo

riporto la parte interessante del documento che mi è arrivato stamattina per email da parte del magnifico

intanto la paternale introduzione con tanto di rassicurazione in grassetto:

al solo fine di adottare tutte le iniziative rivolte ad agevolare la conclusione dei percorsi formativi antecedenti la riforma del 2004 (Vecchio ordinamento e D.M. 509/99).

Lo scopo é quindi, innanzitutto, dare regole certe, e note per tempo, agli studenti che si trovano già in una condizione di`rischio decadenza” e mettere in atto, poi, dei provvedimenti di orientamento e di tutorato finalizzati sia al recupero dei fuori corso sia all’incentivazione della conclusione del loro percorso.

è poi la parte effettivamente utile

La delibera del Senato Accademico distingue i seguenti quattro casi:

a) Gli studenti appartenenti al vecchio ordinamento (A.A. di immatricolazione antecedente il 2001/2002) e quelli all’ordinamento D.M. 509/99 che si sono immatricolati a partire dall’A.A. 2001/2002 devono portare a conclusione il loro curriculum (cioè devono sostenere tutti gli esami previsti nel loro piano di studi escluso l’esame finale) entro la sessione straordinaria dell’A.A. 2012/2013 (marzo 2014);

b) Gli studenti che negli anni accademici 2008/2009 e 2009/20I0 (quest’ultimo essendo il primo anno in cui, nell’Ateneo di Palermo, ha avuto inizio la riforma dell’ordinamento D.M. 270/04) si sono iscritti a Corsi di Laurea o di Laurea Specialistica appartenenti all’ordinamento D.M. 509/99 devono portare a conclusione il loro percorso didattico entro gli stessi termini previsti per il nuovo ordinamento D.M. 270/04 (il doppio di anni corrispondenti alla durata legale più uno: quindi 7 anni, a partire dall’anno accademico di immatricolazione, per una Laurea, 5 anni per una Laurea Specialistica, 11 anni o 13 anni per una Laurea Specialistica a ciclo unico di durata 5 anni (Architettura, Farmacia, Giurisprudenza) o 6 anni (Medicina e Chirurgia, Odontoiatria);

c) Gli studenti dell’ordinamento D.M. 270/04 (nuovo ordinamento) devono portare a conclusione il loro percorso didattico, come stabilito dall’art.25 del vigente Regolamento Didattico di Ateneo, in un intervallo di tempo pari al massimo al doppio di anni corrispondenti alla durata legale più uno;

d) Gli studenti del Corso di Laurea in “scienze della Formazione Primaria” decadono non appena sono trascorsi otto anni dall’ultimo esame sostenuto.

Il testo completo può essere letto qui http://www.scribd.com/doc/49310072/Decadenza-Studenti-2 o qui

la delibera precendente (del 18 Gennaio 2011) qui

Share Button

gen 05

Esportare tutte le informazioni da Facebook

Ho scoperto assolutamente per caso che Facebook permette di esportare tutte le informazioni pubblicate dall’iscrizione, quindi tutte le note, i messaggi, i post in bacheca, le foto, tutto! la procedura è molto semplice:

Si va su Account|Impostazioni Account e poi alla fine della pagina su Scarica le tue informazioni

La procedura non è immediata… infatti Facebook  ci avviserà per email quando il file sarà pronto e per scaricarlo ci verificherà la nostra identità facendoci riconoscere i nostri amici dalle foto (tralaltro a me ha proposto solo ragazze… che carino).

La FAQ della funzione si trova qui

Ho ritrovato il mio primo post su facebook… allego anche quello:

Il mio primo post su facebook...

Share Button

set 27

Appunti di Go, il Go pietra dopo pietra

Ho aperto un blog su un gioco a cui mi sto appassionando ultimamente, il Go http://go.thedarshan.com/info/

Intendo postare settimanalmente delle lezioni su quello che vado imparando di questo meraviglioso ( e decisamente complicato) gioco da tavola

Share Button

Post precedenti «

» Post successivi