No fakt, przydałoby się raczej jakieś:
if( 0!=singleton ) throw runtime_exception("hej! co robisz?!");
W ogóle to singletona w C++ można zrobić trochę bardziej elegancko:
#include <iostream>
#include <windows.h>
using namespace std;
class ScreenObject {
private:
/* jakieś składowe */
int r,w;
/* blokujemy tworzenie i kopiowanie, konstruktory prywante
więc nikt ich nie wywoła */
ScreenObject() { r=w=0; cout << "hello" << endl; }
ScreenObject(const ScreenObject&);
public:
/* niszczenie niech będzie dostępne, a co tam */
~ScreenObject() { cout << "bye" << endl; }
/* tworzyć nie można konstruktorem, to trzeba tą funkcją */
static ScreenObject& create() {
/* metoda klasy może wołać prywatne rzeczy, m.in konstruktory
w metodzie tworzony jest 1 obiekt, istniejący od momentu
pierwszego wywołania funkcji do zakończenia programu
*/
static ScreenObject instance;
/* nie zwracamy użytkownikowi obiektu, tylko referencję */
return instance;
}
void write() { cout << "writing: " << ++w << endl; }
void read() { cout << "reading: " << ++r << endl; }
};
/* a dobra, kosmetyka, żeby ludzie nie musieli się bawić z &
nasz Screen jest referencją, a nie obiektem, ale na "zewnątrz"
nie trzeba tego ciągle podkreślać
*/
typedef ScreenObject& Screen;
/* A no właśnie, funkcja w stylu Javowym. Przekazujemy argument przez wartość.
Ale argumentem nie jest obiekt, lecz referencja. */
void do_something(Screen s) {
s.read();
s.write();
}
int main() {
/* praktycznie całą robotę: sprawdzenie czy obiekt jest jeden
odwala za nas kompilator */
Screen first = ScreenObject::create();
// Screen second; /* musi być nadana wartość, nie pójdzie */
// ScreenObject third; /* konstruktor prywatny, nie pójdzie */
/* nie tworzymy drugiego ekranu tak naprawdę,
a referencję do już istniejącego */
Screen this_is_not_copy = first;
do_something(first);
do_something(this_is_not_copy);
return 0;
}
Ale to tak na boku, bo singleton to sposób na to, żeby mieć jeden obiekt i tylko jeden. Czyli kontrolujesz ilość kopii danych. Do uruchamiania kodu w tle to ci raczej nie posłuży. Bez wątków raczej się nie obejdzie, ale Ty nie panikuj, bo to naprawdę nie jest jakaś czarna magia (przynajmniej jeśli chodzi o podstawową teorię - praktyka i synchronizacja potrafi dobijać).
Pod Windowsa to piszesz? No miejmy nadzieję, że tak, i że się przyda taki przykład:
#include <iostream>
#include <iomanip>
#include <windows.h>
using namespace std;
bool please_stop = false;
/* To będzie hulało w tle */
DWORD WINAPI some_code(void*) {
cout << "Thread start" << endl;
for(int i=0; i<10; i++) {
Sleep(150);
cout << "A" << i << " " << flush;
/* jakbyśmy chcieli wątek wcześniej zabić */
if(please_stop) break;
}
cout << endl << "Thread end" << endl;
return 0;
}
int main() {
// uruchamiamy kod w tle
DWORD background_id;
HANDLE background = CreateThread(0, 0, some_code, 0, 0, &background_id);
// robimy coś w głównym wątku
for(int i=0; i<10; i++) {
Sleep(100);
cout << "X" << i << " " << flush;
}
// dajemy sygnał, żeby tło się zamknęło
please_stop = true;
cout << endl << "Closing..." << endl;
// czekamy maksymalnie sekundę na tło, żeby się zamkło
DWORD result = WaitForSingleObject(background, 1000);
// jak się zamkło, to super
if( WAIT_OBJECT_0 == result ) {
// zwalniamy klamoty
CloseHandle(background);
cout << endl << "Application end." << endl;
}
else {
// coś poszło nie tak. nie chce nam się dochodzić co.
cout << endl << "Unknown error. Application terminated." << endl;
}
return 0;
}
Dopisane:
A ja głupi jestem. Zobaczyłem w google co to MS TAPI. I ja się zastanawiałem, czy Windows... ;)