Best Timers pentru un Scheduler

Intrebari legate de programarea cu biblioteci precum MFC, ATL, WTL si GDI+.
Post Reply
rdenis
Membru
Membru
Posts: 50
Joined: 10 Apr 2010, 20:16
Judet: Iaşi

Best Timers pentru un Scheduler

Post by rdenis » 11 Aug 2010, 18:52

buna tutoror...am nevoie intr-o aplicatie de un scheduler, mai precis am un NTService care trebuie sa efectueze anumite operatiuni fie la un interval de timp fie la o anumita data. Prima idee care imi venise era sa verifica ora si data din secunda in secunda insa asta inseamna sa-mi "termine" procesorul. Dupa ceva cercetari am gasit informatii despre TIMERS si WM_TIMER event, insa am aflat si ca nu e prea de incredere WM_TIMER asta.
Dupa parerea voastra, cei cu experienta, care ar fi cea mai buna "idee" de implementat intr-un scheduler?

va multumesc,
Denis



neagu_laurentiu
Membru++
Membru++
Posts: 919
Joined: 23 Jul 2007, 11:32

Re: Best Timers pentru un Scheduler

Post by neagu_laurentiu » 11 Aug 2010, 19:57

Daca e pus pe un thread nu vad de ce nu ar merge si cu WM_TIMER.
Insa scheduler-ul din Windows nu-i suficient ?

rdenis
Membru
Membru
Posts: 50
Joined: 10 Apr 2010, 20:16
Judet: Iaşi

Re: Best Timers pentru un Scheduler

Post by rdenis » 11 Aug 2010, 20:45

neagu_laurentiu wrote:Daca e pus pe un thread nu vad de ce nu ar merge si cu WM_TIMER.
din ce am citit nu e vorba daca e pus pe un thread separat sau nu ci daca ajunge in coada de mesaje si cat sta acolo...daca ai vreun articol bun te rog trimite-mi un link...sunt interesat sa citesc :yes:
neagu_laurentiu wrote:Insa scheduler-ul din Windows nu-i suficient ?
nu e o solutie...in primul rand ca user-ul poate sa il aiba pe disable sau dupa cum se stie cu produsele MS, si nu numai, exista oricand posibilitatea sa "crape"

doresc ceva in-house insa nu stiu pe care pista sa ma duc

neagu_laurentiu
Membru++
Membru++
Posts: 919
Joined: 23 Jul 2007, 11:32

Re: Best Timers pentru un Scheduler

Post by neagu_laurentiu » 11 Aug 2010, 21:20

rdenis wrote:ci daca ajunge in coada de mesaje si cat sta acolo
Povestea asta e atunci cand in thread-ul curent faci prelucrari de durata si nu mai apuci sa preiei din coada de mesaje pe altele. Dar daca pe un thread separat ai propria bucla de mesaje si doar astepti WM_TIMER... va veni la timp.

Dragos Cojocari
Membru++
Membru++
Posts: 789
Joined: 11 Jul 2007, 14:11

Re: Best Timers pentru un Scheduler

Post by Dragos Cojocari » 11 Aug 2010, 21:21

rdenis wrote:nu e o solutie...in primul rand ca user-ul poate sa il aiba pe disable sau dupa cum se stie cu produsele MS, si nu numai, exista oricand posibilitatea sa "crape"

doresc ceva in-house insa nu stiu pe care pista sa ma duc
N-or fi MS ai mai breji dar cred ca scheduller-ul lor e mai sigur si de incredere decat o solutie in house . Scheduller-ul asta a vazut multe versiuni de Windows si a fost testat si rastestat.

Dar daca insisti sa faci ceva in house atunci folosirea lui WM_TIMER e cea mai la indemana solutie. Uite aici un exemplu: http://msdn.microsoft.com/en-us/library ... 85%29.aspx

Ti-as sugera sa faci scheduller-ul ala ca o aplicatie Windows cu GUI in prima faza ptr ca iti va simplifica mult dezvoltarea si testarea solutiei. Odata ce ai finalizat asta poti impacheta codul intr-un NT Service.

rdenis
Membru
Membru
Posts: 50
Joined: 10 Apr 2010, 20:16
Judet: Iaşi

Re: Best Timers pentru un Scheduler

Post by rdenis » 11 Aug 2010, 21:51

ma gandeam sa introduc tot codul de scheduling intr-un .dll care apoi sa fie actionat de nt service...WM_TIMER va trebui rulat doar intr-un thread separat pentru a nu-mi bloca interfata, corect?
ce stiti despre queue timers? ar fi o solutie viabila?ati mai lucrat cu acesti timers

neagu_laurentiu
Membru++
Membru++
Posts: 919
Joined: 23 Jul 2007, 11:32

Re: Best Timers pentru un Scheduler

Post by neagu_laurentiu » 11 Aug 2010, 22:03

Pui problema de parca vrei la milisecunda X sa declansezi bomba nucleara :)
Toate vor merge la fel. Nu vei avea abateri mai mari de 10ms.

User avatar
MrSmersh
Microsoft MVP
Microsoft MVP
Posts: 289
Joined: 20 Jul 2007, 10:18
Location: Timisoara
Contact:

Re: Best Timers pentru un Scheduler

Post by MrSmersh » 11 Aug 2010, 22:31

Acuma ma intrebam si eu, daca userul umbla la scheduler, ce il opreste sa opreasca serviciul? Ca preferinta personala nu imi place sa reinventez roata, de crapat toate pot crapa...
Da, teoretic la serviciu pot sa ii zic sa is dea restart, dar daca a crapat in primul rind posibil sa o mai faca la restart .

User avatar
cristianamarie
Membru++
Membru++
Posts: 480
Joined: 12 Mar 2009, 18:47
Judet: Iaşi
Location: Iasi

Re: Best Timers pentru un Scheduler

Post by cristianamarie » 12 Aug 2010, 08:45

Service cu WM_TIMER (trecem peste RegisterServiceCtrlHandler si initializari).
Dau paste dintr-un proiect la care lucrez (ignora cine e ifsvc - e o structura C care contine fptrs si variabile, analog cu o clasa C++ sa zicem - urmareste logica si API calls):

1. Armarea timerului. E chemat cu NULL HWND si cu non-NULL callback (ifsvc_fldpollproc)

Code: Select all

	//	prepare folder timer
		//	how many folders, are, no matter, all polling uses the same timer
	ifsvc->timerid = SetTimer(NULL, 0, ifsvc->elapse * 1000, ifsvc_fldpollproc);
	if(ifsvc->timerid == 0) {
		ifsvc->log(ifsvc, "  ifsvc_run SetTimer failed");
	}
2. Worker loop

Code: Select all

	// The worker loop of service
#pragma warning(disable:4127)
	while (1) {
#pragma warning(default:4127)

		BOOL r;
		MSG msg = {0};

		if(ifsvc->end_loop != 0) {
			ifsvc->log(ifsvc, "  ifsvc_run ifsvc->end_loop is now != 0, killing timer and exit loop");
			if(KillTimer(NULL, ifsvc->timerid)) {
				ifsvc->log(ifsvc, "  ifsvc_run KillTimer succeeded");
				ifsvc->timerid = 0;
			}
			else {
				ifsvc->log(ifsvc, "  ifsvc_run KillTimer failed");
			}
			break;
		}

		if(!ifsvc->end_loop
			&& PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)
		) {
			r = GetMessage(&msg, NULL, 0, 0);
			if(r == -1) {
				break;
			}
			if(r == 0) {
				ifsvc->end_loop = 1;
			}

			DispatchMessage(&msg);
		}
	}

	ifsvc->log(ifsvc, "<< ifsvc_run");
2. Timer callback procedure

Code: Select all

static
VOID CALLBACK
ifsvc_fldpollproc(
	HWND hwnd, 
	UINT msg, 
	UINT_PTR id, 
	DWORD time
) {
	struct ifsvc* ifsvc = get_ifsvc();

	OutputDebugStringA("ifsvcd: ifsvc_fldpollproc");
	ifsvc->fldpoll(ifsvc);
	return;
	__unused__(hwnd);
	__unused__(msg);
	__unused__(id);
	__unused__(time);
}
Acum in fldpoll poti colecta ce ai nevoie la momentul asta si face spawn la un worker thread care face ce trebuie. Threadul principal doar sta la WM_TIMER si iti cheama callback-ul fldpollproc.
Si mai bine e sa ai, poate, ca main thread doar sa puna intr-o coada un nou element (new thread requests), si de acolo un al doilea thread (dispatcher) detecteaza noul element si EL face spawn la worker.
Deci ai avea:
- 1 main thread: WM_TIMER si append la colectia de requests (de fapt main thread sint... 2, unul de la SCM si unul al tau armat de StartServiceControlDispatcher)
- 1 dispatcher thread: citeste colectia de requests si creeaza worker threads pe masura ce apar noi requests, cu o limita superioara de workers
- [0..MAX_WORKER - 1] worker thread: facatorii de treburi :)
si IPC eventual intre ele (cel putin la shutdown ar trebui cleanup/stop la workers, stop dispatcher, si exit main thread).

Daca e (ca in cazul meu) doar un apel posibil la un moment dat, atunci callback-ul pur si simplu seteaza un kernel object (daca e deja setat, iese si lasa call-ul curent sa termine si atit). In cazul meu fldpollproc e un scanator pe niste foldere (fld - folder, poll - polling) si n-are sens sa am doua executate concurent. Sa zicem, ca un exemplu standard, un Windows update e single instance.

Daca ai nevoie de mai multe in paralel, mai trebuie, probabil, sa implementezi tu un mecanism unde tii worker threads si starile lor (eventual un max_worker_thread ca sa nu mai faca inca un CreateThread daca ai atins limita de sus, sa mentii colectia de threads data cind un thread se termina, events bidirectionale din/spre main thread pentru IPC si tot ce mai ai nevoie - dar asta deja e alta discutie).
Nuclear launch detected

User avatar
cristianamarie
Membru++
Membru++
Posts: 480
Joined: 12 Mar 2009, 18:47
Judet: Iaşi
Location: Iasi

Re: Best Timers pentru un Scheduler

Post by cristianamarie » 12 Aug 2010, 08:53

Daca WM_TIMER - din varii motive - nu e suficient de precis (55 milisecunde daca mai tin bine minte e cam limita).
Multimedia timers par a fi pe la 10 msec; cauta timeGetTime si de aici mai gasesti referinte. Din pacate e DWORD si sufera ca si GetTickCount, deci un service care o sa ruleze mult timp o sa fie probabil afectat daca nu are un reset la limita de 49.71 de zile.

Pentru high resolution timers ai nevoie de performance counters. In principal de QueryPerformanceCounter si QueryPerformanceFrequency.
Aici deja vorbim de microsecunde, nemaivorbind ca treaba e 64-bit, nu 32.
Citat:
"On a 2 GHz processor, a call to QueryPerformanceCounter takes about five microseconds.
Still, that's much better than what you can get from timeGetTime, and quite useful for games and other high-resolution timing needs."

Un exemplu ai aici: http://cplus.about.com/od/howtodothingsi2/a/timing.htm
Nu stiu cit de bun e ca nu l-am testat, dar pare destul de civilizat, si oricum e un starting point bun.

Mai multe sint pe aici:
http://msdn.microsoft.com/en-us/magazine/cc163996.aspx
http://www.decompile.com/cpp/faq/windows_timer_api.htm
http://www.devsource.com/c/a/Techniques ... r-Windows/
http://cplus.about.com/od/howtodothingsi2/a/timing.htm
Nuclear launch detected

User avatar
cristianamarie
Membru++
Membru++
Posts: 480
Joined: 12 Mar 2009, 18:47
Judet: Iaşi
Location: Iasi

Re: Best Timers pentru un Scheduler

Post by cristianamarie » 12 Aug 2010, 08:57

Poate interesant ar fi si un NtQuerySystemInformation cu SystemTimeOfDayInformation, care intoarce o structura SYSTEM_TIMEOFDAY_INFORMATION.
Totul e undocumented, in Win DDK probabil gasesti.
Oricum, structura e

Code: Select all

typedef struct _SYSTEM_TIMEOFDAY_INFORMATION
{
    LARGE_INTEGER BootTime;
    LARGE_INTEGER CurrentTime;
    LARGE_INTEGER TimeZoneBias;
    ULONG CurrentTimeZoneId;
} 
SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION;
Mai multe aici: http://wookey.org/currentuptime.html
Nu stiu cit de precisa e treaba, dar ma gindesc ca o functie care incepe cu NtXXX trebe sa fie mai precisa decit un WM_TIMER.
Nuclear launch detected

rdenis
Membru
Membru
Posts: 50
Joined: 10 Apr 2010, 20:16
Judet: Iaşi

Re: Best Timers pentru un Scheduler

Post by rdenis » 12 Aug 2010, 11:57

multumesc tuturor de raspunsuri....voi incerca pontul tau cristianamarie...e o idee foarte buna si cred ca o sa mearga bine...schedulerul il folosesc la un program de tip backup asa ca nu imi trebuie o rezolutie prea mare ci doar sa porneasca task-ul la momentul selectat de user...

User avatar
cristianamarie
Membru++
Membru++
Posts: 480
Joined: 12 Mar 2009, 18:47
Judet: Iaşi
Location: Iasi

Re: Best Timers pentru un Scheduler

Post by cristianamarie » 13 Aug 2010, 09:04

Pentru backup nu stiu daca este API, dar ai putea sa folosesti VSS (volume shadow...), ntbackup.exe, cel din Control Panel, desi e cam ceata.
Alternativ poate ai putea folosi setup API (nu e prea pentru backup, dar are alte avantaje), sau COM streams unde ai putea replica structura de backup. Dar deja e terenul tau aici :)
Nuclear launch detected

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Best Timers pentru un Scheduler

Post by Ovidiu Cucu » 15 Aug 2010, 22:01

Eu as arunca totusi um ochi pe la waitable timer.

Post Reply